cuelang.org/go@v0.10.1/internal/golangorgx/tools/gocommand/version.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gocommand 6 7 import ( 8 "context" 9 "fmt" 10 "regexp" 11 "strings" 12 ) 13 14 // GoVersion reports the minor version number of the highest release 15 // tag built into the go command on the PATH. 16 // 17 // Note that this may be higher than the version of the go tool used 18 // to build this application, and thus the versions of the standard 19 // go/{scanner,parser,ast,types} packages that are linked into it. 20 // In that case, callers should either downgrade to the version of 21 // go used to build the application, or report an error that the 22 // application is too old to use the go command on the PATH. 23 func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) { 24 inv.Verb = "list" 25 inv.Args = []string{"-e", "-f", `{{context.ReleaseTags}}`, `--`, `unsafe`} 26 inv.BuildFlags = nil // This is not a build command. 27 inv.ModFlag = "" 28 inv.ModFile = "" 29 inv.Env = append(inv.Env[:len(inv.Env):len(inv.Env)], "GO111MODULE=off") 30 31 stdoutBytes, err := r.Run(ctx, inv) 32 if err != nil { 33 return 0, err 34 } 35 stdout := stdoutBytes.String() 36 if len(stdout) < 3 { 37 return 0, fmt.Errorf("bad ReleaseTags output: %q", stdout) 38 } 39 // Split up "[go1.1 go1.15]" and return highest go1.X value. 40 tags := strings.Fields(stdout[1 : len(stdout)-2]) 41 for i := len(tags) - 1; i >= 0; i-- { 42 var version int 43 if _, err := fmt.Sscanf(tags[i], "go1.%d", &version); err != nil { 44 continue 45 } 46 return version, nil 47 } 48 return 0, fmt.Errorf("no parseable ReleaseTags in %v", tags) 49 } 50 51 // GoVersionOutput returns the complete output of the go version command. 52 func GoVersionOutput(ctx context.Context, inv Invocation, r *Runner) (string, error) { 53 inv.Verb = "version" 54 goVersion, err := r.Run(ctx, inv) 55 if err != nil { 56 return "", err 57 } 58 return goVersion.String(), nil 59 } 60 61 // ParseGoVersionOutput extracts the Go version string 62 // from the output of the "go version" command. 63 // Given an unrecognized form, it returns an empty string. 64 func ParseGoVersionOutput(data string) string { 65 re := regexp.MustCompile(`^go version (go\S+|devel \S+)`) 66 m := re.FindStringSubmatch(data) 67 if len(m) != 2 { 68 return "" // unrecognized version 69 } 70 return m[1] 71 }