goversion: parse version for development builds (#3837)

Once upon a time Go version strings for development builds did not
reference the major/minor version they belonged to, therefore the best
we could do was to always assume that a development build belonged to
the most recently released version of Go.

This commit changes pkg/goversion so that the new style of development
version string is fully parsed.
This commit is contained in:
Alessandro Arzilli 2024-10-21 18:15:02 +02:00 committed by GitHub
parent 064ef226ca
commit 1a9bd03d7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 42 additions and 16 deletions

@ -21,7 +21,7 @@ var (
// this version of delve.
func Compatible(producer string, warnonly bool) error {
ver := ParseProducer(producer)
if ver.IsDevel() {
if ver.IsOldDevel() {
return nil
}
if !ver.AfterOrEqual(GoVersion{MinSupportedVersionOfGoMajor, MinSupportedVersionOfGoMinor, betaRev(0), "", ""}) {

@ -19,8 +19,9 @@ type GoVersion struct {
}
const (
betaStart = -1000
betaEnd = -2000
betaStart = -1000
betaEnd = -2000
versionedDevel = -3000
)
func betaRev(beta int) int {
@ -40,8 +41,27 @@ func Parse(ver string) (GoVersion, bool) {
var r GoVersion
var err1, err2, err3 error
if strings.HasPrefix(ver, "devel") {
return GoVersion{-1, 0, 0, "", ""}, true
const devel = "devel"
if strings.HasPrefix(ver, devel) {
ver = strings.TrimSpace(ver[len(devel):])
if !strings.HasPrefix(ver, "go") {
// old development build: devel +COMMIT DATE ARCH
return GoVersion{-1, 0, 0, "", ""}, true
}
// new development build: devel goX.Y-COMMIT DATE ARCH
ver = strings.Split(ver[2:], "-")[0]
v := strings.SplitN(ver, ".", 2)
if len(v) != 2 {
return GoVersion{-1, 0, 0, "", ""}, true
}
major, err1 := strconv.Atoi(v[0])
minor, err2 := strconv.Atoi(v[1])
if err1 != nil || err2 != nil {
return GoVersion{-1, 0, 0, "", ""}, true
}
return GoVersion{major, minor, versionedDevel, "", ""}, true
}
if strings.HasPrefix(ver, "go") {
@ -159,12 +179,17 @@ func (v *GoVersion) AfterOrEqual(b GoVersion) bool {
return true
}
// IsDevel returns whether the GoVersion
// is a development version.
func (v *GoVersion) IsDevel() bool {
// IsOldDevel returns whether the GoVersion is an old-style development
// build of Go, i.e. without an associated minor and major version.
func (v *GoVersion) IsOldDevel() bool {
return v.Major < 0
}
// IsDevelBuild returns whether the GoVersion is a development build
func (v *GoVersion) IsDevelBuild() bool {
return v.Major < 0 || v.Rev == versionedDevel
}
func (v *GoVersion) String() string {
switch {
case v.Rev < betaStart:
@ -209,7 +234,7 @@ func Installed() (GoVersion, bool) {
// or go version) is major.minor or a later version, or a development
// version.
func VersionAfterOrEqual(version string, major, minor int) bool {
return VersionAfterOrEqualRev(version, major, minor, betaEnd)
return VersionAfterOrEqualRev(version, major, minor, versionedDevel)
}
// VersionAfterOrEqualRev checks that version (as returned by runtime.Version()
@ -217,7 +242,7 @@ func VersionAfterOrEqual(version string, major, minor int) bool {
// version.
func VersionAfterOrEqualRev(version string, major, minor, rev int) bool {
ver, _ := Parse(version)
if ver.IsDevel() {
if ver.IsOldDevel() {
return true
}
return ver.AfterOrEqual(GoVersion{major, minor, rev, "", ""})
@ -229,7 +254,7 @@ const producerVersionPrefix = "Go cmd/compile "
// major.minor or a later version, or a development version.
func ProducerAfterOrEqual(producer string, major, minor int) bool {
ver := ParseProducer(producer)
if ver.IsDevel() {
if ver.IsOldDevel() {
return true
}
return ver.AfterOrEqual(GoVersion{major, minor, 0, "", ""})

@ -54,7 +54,7 @@ func TestParseVersionStringAfterOrEqual(t *testing.T) {
if !ok {
t.Fatalf("Could not parse devel version string")
}
if !ver.IsDevel() {
if !ver.IsOldDevel() {
t.Fatalf("Devel version string not correctly recognized")
}
@ -77,6 +77,7 @@ func TestParseVersionStringEqual(t *testing.T) {
versionEqual(t, "go1.16.4b7", GoVersion{1, 16, 4, "", ""})
versionEqual(t, "go1.21.1-something", GoVersion{1, 21, 1, "", "something"})
versionEqual(t, "devel +17efbfc Tue Jul 28 17:39:19 2015 +0000 linux/amd64", GoVersion{Major: -1})
versionEqual(t, "devel go1.24-1bb6f19a25 Mon Oct 14 15:17:20 2024 -0400 linux/amd64", GoVersion{1, 24, versionedDevel, "", ""})
}
func TestRoundtrip(t *testing.T) {

@ -2081,7 +2081,7 @@ func (bi *BinaryInfo) macOSDebugFrameBugWorkaround() {
}
} else {
prod := goversion.ParseProducer(bi.Producer())
if !prod.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 19, Rev: 3}) && !prod.IsDevel() {
if !prod.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 19, Rev: 3}) && !prod.IsOldDevel() {
bi.logger.Infof("debug_frame workaround not needed (version %q on %s)", bi.Producer(), bi.Arch.Name)
return
}

@ -2780,7 +2780,7 @@ func TestDebugStripped(t *testing.T) {
skipOn(t, "not working on linux/386", "linux", "386")
skipOn(t, "not working on linux/ppc64le when -gcflags=-N -l is passed", "linux", "ppc64le")
ver, _ := goversion.Parse(runtime.Version())
if ver.IsDevel() {
if ver.IsDevelBuild() {
t.Skip("not supported")
}
withTestProcessArgs("testnextprog", t, "", []string{}, protest.LinkStrip, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
@ -2810,7 +2810,7 @@ func TestDebugStripped2(t *testing.T) {
skipOn(t, "not working on linux/ppc64le when -gcflags=-N -l is passed", "linux", "ppc64le")
skipOn(t, "not working on linux/riscv64", "linux", "riscv64")
ver, _ := goversion.Parse(runtime.Version())
if ver.IsDevel() {
if ver.IsDevelBuild() {
t.Skip("not supported")
}
if ver.Major > 0 && ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 22, Rev: -1}) {

@ -158,7 +158,7 @@ func BuildFixture(name string, flags BuildFlags) Fixture {
if flags&BuildModeExternalLinker != 0 {
buildFlags = append(buildFlags, "-ldflags=-linkmode=external")
}
if ver.IsDevel() || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 11, Rev: -1}) {
if ver.IsOldDevel() || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 11, Rev: -1}) {
if flags&EnableDWZCompression != 0 {
buildFlags = append(buildFlags, "-ldflags=-compressdwarf=false")
}