Skip to content

Commit 280120e

Browse files
committed
Fix version checks to support rust >= 1.100.0
1 parent 3038b62 commit 280120e

File tree

5 files changed

+198
-5
lines changed

5 files changed

+198
-5
lines changed

rust/private/repository_utils.bzl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ load(
1414
"system_to_staticlib_ext",
1515
"system_to_stdlib_linkflags",
1616
)
17-
load("//rust/private:common.bzl", "DEFAULT_NIGHTLY_ISO_DATE")
17+
load(":common.bzl", "DEFAULT_NIGHTLY_ISO_DATE")
18+
load(":semver.bzl", "semver")
1819

1920
DEFAULT_TOOLCHAIN_NAME_PREFIX = "toolchain_for"
2021
DEFAULT_STATIC_RUST_URL_TEMPLATES = ["https://static.rust-lang.org/dist/{}.tar.xz"]
@@ -550,9 +551,13 @@ def includes_rust_analyzer_proc_macro_srv(version, iso_date):
550551

551552
if version == "nightly":
552553
return iso_date >= "2022-09-21"
553-
elif version == "beta":
554+
555+
if version == "beta":
554556
return False
555-
elif version >= "1.64.0":
557+
558+
# version >= 1.64.0
559+
version_semver = semver(version)
560+
if version_semver.major >= 1 and version_semver.minor >= 64:
556561
return True
557562

558563
return False

