Skip to content

Commit

Permalink
go_register_toolchains: improve version string parsing and comparison (
Browse files Browse the repository at this point in the history
  • Loading branch information
Jay Conrod committed Dec 2, 2020
1 parent bd1f492 commit 694c23a
Showing 1 changed file with 71 additions and 14 deletions.
85 changes: 71 additions & 14 deletions go/private/sdk.bzl
Expand Up @@ -24,12 +24,8 @@ load(
"//go/private:platforms.bzl",
"generate_toolchain_names",
)
load(
"//go/private/skylib/lib:versions.bzl",
"versions",
)

MIN_SUPPORTED_VERSION = "1.14"
MIN_SUPPORTED_VERSION = (1, 14, 0)

def _go_host_sdk_impl(ctx):
goroot = _detect_host_sdk(ctx)
Expand Down Expand Up @@ -85,15 +81,17 @@ def _go_download_sdk_impl(ctx):
if not version:
highest_version = None
for v in sdks_by_version.keys():
sv = versions.parse(v)
if v != ".".join([str(d) for d in sv]):
# skip pre-release versions
pv = _parse_version(v)
if not pv or _version_is_prerelease(pv):
# skip parse errors and pre-release versions
continue
if not highest_version or sv > highest_version:
highest_version = sv
if not highest_version or _version_less(highest_version, pv):
highest_version = pv
if not highest_version:
fail("did not find any Go versions in https://golang.org/dl/?mode=json")
version = ".".join([str(d) for d in highest_version])
version = _version_string(highest_version)
if version not in sdks_by_version:
fail("did not find version {} in https://golang.org/dl/?mode=json".format(version))
sdks = sdks_by_version[version]

if platform not in sdks:
Expand Down Expand Up @@ -335,6 +333,62 @@ def _parse_versions_json_field(line):
return "", ""
return k[1:], v[:-1]

def _parse_version(version):
"""Parses a version string like "1.15.5" and returns a tuple of numbers or None"""
l, r = 0, 0
parsed = []
for c in version.elems():
if c == ".":
if l == r:
# empty component
return None
parsed.append(int(version[l:r]))
r += 1
l = r
continue

if c.isdigit():
r += 1
continue

# pre-release suffix
break

if l == r:
# empty component
return None
parsed.append(int(version[l:r]))
if len(parsed) == 2:
# first minor version, like (1, 15)
parsed.append(0)
if len(parsed) != 3:
# too many or too few components
return None
if r < len(version):
# pre-release suffix
parsed.append(version[r:])
return tuple(parsed)

def _version_is_prerelease(v):
return len(v) > 3

def _version_less(a, b):
if a[:3] < b[:3]:
return True
if a[:3] > b[:3]:
return False
if len(a) > len(b):
return True
if len(a) < len(b) or len(a) == 3:
return False
return a[3:] < b[3:]

def _version_string(v):
suffix = v[3] if _version_is_prerelease(v) else ""
if v[-1] == 0:
v = v[:-1]
return ".".join([str(n) for n in v]) + suffix

def go_register_toolchains(version = None, nogo = None, go_version = None):
"""See /go/toolchains.rst#go-register-toolchains for full documentation."""
if not version:
Expand All @@ -351,12 +405,15 @@ def go_register_toolchains(version = None, nogo = None, go_version = None):
fail("go_register_toolchains: version set after go sdk rule declared ({})".format(", ".join([r["name"] for r in sdk_rules])))
if len(sdk_rules) == 0:
if not version:
fail('go_register_toolchains: version must be set to a string like "1.15.5" or "host"')
fail('go_register_toolchains: version must be a string like "1.15.5" or "host"')
elif version == "host":
go_host_sdk(name = "go_sdk")
else:
if not versions.is_at_least(MIN_SUPPORTED_VERSION, version):
print("DEPRECATED: Go versions before {} are not supported and may not work".format(MIN_SUPPORTED_VERSION))
pv = _parse_version(version)
if not pv:
fail('go_register_toolchains: version must be a string like "1.15.5" or "host"')
if _version_less(pv, MIN_SUPPORTED_VERSION):
print("DEPRECATED: Go versions before {} are not supported and may not work".format(_version_string(MIN_SUPPORTED_VERSION)))
go_download_sdk(
name = "go_sdk",
version = version,
Expand Down

0 comments on commit 694c23a

Please sign in to comment.