rust/private/semver.bzl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Semver"""
2+
3+
def semver(version):
4+
"""Constructs a struct containing separated sections of a semantic version value.
5+
6+
Args:
7+
version (str): The semver value.
8+
9+
Returns:
10+
struct:
11+
- major (int): The semver's major component. E.g. `1` from `1.2.3`
12+
- minor (int): The semver's minor component. E.g. `2` from `1.2.3`
13+
- patch (int): The semver's patch component. E.g. `3` from `1.2.3`
14+
- pre (optional str): The semver's pre component. E.g. `rc4` from `1.2.3-rc4` or None if absent.
15+
- str (str): The full string value of the semver.
16+
"""
17+
parts = version.split(".", 2)
18+
if len(parts) < 3:
19+
fail("Unexpected number of parts for semver value: {}".format(version))
20+
21+
major = parts[0]
22+
minor = parts[1]
23+
patch, split, pre = parts[2].partition("-")
24+
if not split:
25+
pre = None
26+
27+
return struct(
28+
major = int(major),
29+
minor = int(minor),
30+
patch = int(patch),
31+
pre = pre,
32+
str = version,
33+
)

rust/repositories.bzl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ load(
3535
"toolchain_repository_hub",
3636
_load_arbitrary_tool = "load_arbitrary_tool",
3737
)
38+
load("//rust/private:semver.bzl", "semver")
3839

3940
# Re-export `load_arbitrary_tool` as it's historically been used in external repositories.
4041
load_arbitrary_tool = _load_arbitrary_tool
@@ -422,6 +423,19 @@ _RUST_TOOLCHAIN_REPOSITORY_ATTRS = {
422423
),
423424
}
424425

426+
def _include_llvm_tools(version, iso_date):
427+
"""Rust 1.45.0 and nightly builds after 2020-05-22 need the llvm-tools gzip to get the libLLVM dylib"""
428+
if version in ("nightly", "beta"):
429+
if iso_date > "2020-05-22":
430+
return True
431+
return False
432+
433+
version_semver = semver(version)
434+
if version_semver.major >= 1 and version_semver.minor >= 45:
435+
return True
436+
437+
return False
438+
425439
def _rust_toolchain_tools_repository_impl(ctx):
426440
"""The implementation of the rust toolchain tools repository rule."""
427441
sha256s = dict(ctx.attr.sha256s)
@@ -483,8 +497,7 @@ def _rust_toolchain_tools_repository_impl(ctx):
483497
build_components.append(rustfmt_content)
484498
sha256s.update(rustfmt_sha256)
485499

486-
# Rust 1.45.0 and nightly builds after 2020-05-22 need the llvm-tools gzip to get the libLLVM dylib
487-
include_llvm_tools = version >= "1.45.0" or (version == "nightly" and iso_date > "2020-05-22")
500+
include_llvm_tools = _include_llvm_tools(version, iso_date)
488501
if include_llvm_tools:
489502
llvm_tools_content, llvm_tools_sha256 = load_llvm_tools(
490503
ctx = ctx,

test/unit/semver/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
load(":semver_test.bzl", "semver_test_suite")
2+
3+
semver_test_suite(name = "semver_test_suite")

test/unit/semver/semver_test.bzl

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
"""Unit tests for semver.bzl."""
2+
3+
load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
4+
5+
# buildifier: disable=bzl-visibility
6+
load("//rust/private:semver.bzl", "semver")
7+
8+
def _semver_basic_test_impl(ctx):
9+
env = unittest.begin(ctx)
10+
11+
# Test basic semver parsing
12+
result = semver("1.2.3")
13+
asserts.equals(env, 1, result.major)
14+
asserts.equals(env, 2, result.minor)
15+
asserts.equals(env, 3, result.patch)
16+
asserts.equals(env, None, result.pre)
17+
asserts.equals(env, "1.2.3", result.str)
18+
19+
# Test with zeros
20+
result = semver("0.0.0")
21+
asserts.equals(env, 0, result.major)
22+
asserts.equals(env, 0, result.minor)
23+
asserts.equals(env, 0, result.patch)
24+
asserts.equals(env, None, result.pre)
25+
asserts.equals(env, "0.0.0", result.str)
26+
27+
# Test larger version numbers
28+
result = semver("10.20.30")
29+
asserts.equals(env, 10, result.major)
30+
asserts.equals(env, 20, result.minor)
31+
asserts.equals(env, 30, result.patch)
32+
asserts.equals(env, None, result.pre)
33+
asserts.equals(env, "10.20.30", result.str)
34+
35+
return unittest.end(env)
36+
37+
def _semver_with_pre_test_impl(ctx):
38+
env = unittest.begin(ctx)
39+
40+
# Test semver with pre-release
41+
result = semver("1.2.3-rc4")
42+
asserts.equals(env, 1, result.major)
43+
asserts.equals(env, 2, result.minor)
44+
asserts.equals(env, 3, result.patch)
45+
asserts.equals(env, "rc4", result.pre)
46+
asserts.equals(env, "1.2.3-rc4", result.str)
47+
48+
# Test semver with alpha pre-release
49+
result = semver("2.0.0-alpha")
50+
asserts.equals(env, 2, result.major)
51+
asserts.equals(env, 0, result.minor)
52+
asserts.equals(env, 0, result.patch)
53+
asserts.equals(env, "alpha", result.pre)
54+
asserts.equals(env, "2.0.0-alpha", result.str)
55+
56+
# Test semver with beta pre-release
57+
result = semver("1.5.0-beta.1")
58+
asserts.equals(env, 1, result.major)
59+
asserts.equals(env, 5, result.minor)
60+
asserts.equals(env, 0, result.patch)
61+
asserts.equals(env, "beta.1", result.pre)
62+
asserts.equals(env, "1.5.0-beta.1", result.str)
63+
64+
# Test semver with nightly pre-release
65+
result = semver("1.70.0-nightly")
66+
asserts.equals(env, 1, result.major)
67+
asserts.equals(env, 70, result.minor)
68+
asserts.equals(env, 0, result.patch)
69+
asserts.equals(env, "nightly", result.pre)
70+
asserts.equals(env, "1.70.0-nightly", result.str)
71+
72+
return unittest.end(env)
73+
74+
def _semver_edge_cases_test_impl(ctx):
75+
env = unittest.begin(ctx)
76+
77+
# Test semver with empty pre-release (trailing dash)
78+
# When there's a trailing dash, partition returns empty string for pre,
79+
# but "pre or None" converts it to None
80+
result = semver("1.2.3-")
81+
asserts.equals(env, 1, result.major)
82+
asserts.equals(env, 2, result.minor)
83+
asserts.equals(env, 3, result.patch)
84+
asserts.equals(env, "", result.pre)
85+
asserts.equals(env, "1.2.3-", result.str)
86+
87+
# Test semver with multiple dashes in pre-release
88+
result = semver("1.2.3-alpha-test")
89+
asserts.equals(env, 1, result.major)
90+
asserts.equals(env, 2, result.minor)
91+
asserts.equals(env, 3, result.patch)
92+
asserts.equals(env, "alpha-test", result.pre)
93+
asserts.equals(env, "1.2.3-alpha-test", result.str)
94+
95+
return unittest.end(env)
96+
97+
def _semver_real_world_examples_test_impl(ctx):
98+
env = unittest.begin(ctx)
99+
100+
# Test real Rust version examples
101+
result = semver("1.80.0")
102+
asserts.equals(env, 1, result.major)
103+
asserts.equals(env, 80, result.minor)
104+
asserts.equals(env, 0, result.patch)
105+
asserts.equals(env, None, result.pre)
106+
asserts.equals(env, "1.80.0", result.str)
107+
108+
result = semver("1.70.0")
109+
asserts.equals(env, 1, result.major)
110+
asserts.equals(env, 70, result.minor)
111+
asserts.equals(env, 0, result.patch)
112+
asserts.equals(env, None, result.pre)
113+
114+
result = semver("1.54.0")
115+
asserts.equals(env, 1, result.major)
116+
asserts.equals(env, 54, result.minor)
117+
asserts.equals(env, 0, result.patch)
118+
asserts.equals(env, None, result.pre)
119+
120+
return unittest.end(env)
121+
122+
semver_basic_test = unittest.make(_semver_basic_test_impl)
123+
semver_with_pre_test = unittest.make(_semver_with_pre_test_impl)
124+
semver_edge_cases_test = unittest.make(_semver_edge_cases_test_impl)
125+
semver_real_world_examples_test = unittest.make(_semver_real_world_examples_test_impl)
126+
127+
def semver_test_suite(name):
128+
"""Entry-point macro called from the BUILD file.
129+
130+
Args:
131+
name (str): Name of the test suite.
132+
"""
133+
unittest.suite(
134+
name,
135+
semver_basic_test,
136+
semver_with_pre_test,
137+
semver_edge_cases_test,
138+
semver_real_world_examples_test,
139+
)

0 commit comments

Comments
 (0)