diff --git a/app/app.go b/app/app.go index 22bb81b66d..52e129fac3 100644 --- a/app/app.go +++ b/app/app.go @@ -4,7 +4,6 @@ package app // import "fyne.io/fyne/v2/app" import ( - "os/exec" "strconv" "sync" "time" @@ -14,6 +13,8 @@ import ( "fyne.io/fyne/v2/internal/app" intRepo "fyne.io/fyne/v2/internal/repository" "fyne.io/fyne/v2/storage/repository" + + "golang.org/x/sys/execabs" ) // Declare conformity with App interface @@ -31,7 +32,7 @@ type fyneApp struct { running bool runMutex sync.Mutex - exec func(name string, arg ...string) *exec.Cmd + exec func(name string, arg ...string) *execabs.Cmd } func (a *fyneApp) Icon() fyne.Resource { @@ -111,7 +112,7 @@ func New() fyne.App { } func newAppWithDriver(d fyne.Driver, id string) fyne.App { - newApp := &fyneApp{uniqueID: id, driver: d, exec: exec.Command, lifecycle: &app.Lifecycle{}} + newApp := &fyneApp{uniqueID: id, driver: d, exec: execabs.Command, lifecycle: &app.Lifecycle{}} fyne.SetCurrentApp(newApp) newApp.prefs = newPreferences(newApp) diff --git a/app/app_darwin.go b/app/app_darwin.go index 57b3c8ae38..bca7a56726 100644 --- a/app/app_darwin.go +++ b/app/app_darwin.go @@ -20,13 +20,14 @@ import ( "fmt" "net/url" "os" - "os/exec" "path/filepath" "strings" "unsafe" "fyne.io/fyne/v2" "fyne.io/fyne/v2/theme" + + "golang.org/x/sys/execabs" ) func defaultVariant() fyne.ThemeVariant { @@ -65,7 +66,7 @@ func (a *fyneApp) SendNotification(n *fyne.Notification) { template := `display notification "%s" with title "%s"` script := fmt.Sprintf(template, content, title) - err := exec.Command("osascript", "-e", script).Start() + err := execabs.Command("osascript", "-e", script).Start() if err != nil { fyne.LogError("Failed to launch darwin notify script", err) } diff --git a/app/app_test.go b/app/app_test.go index 156ba93124..df31672785 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -2,13 +2,14 @@ package app import ( "net/url" - "os/exec" "strings" "testing" "fyne.io/fyne/v2" _ "fyne.io/fyne/v2/test" "github.com/stretchr/testify/assert" + + "golang.org/x/sys/execabs" ) func TestDummyApp(t *testing.T) { @@ -33,9 +34,9 @@ func TestFyneApp_UniqueID(t *testing.T) { func TestFyneApp_OpenURL(t *testing.T) { opened := "" app := NewWithID("io.fyne.test") - app.(*fyneApp).exec = func(cmd string, arg ...string) *exec.Cmd { + app.(*fyneApp).exec = func(cmd string, arg ...string) *execabs.Cmd { opened = arg[len(arg)-1] - return exec.Command("") + return execabs.Command("") } urlStr := "https://fyne.io" diff --git a/app/app_windows.go b/app/app_windows.go index 6ab2d3a485..25d67fb4bd 100644 --- a/app/app_windows.go +++ b/app/app_windows.go @@ -9,7 +9,6 @@ import ( "io/ioutil" "net/url" "os" - "os/exec" "path/filepath" "strings" "syscall" @@ -18,6 +17,8 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/theme" + + "golang.org/x/sys/execabs" ) const notificationTemplate = `$title = "%s" @@ -102,7 +103,7 @@ func runScript(name, script string) { defer os.Remove(tmpFilePath) launch := "(Get-Content -Encoding UTF8 -Path " + tmpFilePath + " -Raw) | Invoke-Expression" - cmd := exec.Command("PowerShell", "-ExecutionPolicy", "Bypass", launch) + cmd := execabs.Command("PowerShell", "-ExecutionPolicy", "Bypass", launch) cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} err = cmd.Run() if err != nil { diff --git a/cmd/fyne/internal/commands/build.go b/cmd/fyne/internal/commands/build.go index c6555d4b82..4a1bc4b483 100644 --- a/cmd/fyne/internal/commands/build.go +++ b/cmd/fyne/internal/commands/build.go @@ -3,9 +3,10 @@ package commands import ( "fmt" "os" - "os/exec" "runtime" "strings" + + "golang.org/x/sys/execabs" ) type builder struct { @@ -45,7 +46,7 @@ func (b *builder) build() error { args = append(args, "-tags", strings.Join(tags, ",")) } - cmd := exec.Command("go", args...) + cmd := execabs.Command("go", args...) cmd.Dir = b.srcdir if goos != "ios" && goos != "android" { env = append(env, "GOOS="+goos) diff --git a/cmd/fyne/internal/commands/deprecated.go b/cmd/fyne/internal/commands/deprecated.go index 8938a05253..0b43630dde 100644 --- a/cmd/fyne/internal/commands/deprecated.go +++ b/cmd/fyne/internal/commands/deprecated.go @@ -2,9 +2,9 @@ package commands import ( "os" - "os/exec" "github.com/urfave/cli/v2" + "golang.org/x/sys/execabs" ) // Vendor returns the vendor cli command. @@ -15,7 +15,7 @@ func Vendor() *cli.Command { Name: "vendor", Usage: "Deprecated: Use \"go mod vendor\" instead.", Action: func(_ *cli.Context) error { - cmd := exec.Command("go", "mod", "vendor") + cmd := execabs.Command("go", "mod", "vendor") cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr return cmd.Run() }, diff --git a/cmd/fyne/internal/commands/get.go b/cmd/fyne/internal/commands/get.go index 6e2b69fa33..c53c10ed31 100644 --- a/cmd/fyne/internal/commands/get.go +++ b/cmd/fyne/internal/commands/get.go @@ -4,13 +4,13 @@ import ( "flag" "fmt" "os" - "os/exec" "path/filepath" "strings" "fyne.io/fyne/v2/cmd/fyne/internal/util" "github.com/pkg/errors" "github.com/urfave/cli/v2" + "golang.org/x/sys/execabs" ) // Get returns the command which downloads and installs fyne applications. @@ -58,7 +58,7 @@ func NewGetter() *Getter { // Get automates the download and install of a named GUI app package. func (g *Getter) Get(pkg string) error { - cmd := exec.Command("go", "get", "-u", "-d", pkg) + cmd := execabs.Command("go", "get", "-u", "-d", pkg) cmd.Env = append(os.Environ(), "GO111MODULE=off") // cache the downloaded code cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr @@ -124,7 +124,7 @@ func (g *Getter) Run(args []string) { } func goPath() string { - cmd := exec.Command("go", "env", "GOPATH") + cmd := execabs.Command("go", "env", "GOPATH") out, err := cmd.CombinedOutput() if err != nil { diff --git a/cmd/fyne/internal/commands/install.go b/cmd/fyne/internal/commands/install.go index ab739ba330..9cdf68edd7 100644 --- a/cmd/fyne/internal/commands/install.go +++ b/cmd/fyne/internal/commands/install.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "os" - "os/exec" "path/filepath" "strings" @@ -13,6 +12,7 @@ import ( "fyne.io/fyne/v2/cmd/fyne/internal/mobile" "github.com/urfave/cli/v2" + "golang.org/x/sys/execabs" ) // Install returns the cli command for installing fyne applications @@ -195,12 +195,12 @@ func (i *Installer) installIOS() error { } func (i *Installer) runMobileInstall(tool, target string, args ...string) error { - _, err := exec.LookPath(tool) + _, err := execabs.LookPath(tool) if err != nil { return err } - cmd := exec.Command(tool, append(args, target)...) + cmd := execabs.Command(tool, append(args, target)...) cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout return cmd.Run() diff --git a/cmd/fyne/internal/commands/package-mobile.go b/cmd/fyne/internal/commands/package-mobile.go index 4a9b0c4f74..d98f0ab1c9 100644 --- a/cmd/fyne/internal/commands/package-mobile.go +++ b/cmd/fyne/internal/commands/package-mobile.go @@ -3,7 +3,6 @@ package commands import ( "io/ioutil" "os" - "os/exec" "path/filepath" "strconv" @@ -12,6 +11,7 @@ import ( "fyne.io/fyne/v2/cmd/fyne/internal/templates" "fyne.io/fyne/v2/cmd/fyne/internal/util" "github.com/pkg/errors" + "golang.org/x/sys/execabs" ) func (p *Packager) packageAndroid(arch string) error { @@ -61,7 +61,7 @@ func (p *Packager) packageIOS() error { } appDir := filepath.Join(p.dir, mobile.AppOutputName(p.os, p.name)) - cmd := exec.Command("xcrun", "actool", "Images.xcassets", "--compile", appDir, "--platform", + cmd := execabs.Command("xcrun", "actool", "Images.xcassets", "--compile", appDir, "--platform", "iphoneos", "--target-device", "iphone", "--minimum-deployment-target", "9.0", "--app-icon", "AppIcon", "--output-partial-info-plist", "/dev/null") return cmd.Run() @@ -70,5 +70,5 @@ func (p *Packager) packageIOS() error { func copyResizeIcon(size int, dir, source string) error { strSize := strconv.Itoa(size) path := dir + "/Icon_" + strSize + ".png" - return exec.Command("sips", "-o", path, "-Z", strSize, source).Run() + return execabs.Command("sips", "-o", path, "-Z", strSize, source).Run() } diff --git a/cmd/fyne/internal/commands/package-unix.go b/cmd/fyne/internal/commands/package-unix.go index e509f39677..c09f33ae54 100644 --- a/cmd/fyne/internal/commands/package-unix.go +++ b/cmd/fyne/internal/commands/package-unix.go @@ -2,12 +2,13 @@ package commands import ( "os" - "os/exec" "path/filepath" "fyne.io/fyne/v2/cmd/fyne/internal/templates" "fyne.io/fyne/v2/cmd/fyne/internal/util" "github.com/pkg/errors" + + "golang.org/x/sys/execabs" ) type unixData struct { @@ -66,7 +67,7 @@ func (p *Packager) packageUNIX() error { return errors.Wrap(err, "Failed to write Makefile string") } - tarCmd := exec.Command("tar", "-Jcf", p.name+".tar.xz", "-C", tempDir, "usr", "Makefile") + tarCmd := execabs.Command("tar", "-Jcf", p.name+".tar.xz", "-C", tempDir, "usr", "Makefile") if err = tarCmd.Run(); err != nil { return errors.Wrap(err, "Failed to create archive with tar") } diff --git a/cmd/fyne/internal/commands/package-windows.go b/cmd/fyne/internal/commands/package-windows.go index 523f3181e8..6dbcb7a733 100644 --- a/cmd/fyne/internal/commands/package-windows.go +++ b/cmd/fyne/internal/commands/package-windows.go @@ -4,7 +4,6 @@ import ( "image" "io/ioutil" "os" - "os/exec" "path/filepath" "runtime" "strings" @@ -15,6 +14,7 @@ import ( "github.com/pkg/errors" "golang.org/x/mod/modfile" "golang.org/x/mod/module" + "golang.org/x/sys/execabs" ) type windowsData struct { @@ -144,5 +144,5 @@ func runAsAdminWindows(args ...string) error { cmd += ",\"" + arg + "\"" } - return exec.Command("powershell.exe", "Start-Process", "cmd.exe", "-Verb", "runAs", "-ArgumentList", cmd).Run() + return execabs.Command("powershell.exe", "Start-Process", "cmd.exe", "-Verb", "runAs", "-ArgumentList", cmd).Run() } diff --git a/cmd/fyne/internal/commands/release.go b/cmd/fyne/internal/commands/release.go index 9ae8658ae8..6f02a10eb6 100644 --- a/cmd/fyne/internal/commands/release.go +++ b/cmd/fyne/internal/commands/release.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "os" - "os/exec" "path/filepath" "strings" "text/template" @@ -15,6 +14,7 @@ import ( "fyne.io/fyne/v2/cmd/fyne/internal/templates" "fyne.io/fyne/v2/cmd/fyne/internal/util" "github.com/urfave/cli/v2" + "golang.org/x/sys/execabs" ) var macAppStoreCategories = []string{ @@ -278,14 +278,14 @@ func (r *Releaser) packageIOSRelease() error { } defer cleanup() - cmd := exec.Command("codesign", "-f", "-vv", "-s", r.certificate, "--entitlements", + cmd := execabs.Command("codesign", "-f", "-vv", "-s", r.certificate, "--entitlements", "entitlements.plist", "Payload/"+appName+"/") if err := cmd.Run(); err != nil { fyne.LogError("Codesign failed", err) return errors.New("unable to codesign application bundle") } - return exec.Command("zip", "-r", appName[:len(appName)-4]+".ipa", "Payload/").Run() + return execabs.Command("zip", "-r", appName[:len(appName)-4]+".ipa", "Payload/").Run() } func (r *Releaser) packageMacOSRelease() error { @@ -302,14 +302,14 @@ func (r *Releaser) packageMacOSRelease() error { } defer cleanup() - cmd := exec.Command("codesign", "-vfs", appCert, "--entitlement", "entitlements.plist", r.name+".app") + cmd := execabs.Command("codesign", "-vfs", appCert, "--entitlement", "entitlements.plist", r.name+".app") err = cmd.Run() if err != nil { fyne.LogError("Codesign failed", err) return errors.New("unable to codesign application bundle") } - cmd = exec.Command("productbuild", "--component", r.name+".app", "/Applications/", + cmd = execabs.Command("productbuild", "--component", r.name+".app", "/Applications/", "--product", r.name+".app/Contents/Info.plist", unsignedPath) err = cmd.Run() if err != nil { @@ -318,7 +318,7 @@ func (r *Releaser) packageMacOSRelease() error { } defer os.Remove(unsignedPath) - cmd = exec.Command("productsign", "--sign", installCert, unsignedPath, r.name+".pkg") + cmd = execabs.Command("productsign", "--sign", installCert, unsignedPath, r.name+".pkg") return cmd.Run() } @@ -354,7 +354,7 @@ func (r *Releaser) packageWindowsRelease(outFile string) error { return errors.New("cannot find makeappx.exe, make sure you have installed the Windows SDK") } - cmd := exec.Command(filepath.Join(binDir, "makeappx.exe"), "pack", "/d", payload, "/p", outFile) + cmd := execabs.Command(filepath.Join(binDir, "makeappx.exe"), "pack", "/d", payload, "/p", outFile) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin @@ -373,7 +373,7 @@ func (r *Releaser) signAndroid(path string) error { } args = append(args, path) - cmd := exec.Command(signer, args...) + cmd := execabs.Command(signer, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin @@ -386,7 +386,7 @@ func (r *Releaser) signWindows(appx string) error { return errors.New("cannot find signtool.exe, make sure you have installed the Windows SDK") } - cmd := exec.Command(filepath.Join(binDir, "signtool.exe"), + cmd := execabs.Command(filepath.Join(binDir, "signtool.exe"), "sign", "/a", "/v", "/fd", "SHA256", "/f", r.certificate, "/p", r.password, appx) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -474,7 +474,7 @@ func (r *Releaser) zipAlign(path string) error { } cmd := filepath.Join(util.AndroidBuildToolsPath(), "zipalign") - err = exec.Command(cmd, "4", unaligned, path).Run() + err = execabs.Command(cmd, "4", unaligned, path).Run() if err != nil { _ = os.Rename(path, unaligned) // ignore error, return previous return err @@ -483,7 +483,7 @@ func (r *Releaser) zipAlign(path string) error { } func findWindowsSDKBin() (string, error) { - inPath, err := exec.LookPath("makeappx.exe") + inPath, err := execabs.LookPath("makeappx.exe") if err == nil { return inPath, nil } diff --git a/cmd/fyne/internal/mobile/build.go b/cmd/fyne/internal/mobile/build.go index f4061d8fd9..76b11d28ea 100644 --- a/cmd/fyne/internal/mobile/build.go +++ b/cmd/fyne/internal/mobile/build.go @@ -12,10 +12,10 @@ import ( "fmt" "io" "os" - "os/exec" "regexp" "strings" + "golang.org/x/sys/execabs" "golang.org/x/tools/go/packages" ) @@ -183,7 +183,7 @@ func extractPkgs(nm string, path string) (map[string]bool, error) { return map[string]bool{"github.com/fyne-io/mobile/app": true}, nil } r, w := io.Pipe() - cmd := exec.Command(nm, path) + cmd := execabs.Command(nm, path) cmd.Stdout = w cmd.Stderr = os.Stderr @@ -312,7 +312,7 @@ func goCmd(subcmd string, srcs []string, env []string, args ...string) error { } func goCmdAt(at string, subcmd string, srcs []string, env []string, args ...string) error { - cmd := exec.Command("go", subcmd) + cmd := execabs.Command("go", subcmd) tags := buildTags targetOS, _, err := parseBuildTarget(buildTarget) if err != nil { diff --git a/cmd/fyne/internal/mobile/build_iosapp.go b/cmd/fyne/internal/mobile/build_iosapp.go index a9b96790ce..47998ee638 100644 --- a/cmd/fyne/internal/mobile/build_iosapp.go +++ b/cmd/fyne/internal/mobile/build_iosapp.go @@ -11,12 +11,12 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" "path" "path/filepath" "strings" "text/template" + "golang.org/x/sys/execabs" "golang.org/x/tools/go/packages" ) @@ -82,7 +82,7 @@ func goIOSBuild(pkg *packages.Package, bundleID string, archs []string, } // We are using lipo tool to build multiarchitecture binaries. - cmd := exec.Command( + cmd := execabs.Command( "xcrun", "lipo", "-o", filepath.Join(tmpdir, "main/main"), "-create", @@ -122,7 +122,7 @@ func goIOSBuild(pkg *packages.Package, bundleID string, archs []string, "DEVELOPMENT_TEAM=" + teamID, } - cmd = exec.Command("xcrun", cmdStrings...) + cmd = execabs.Command("xcrun", cmdStrings...) if err := runCmd(cmd); err != nil { return nil, err } @@ -252,7 +252,7 @@ func lookupCert(optName string) ([]byte, error) { } func lookupCertNamed(name string) ([]byte, error) { - cmd := exec.Command( + cmd := execabs.Command( "security", "find-certificate", "-c", name, "-p", ) diff --git a/cmd/fyne/internal/mobile/env.go b/cmd/fyne/internal/mobile/env.go index 429da1b185..c3083351cc 100644 --- a/cmd/fyne/internal/mobile/env.go +++ b/cmd/fyne/internal/mobile/env.go @@ -5,12 +5,13 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" "runtime" "strings" "fyne.io/fyne/v2" + + "golang.org/x/sys/execabs" ) // General mobile build environment. Initialized by envInit. @@ -209,14 +210,14 @@ func envClang(sdkName string) (clang, cflags string, err error) { if buildN { return sdkName + "-clang", "-isysroot=" + sdkName, nil } - cmd := exec.Command("xcrun", "--sdk", sdkName, "--find", "clang") + cmd := execabs.Command("xcrun", "--sdk", sdkName, "--find", "clang") out, err := cmd.CombinedOutput() if err != nil { return "", "", fmt.Errorf("xcrun --find: %v\n%s", err, out) } clang = strings.TrimSpace(string(out)) - cmd = exec.Command("xcrun", "--sdk", sdkName, "--show-sdk-path") + cmd = execabs.Command("xcrun", "--sdk", sdkName, "--show-sdk-path") out, err = cmd.CombinedOutput() if err != nil { return "", "", fmt.Errorf("xcrun --show-sdk-path: %v\n%s", err, out) @@ -362,6 +363,6 @@ var ndk = ndkConfig{ } func xcodeAvailable() bool { - err := exec.Command("xcrun", "xcodebuild", "-version").Run() + err := execabs.Command("xcrun", "xcodebuild", "-version").Run() return err == nil } diff --git a/cmd/fyne/internal/mobile/gendex/gendex.go b/cmd/fyne/internal/mobile/gendex/gendex.go index 07c97f0e82..d8de79abbb 100644 --- a/cmd/fyne/internal/mobile/gendex/gendex.go +++ b/cmd/fyne/internal/mobile/gendex/gendex.go @@ -26,8 +26,9 @@ import ( "io/ioutil" "log" "os" - "os/exec" "path/filepath" + + "golang.org/x/sys/execabs" ) var outfile = flag.String("o", "dex.go", "result will be written file") @@ -69,7 +70,7 @@ func gendex() error { if err != nil { return err } - cmd := exec.Command( + cmd := execabs.Command( "javac", "-source", "1.7", "-target", "1.7", @@ -86,7 +87,7 @@ func gendex() error { if err != nil { return err } - cmd = exec.Command( + cmd = execabs.Command( buildTools+"/dx", "--dex", "--output="+tmpdir+"/classes.dex", diff --git a/cmd/fyne/internal/mobile/init.go b/cmd/fyne/internal/mobile/init.go index 831643a1eb..bd7beadfef 100644 --- a/cmd/fyne/internal/mobile/init.go +++ b/cmd/fyne/internal/mobile/init.go @@ -8,10 +8,11 @@ import ( "bytes" "fmt" "os" - "os/exec" "path/filepath" "runtime" "strings" + + "golang.org/x/sys/execabs" ) var ( @@ -76,14 +77,14 @@ func goEnv(name string) string { if val := os.Getenv(name); val != "" { return val } - val, err := exec.Command("go", "env", name).Output() + val, err := execabs.Command("go", "env", name).Output() if err != nil { panic(err) // the Go tool was tested to work earlier } return strings.TrimSpace(string(val)) } -func runCmd(cmd *exec.Cmd) error { +func runCmd(cmd *execabs.Cmd) error { if buildX || buildN { dir := "" if cmd.Dir != "" { diff --git a/dialog/file_xdg.go b/dialog/file_xdg.go index 748d116273..3a74e39e51 100644 --- a/dialog/file_xdg.go +++ b/dialog/file_xdg.go @@ -6,19 +6,20 @@ package dialog import ( "fmt" "os" - "os/exec" "fyne.io/fyne/v2" "fyne.io/fyne/v2/storage" + + "golang.org/x/sys/execabs" ) func getFavoriteLocation(homeURI fyne.URI, name, fallbackName string) (fyne.URI, error) { cmdName := "xdg-user-dir" - if _, err := exec.LookPath(cmdName); err != nil { + if _, err := execabs.LookPath(cmdName); err != nil { return storage.Child(homeURI, fallbackName) // no lookup possible } - cmd := exec.Command(cmdName, name) + cmd := execabs.Command(cmdName, name) loc, err := cmd.Output() if err != nil { return storage.Child(homeURI, fallbackName) diff --git a/go.mod b/go.mod index fc45781416..b34c0ce65f 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526 github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca - github.com/lucor/goinfo v0.0.0-20210209132455-aee5dbc9b821 + github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pkg/errors v0.9.1 github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 @@ -23,11 +23,9 @@ require ( github.com/stretchr/testify v1.5.1 github.com/urfave/cli/v2 v2.3.0 golang.org/x/image v0.0.0-20200430140353-33d19683fad8 - golang.org/x/mod v0.2.0 - golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect - golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666 - golang.org/x/text v0.3.2 // indirect - golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03 + golang.org/x/mod v0.4.2 + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c + golang.org/x/tools v0.1.5 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/go.sum b/go.sum index c53acc32ef..48e3eafc82 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mo github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lucor/goinfo v0.0.0-20210209132455-aee5dbc9b821 h1:oROpX/5r4YyH7tjXHFpwuH6pmG5Fy2rz7382MQhEcbw= -github.com/lucor/goinfo v0.0.0-20210209132455-aee5dbc9b821/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng= +github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b h1:tLSDWcFhT0WRlnsFszh4iaFTexWF8mmccGTk88Siq7Q= +github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -58,40 +58,42 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666 h1:gVCS+QOncANNPlmlO1AhlU3oxs4V9z+gTtPwIk3p2N8= -golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03 h1:XpToik3MpT5iW3iHgNwnh3a8QwugfomvxOlyDnaOils= -golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/vendor/github.com/lucor/goinfo/.gitignore b/vendor/github.com/lucor/goinfo/.gitignore new file mode 100644 index 0000000000..60a8267267 --- /dev/null +++ b/vendor/github.com/lucor/goinfo/.gitignore @@ -0,0 +1,11 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +goinfo +cmd/goinfo/goinfo + +# Test binary, build with `go test -c` +*.test diff --git a/vendor/github.com/lucor/goinfo/go.mod b/vendor/github.com/lucor/goinfo/go.mod index 85d701fe76..c012890bda 100644 --- a/vendor/github.com/lucor/goinfo/go.mod +++ b/vendor/github.com/lucor/goinfo/go.mod @@ -2,4 +2,7 @@ module github.com/lucor/goinfo go 1.13 -require golang.org/x/mod v0.2.0 +require ( + golang.org/x/mod v0.4.2 + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c +) diff --git a/vendor/github.com/lucor/goinfo/go.sum b/vendor/github.com/lucor/goinfo/go.sum index dc2fa8e3d2..74b314ca16 100644 --- a/vendor/github.com/lucor/goinfo/go.sum +++ b/vendor/github.com/lucor/goinfo/go.sum @@ -1,12 +1,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/lucor/goinfo/report/go_env.go b/vendor/github.com/lucor/goinfo/report/go_env.go index f4ae184685..c222675490 100644 --- a/vendor/github.com/lucor/goinfo/report/go_env.go +++ b/vendor/github.com/lucor/goinfo/report/go_env.go @@ -3,9 +3,9 @@ package report import ( "encoding/json" "fmt" - "os/exec" "github.com/lucor/goinfo" + "golang.org/x/sys/execabs" ) // GoEnv collects the info about the Go environment using the go env tool @@ -21,7 +21,7 @@ func (i *GoEnv) Summary() string { // Info returns the collected info func (i *GoEnv) Info() (goinfo.Info, error) { var info goinfo.Info - cmd := exec.Command("go", "env", "-json") + cmd := execabs.Command("go", "env", "-json") out, err := cmd.Output() if err != nil { return nil, fmt.Errorf("could not detect go env info: %w", err) diff --git a/vendor/github.com/lucor/goinfo/report/go_module.go b/vendor/github.com/lucor/goinfo/report/go_module.go index 18c45312cc..85dfb9e6ee 100644 --- a/vendor/github.com/lucor/goinfo/report/go_module.go +++ b/vendor/github.com/lucor/goinfo/report/go_module.go @@ -5,12 +5,12 @@ import ( "go/build" "io/ioutil" "os" - "os/exec" "path/filepath" "strings" "github.com/lucor/goinfo" "golang.org/x/mod/modfile" + "golang.org/x/sys/execabs" ) const ( @@ -120,7 +120,7 @@ func vcsInfo(workDir string) (string, error) { // gitInfo returns the "human-readable" commit name using git describe func gitInfo(workDir string) (string, error) { - cmd := exec.Command("git", "describe", "--tags", "--dirty", "--always") + cmd := execabs.Command("git", "describe", "--tags", "--dirty", "--always") cmd.Dir = workDir out, err := cmd.CombinedOutput() s := strings.Trim(string(out), "\n") diff --git a/vendor/github.com/lucor/goinfo/report/go_version.go b/vendor/github.com/lucor/goinfo/report/go_version.go index 9dc2305e58..329bcce8ae 100644 --- a/vendor/github.com/lucor/goinfo/report/go_version.go +++ b/vendor/github.com/lucor/goinfo/report/go_version.go @@ -2,10 +2,10 @@ package report import ( "fmt" - "os/exec" "strings" "github.com/lucor/goinfo" + "golang.org/x/sys/execabs" ) // GoVersion collects the info about the Go version using the go version command @@ -18,7 +18,7 @@ func (i *GoVersion) Summary() string { // Info returns the collected info func (i *GoVersion) Info() (goinfo.Info, error) { - cmd := exec.Command("go", "version") + cmd := execabs.Command("go", "version") out, err := cmd.Output() if err != nil { return nil, fmt.Errorf("could not detect go version info: %w", err) diff --git a/vendor/github.com/lucor/goinfo/report/os_darwin.go b/vendor/github.com/lucor/goinfo/report/os_darwin.go index d8f4eda996..c624df3384 100644 --- a/vendor/github.com/lucor/goinfo/report/os_darwin.go +++ b/vendor/github.com/lucor/goinfo/report/os_darwin.go @@ -4,10 +4,10 @@ import ( "bufio" "bytes" "fmt" - "os/exec" "strings" "github.com/lucor/goinfo" + "golang.org/x/sys/execabs" ) // Info returns the collected info @@ -32,7 +32,7 @@ func (i *OS) Info() (goinfo.Info, error) { } func (i *OS) swVers() (goinfo.Info, error) { - cmd := exec.Command("sw_vers") + cmd := execabs.Command("sw_vers") out, err := cmd.Output() if err != nil { return nil, fmt.Errorf("could not detect os info using sw_vers command: %w", err) @@ -65,7 +65,7 @@ func (i *OS) parseSwVersCmdOutput(data []byte) (goinfo.Info, error) { } func (i *OS) architecture() (string, error) { - cmd := exec.Command("uname", "-m") + cmd := execabs.Command("uname", "-m") out, err := cmd.Output() if err != nil { return "", fmt.Errorf("could not detect architecture using uname command: %w", err) @@ -77,7 +77,7 @@ func (i *OS) architecture() (string, error) { } func (i *OS) kernel() (string, error) { - cmd := exec.Command("uname", "-rsv") + cmd := execabs.Command("uname", "-rsv") out, err := cmd.Output() if err != nil { return "", fmt.Errorf("could not detect the kernel using uname command: %w", err) diff --git a/vendor/github.com/lucor/goinfo/report/os_windows.go b/vendor/github.com/lucor/goinfo/report/os_windows.go index 97d60b045d..8f9006319e 100644 --- a/vendor/github.com/lucor/goinfo/report/os_windows.go +++ b/vendor/github.com/lucor/goinfo/report/os_windows.go @@ -4,15 +4,15 @@ import ( "bufio" "bytes" "fmt" - "os/exec" "strings" "github.com/lucor/goinfo" + "golang.org/x/sys/execabs" ) // Info returns the collected info about the OS func (i *OS) Info() (goinfo.Info, error) { - cmd := exec.Command("cmd", "/C", "wmic os get /value") + cmd := execabs.Command("cmd", "/C", "wmic os get /value") out, err := cmd.Output() if err != nil { return nil, fmt.Errorf("could not detect os info using wmic command: %w", err) diff --git a/vendor/github.com/lucor/goinfo/report/os_xdg.go b/vendor/github.com/lucor/goinfo/report/os_xdg.go index 5a0cfab670..4c6a6790ac 100644 --- a/vendor/github.com/lucor/goinfo/report/os_xdg.go +++ b/vendor/github.com/lucor/goinfo/report/os_xdg.go @@ -7,11 +7,11 @@ import ( "bytes" "fmt" "io/ioutil" - "os/exec" "path/filepath" "strings" "github.com/lucor/goinfo" + "golang.org/x/sys/execabs" ) // Info returns the collected info @@ -79,7 +79,7 @@ func (i *OS) parseOsReleaseCmdOutput(data []byte) (goinfo.Info, error) { } func (i *OS) architecture() (string, error) { - cmd := exec.Command("uname", "-m") + cmd := execabs.Command("uname", "-m") out, err := cmd.Output() if err != nil { return "", fmt.Errorf("could not detect architecture using uname command: %w", err) @@ -91,7 +91,7 @@ func (i *OS) architecture() (string, error) { } func (i *OS) kernel() (string, error) { - cmd := exec.Command("uname", "-rsv") + cmd := execabs.Command("uname", "-rsv") out, err := cmd.Output() if err != nil { return "", fmt.Errorf("could not detect the kernel using uname command: %w", err) diff --git a/vendor/golang.org/x/mod/modfile/print.go b/vendor/golang.org/x/mod/modfile/print.go index 3bbea38529..524f93022a 100644 --- a/vendor/golang.org/x/mod/modfile/print.go +++ b/vendor/golang.org/x/mod/modfile/print.go @@ -138,16 +138,11 @@ func (p *printer) expr(x Expr) { p.printf(")") case *Line: - sep := "" - for _, tok := range x.Token { - p.printf("%s%s", sep, tok) - sep = " " - } + p.tokens(x.Token) case *LineBlock: - for _, tok := range x.Token { - p.printf("%s ", tok) - } + p.tokens(x.Token) + p.printf(" ") p.expr(&x.LParen) p.margin++ for _, l := range x.Line { @@ -163,3 +158,17 @@ func (p *printer) expr(x Expr) { // reach the end of the line. p.comment = append(p.comment, x.Comment().Suffix...) } + +func (p *printer) tokens(tokens []string) { + sep := "" + for _, t := range tokens { + if t == "," || t == ")" || t == "]" || t == "}" { + sep = "" + } + p.printf("%s%s", sep, t) + sep = " " + if t == "(" || t == "[" || t == "{" { + sep = "" + } + } +} diff --git a/vendor/golang.org/x/mod/modfile/read.go b/vendor/golang.org/x/mod/modfile/read.go index 616d00efdb..2a961ca81c 100644 --- a/vendor/golang.org/x/mod/modfile/read.go +++ b/vendor/golang.org/x/mod/modfile/read.go @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Module file parser. -// This is a simplified copy of Google's buildifier parser. - package modfile import ( "bytes" + "errors" "fmt" "os" "strconv" @@ -323,18 +321,17 @@ func (x *RParen) Span() (start, end Position) { // An input represents a single input file being parsed. type input struct { // Lexing state. - filename string // name of input file, for errors - complete []byte // entire input - remaining []byte // remaining input - token []byte // token being scanned - lastToken string // most recently returned token, for error messages - pos Position // current input position - comments []Comment // accumulated comments - endRule int // position of end of current rule + filename string // name of input file, for errors + complete []byte // entire input + remaining []byte // remaining input + tokenStart []byte // token being scanned to end of input + token token // next token to be returned by lex, peek + pos Position // current input position + comments []Comment // accumulated comments // Parser state. - file *FileSyntax // returned top-level syntax tree - parseError error // error encountered during parsing + file *FileSyntax // returned top-level syntax tree + parseErrors ErrorList // errors encountered during parsing // Comment assignment state. pre []Expr // all expressions, in preorder traversal @@ -352,25 +349,32 @@ func newInput(filename string, data []byte) *input { // parse parses the input file. func parse(file string, data []byte) (f *FileSyntax, err error) { - in := newInput(file, data) // The parser panics for both routine errors like syntax errors // and for programmer bugs like array index errors. // Turn both into error returns. Catching bug panics is // especially important when processing many files. + in := newInput(file, data) defer func() { - if e := recover(); e != nil { - if e == in.parseError { - err = in.parseError - } else { - err = fmt.Errorf("%s:%d:%d: internal error: %v", in.filename, in.pos.Line, in.pos.LineRune, e) - } + if e := recover(); e != nil && e != &in.parseErrors { + in.parseErrors = append(in.parseErrors, Error{ + Filename: in.filename, + Pos: in.pos, + Err: fmt.Errorf("internal error: %v", e), + }) + } + if err == nil && len(in.parseErrors) > 0 { + err = in.parseErrors } }() + // Prime the lexer by reading in the first token. It will be available + // in the next peek() or lex() call. + in.readToken() + // Invoke the parser. in.parseFile() - if in.parseError != nil { - return nil, in.parseError + if len(in.parseErrors) > 0 { + return nil, in.parseErrors } in.file.Name = in.filename @@ -381,14 +385,14 @@ func parse(file string, data []byte) (f *FileSyntax, err error) { } // Error is called to report an error. -// The reason s is often "syntax error". // Error does not return: it panics. func (in *input) Error(s string) { - if s == "syntax error" && in.lastToken != "" { - s += " near " + in.lastToken - } - in.parseError = fmt.Errorf("%s:%d:%d: %v", in.filename, in.pos.Line, in.pos.LineRune, s) - panic(in.parseError) + in.parseErrors = append(in.parseErrors, Error{ + Filename: in.filename, + Pos: in.pos, + Err: errors.New(s), + }) + panic(&in.parseErrors) } // eof reports whether the input has reached end of file. @@ -434,46 +438,76 @@ func (in *input) readRune() int { return int(r) } -type symType struct { +type token struct { + kind tokenKind pos Position endPos Position text string } +type tokenKind int + +const ( + _EOF tokenKind = -(iota + 1) + _EOLCOMMENT + _IDENT + _STRING + _COMMENT + + // newlines and punctuation tokens are allowed as ASCII codes. +) + +func (k tokenKind) isComment() bool { + return k == _COMMENT || k == _EOLCOMMENT +} + +// isEOL returns whether a token terminates a line. +func (k tokenKind) isEOL() bool { + return k == _EOF || k == _EOLCOMMENT || k == '\n' +} + // startToken marks the beginning of the next input token. -// It must be followed by a call to endToken, once the token has +// It must be followed by a call to endToken, once the token's text has // been consumed using readRune. -func (in *input) startToken(sym *symType) { - in.token = in.remaining - sym.text = "" - sym.pos = in.pos +func (in *input) startToken() { + in.tokenStart = in.remaining + in.token.text = "" + in.token.pos = in.pos } // endToken marks the end of an input token. -// It records the actual token string in sym.text if the caller -// has not done that already. -func (in *input) endToken(sym *symType) { - if sym.text == "" { - tok := string(in.token[:len(in.token)-len(in.remaining)]) - sym.text = tok - in.lastToken = sym.text +// It records the actual token string in tok.text. +// A single trailing newline (LF or CRLF) will be removed from comment tokens. +func (in *input) endToken(kind tokenKind) { + in.token.kind = kind + text := string(in.tokenStart[:len(in.tokenStart)-len(in.remaining)]) + if kind.isComment() { + if strings.HasSuffix(text, "\r\n") { + text = text[:len(text)-2] + } else { + text = strings.TrimSuffix(text, "\n") + } } - sym.endPos = in.pos + in.token.text = text + in.token.endPos = in.pos +} + +// peek returns the kind of the the next token returned by lex. +func (in *input) peek() tokenKind { + return in.token.kind } // lex is called from the parser to obtain the next input token. -// It returns the token value (either a rune like '+' or a symbolic token _FOR) -// and sets val to the data associated with the token. -// For all our input tokens, the associated data is -// val.Pos (the position where the token begins) -// and val.Token (the input string corresponding to the token). -func (in *input) lex(sym *symType) int { +func (in *input) lex() token { + tok := in.token + in.readToken() + return tok +} + +// readToken lexes the next token from the text and stores it in in.token. +func (in *input) readToken() { // Skip past spaces, stopping at non-space or EOF. - countNL := 0 // number of newlines we've skipped past for !in.eof() { - // Skip over spaces. Count newlines so we can give the parser - // information about where top-level blank lines are, - // for top-level comment assignment. c := in.peekRune() if c == ' ' || c == '\t' || c == '\r' { in.readRune() @@ -482,7 +516,7 @@ func (in *input) lex(sym *symType) int { // Comment runs to end of line. if in.peekPrefix("//") { - in.startToken(sym) + in.startToken() // Is this comment the only thing on its line? // Find the last \n before this // and see if it's all @@ -495,30 +529,23 @@ func (in *input) lex(sym *symType) int { // Consume comment. for len(in.remaining) > 0 && in.readRune() != '\n' { } - in.endToken(sym) - - sym.text = strings.TrimRight(sym.text, "\n") - in.lastToken = "comment" // If we are at top level (not in a statement), hand the comment to // the parser as a _COMMENT token. The grammar is written // to handle top-level comments itself. if !suffix { - // Not in a statement. Tell parser about top-level comment. - return _COMMENT + in.endToken(_COMMENT) + return } // Otherwise, save comment for later attachment to syntax tree. - if countNL > 1 { - in.comments = append(in.comments, Comment{sym.pos, "", false}) - } - in.comments = append(in.comments, Comment{sym.pos, sym.text, suffix}) - countNL = 1 - return _EOL + in.endToken(_EOLCOMMENT) + in.comments = append(in.comments, Comment{in.token.pos, in.token.text, suffix}) + return } if in.peekPrefix("/*") { - in.Error(fmt.Sprintf("mod files must use // comments (not /* */ comments)")) + in.Error("mod files must use // comments (not /* */ comments)") } // Found non-space non-comment. @@ -526,35 +553,27 @@ func (in *input) lex(sym *symType) int { } // Found the beginning of the next token. - in.startToken(sym) - defer in.endToken(sym) + in.startToken() // End of file. if in.eof() { - in.lastToken = "EOF" - return _EOF + in.endToken(_EOF) + return } // Punctuation tokens. switch c := in.peekRune(); c { - case '\n': + case '\n', '(', ')', '[', ']', '{', '}', ',': in.readRune() - return c - - case '(': - in.readRune() - return c - - case ')': - in.readRune() - return c + in.endToken(tokenKind(c)) + return case '"', '`': // quoted string quote := c in.readRune() for { if in.eof() { - in.pos = sym.pos + in.pos = in.token.pos in.Error("unexpected EOF in string") } if in.peekRune() == '\n' { @@ -566,14 +585,14 @@ func (in *input) lex(sym *symType) int { } if c == '\\' && quote != '`' { if in.eof() { - in.pos = sym.pos + in.pos = in.token.pos in.Error("unexpected EOF in string") } in.readRune() } } - in.endToken(sym) - return _STRING + in.endToken(_STRING) + return } // Checked all punctuation. Must be identifier token. @@ -587,17 +606,23 @@ func (in *input) lex(sym *symType) int { break } if in.peekPrefix("/*") { - in.Error(fmt.Sprintf("mod files must use // comments (not /* */ comments)")) + in.Error("mod files must use // comments (not /* */ comments)") } in.readRune() } - return _IDENT + in.endToken(_IDENT) } // isIdent reports whether c is an identifier rune. -// We treat nearly all runes as identifier runes. +// We treat most printable runes as identifier runes, except for a handful of +// ASCII punctuation characters. func isIdent(c int) bool { - return c != 0 && !unicode.IsSpace(rune(c)) + switch r := rune(c); r { + case ' ', '(', ')', '[', ']', '{', '}', ',': + return false + default: + return !unicode.IsSpace(r) && unicode.IsPrint(r) + } } // Comment assignment. @@ -668,7 +693,7 @@ func (in *input) assignComments() { for _, x := range in.pre { start, _ := x.Span() if debug { - fmt.Printf("pre %T :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte) + fmt.Fprintf(os.Stderr, "pre %T :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte) } xcom := x.Comment() for len(line) > 0 && start.Byte >= line[0].Start.Byte { @@ -695,7 +720,7 @@ func (in *input) assignComments() { start, end := x.Span() if debug { - fmt.Printf("post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte) + fmt.Fprintf(os.Stderr, "post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte) } // Do not assign suffix comments to end of line block or whole file. @@ -745,29 +770,29 @@ func reverseComments(list []Comment) { func (in *input) parseFile() { in.file = new(FileSyntax) - var sym symType var cb *CommentBlock for { - tok := in.lex(&sym) - switch tok { + switch in.peek() { case '\n': + in.lex() if cb != nil { in.file.Stmt = append(in.file.Stmt, cb) cb = nil } case _COMMENT: + tok := in.lex() if cb == nil { - cb = &CommentBlock{Start: sym.pos} + cb = &CommentBlock{Start: tok.pos} } com := cb.Comment() - com.Before = append(com.Before, Comment{Start: sym.pos, Token: sym.text}) + com.Before = append(com.Before, Comment{Start: tok.pos, Token: tok.text}) case _EOF: if cb != nil { in.file.Stmt = append(in.file.Stmt, cb) } return default: - in.parseStmt(&sym) + in.parseStmt() if cb != nil { in.file.Stmt[len(in.file.Stmt)-1].Comment().Before = cb.Before cb = nil @@ -776,60 +801,88 @@ func (in *input) parseFile() { } } -func (in *input) parseStmt(sym *symType) { - start := sym.pos - end := sym.endPos - token := []string{sym.text} +func (in *input) parseStmt() { + tok := in.lex() + start := tok.pos + end := tok.endPos + tokens := []string{tok.text} for { - tok := in.lex(sym) - switch tok { - case '\n', _EOF, _EOL: + tok := in.lex() + switch { + case tok.kind.isEOL(): in.file.Stmt = append(in.file.Stmt, &Line{ Start: start, - Token: token, + Token: tokens, End: end, }) return - case '(': - in.file.Stmt = append(in.file.Stmt, in.parseLineBlock(start, token, sym)) - return + + case tok.kind == '(': + if next := in.peek(); next.isEOL() { + // Start of block: no more tokens on this line. + in.file.Stmt = append(in.file.Stmt, in.parseLineBlock(start, tokens, tok)) + return + } else if next == ')' { + rparen := in.lex() + if in.peek().isEOL() { + // Empty block. + in.lex() + in.file.Stmt = append(in.file.Stmt, &LineBlock{ + Start: start, + Token: tokens, + LParen: LParen{Pos: tok.pos}, + RParen: RParen{Pos: rparen.pos}, + }) + return + } + // '( )' in the middle of the line, not a block. + tokens = append(tokens, tok.text, rparen.text) + } else { + // '(' in the middle of the line, not a block. + tokens = append(tokens, tok.text) + } + default: - token = append(token, sym.text) - end = sym.endPos + tokens = append(tokens, tok.text) + end = tok.endPos } } } -func (in *input) parseLineBlock(start Position, token []string, sym *symType) *LineBlock { +func (in *input) parseLineBlock(start Position, token []string, lparen token) *LineBlock { x := &LineBlock{ Start: start, Token: token, - LParen: LParen{Pos: sym.pos}, + LParen: LParen{Pos: lparen.pos}, } var comments []Comment for { - tok := in.lex(sym) - switch tok { - case _EOL: - // ignore + switch in.peek() { + case _EOLCOMMENT: + // Suffix comment, will be attached later by assignComments. + in.lex() case '\n': + // Blank line. Add an empty comment to preserve it. + in.lex() if len(comments) == 0 && len(x.Line) > 0 || len(comments) > 0 && comments[len(comments)-1].Token != "" { comments = append(comments, Comment{}) } case _COMMENT: - comments = append(comments, Comment{Start: sym.pos, Token: sym.text}) + tok := in.lex() + comments = append(comments, Comment{Start: tok.pos, Token: tok.text}) case _EOF: in.Error(fmt.Sprintf("syntax error (unterminated block started at %s:%d:%d)", in.filename, x.Start.Line, x.Start.LineRune)) case ')': + rparen := in.lex() x.RParen.Before = comments - x.RParen.Pos = sym.pos - tok = in.lex(sym) - if tok != '\n' && tok != _EOF && tok != _EOL { + x.RParen.Pos = rparen.pos + if !in.peek().isEOL() { in.Error("syntax error (expected newline after closing paren)") } + in.lex() return x default: - l := in.parseLine(sym) + l := in.parseLine() x.Line = append(x.Line, l) l.Comment().Before = comments comments = nil @@ -837,35 +890,29 @@ func (in *input) parseLineBlock(start Position, token []string, sym *symType) *L } } -func (in *input) parseLine(sym *symType) *Line { - start := sym.pos - end := sym.endPos - token := []string{sym.text} +func (in *input) parseLine() *Line { + tok := in.lex() + if tok.kind.isEOL() { + in.Error("internal parse error: parseLine at end of line") + } + start := tok.pos + end := tok.endPos + tokens := []string{tok.text} for { - tok := in.lex(sym) - switch tok { - case '\n', _EOF, _EOL: + tok := in.lex() + if tok.kind.isEOL() { return &Line{ Start: start, - Token: token, + Token: tokens, End: end, InBlock: true, } - default: - token = append(token, sym.text) - end = sym.endPos } + tokens = append(tokens, tok.text) + end = tok.endPos } } -const ( - _EOF = -(1 + iota) - _EOL - _IDENT - _STRING - _COMMENT -) - var ( slashSlash = []byte("//") moduleStr = []byte("module") diff --git a/vendor/golang.org/x/mod/modfile/rule.go b/vendor/golang.org/x/mod/modfile/rule.go index 62af06889f..f8c9384985 100644 --- a/vendor/golang.org/x/mod/modfile/rule.go +++ b/vendor/golang.org/x/mod/modfile/rule.go @@ -2,10 +2,24 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Package modfile implements a parser and formatter for go.mod files. +// +// The go.mod syntax is described in +// https://golang.org/cmd/go/#hdr-The_go_mod_file. +// +// The Parse and ParseLax functions both parse a go.mod file and return an +// abstract syntax tree. ParseLax ignores unknown statements and may be used to +// parse go.mod files that may have been developed with newer versions of Go. +// +// The File struct returned by Parse and ParseLax represent an abstract +// go.mod file. File has several methods like AddNewRequire and DropReplace +// that can be used to programmatically edit a file. +// +// The Format function formats a File back to a byte slice which can be +// written to a file. package modfile import ( - "bytes" "errors" "fmt" "path/filepath" @@ -16,6 +30,7 @@ import ( "golang.org/x/mod/internal/lazyregexp" "golang.org/x/mod/module" + "golang.org/x/mod/semver" ) // A File is the parsed, interpreted form of a go.mod file. @@ -25,6 +40,7 @@ type File struct { Require []*Require Exclude []*Exclude Replace []*Replace + Retract []*Retract Syntax *FileSyntax } @@ -61,6 +77,21 @@ type Replace struct { Syntax *Line } +// A Retract is a single retract statement. +type Retract struct { + VersionInterval + Rationale string + Syntax *Line +} + +// A VersionInterval represents a range of versions with upper and lower bounds. +// Intervals are closed: both bounds are included. When Low is equal to High, +// the interval may refer to a single version ('v1.2.3') or an interval +// ('[v1.2.3, v1.2.3]'); both have the same representation. +type VersionInterval struct { + Low, High string +} + func (f *File) AddModuleStmt(path string) error { if f.Syntax == nil { f.Syntax = new(FileSyntax) @@ -94,6 +125,12 @@ func (f *File) AddComment(text string) { type VersionFixer func(path, version string) (string, error) +// errDontFix is returned by a VersionFixer to indicate the version should be +// left alone, even if it's not canonical. +var dontFixRetract VersionFixer = func(_, vers string) (string, error) { + return vers, nil +} + // Parse parses the data, reported in errors as being from file, // into a File struct. It applies fix, if non-nil, to canonicalize all module versions found. func Parse(file string, data []byte, fix VersionFixer) (*File, error) { @@ -111,7 +148,7 @@ func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) { return parseToFile(file, data, fix, false) } -func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File, error) { +func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parsed *File, err error) { fs, err := parse(file, data) if err != nil { return nil, err @@ -119,43 +156,61 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File f := &File{ Syntax: fs, } + var errs ErrorList + + // fix versions in retract directives after the file is parsed. + // We need the module path to fix versions, and it might be at the end. + defer func() { + oldLen := len(errs) + f.fixRetract(fix, &errs) + if len(errs) > oldLen { + parsed, err = nil, errs + } + }() - var errs bytes.Buffer for _, x := range fs.Stmt { switch x := x.(type) { case *Line: - f.add(&errs, x, x.Token[0], x.Token[1:], fix, strict) + f.add(&errs, nil, x, x.Token[0], x.Token[1:], fix, strict) case *LineBlock: if len(x.Token) > 1 { if strict { - fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " ")) + errs = append(errs, Error{ + Filename: file, + Pos: x.Start, + Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), + }) } continue } switch x.Token[0] { default: if strict { - fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " ")) + errs = append(errs, Error{ + Filename: file, + Pos: x.Start, + Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), + }) } continue - case "module", "require", "exclude", "replace": + case "module", "require", "exclude", "replace", "retract": for _, l := range x.Line { - f.add(&errs, l, x.Token[0], l.Token, fix, strict) + f.add(&errs, x, l, x.Token[0], l.Token, fix, strict) } } } } - if errs.Len() > 0 { - return nil, errors.New(strings.TrimRight(errs.String(), "\n")) + if len(errs) > 0 { + return nil, errs } return f, nil } var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`) -func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, fix VersionFixer, strict bool) { +func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) { // If strict is false, this module is a dependency. // We ignore all unknown directives as well as main-module-only // directives like replace and exclude. It will work better for @@ -164,67 +219,92 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f // and simply ignore those statements. if !strict { switch verb { - case "module", "require", "go": + case "go", "module", "retract", "require": // want these even for dependency go.mods default: return } } + wrapModPathError := func(modPath string, err error) { + *errs = append(*errs, Error{ + Filename: f.Syntax.Name, + Pos: line.Start, + ModPath: modPath, + Verb: verb, + Err: err, + }) + } + wrapError := func(err error) { + *errs = append(*errs, Error{ + Filename: f.Syntax.Name, + Pos: line.Start, + Err: err, + }) + } + errorf := func(format string, args ...interface{}) { + wrapError(fmt.Errorf(format, args...)) + } + switch verb { default: - fmt.Fprintf(errs, "%s:%d: unknown directive: %s\n", f.Syntax.Name, line.Start.Line, verb) + errorf("unknown directive: %s", verb) case "go": if f.Go != nil { - fmt.Fprintf(errs, "%s:%d: repeated go statement\n", f.Syntax.Name, line.Start.Line) + errorf("repeated go statement") return } - if len(args) != 1 || !GoVersionRE.MatchString(args[0]) { - fmt.Fprintf(errs, "%s:%d: usage: go 1.23\n", f.Syntax.Name, line.Start.Line) + if len(args) != 1 { + errorf("go directive expects exactly one argument") + return + } else if !GoVersionRE.MatchString(args[0]) { + errorf("invalid go version '%s': must match format 1.23", args[0]) return } + f.Go = &Go{Syntax: line} f.Go.Version = args[0] + case "module": if f.Module != nil { - fmt.Fprintf(errs, "%s:%d: repeated module statement\n", f.Syntax.Name, line.Start.Line) + errorf("repeated module statement") return } f.Module = &Module{Syntax: line} if len(args) != 1 { - - fmt.Fprintf(errs, "%s:%d: usage: module module/path\n", f.Syntax.Name, line.Start.Line) + errorf("usage: module module/path") return } s, err := parseString(&args[0]) if err != nil { - fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + errorf("invalid quoted string: %v", err) return } f.Module.Mod = module.Version{Path: s} + case "require", "exclude": if len(args) != 2 { - fmt.Fprintf(errs, "%s:%d: usage: %s module/path v1.2.3\n", f.Syntax.Name, line.Start.Line, verb) + errorf("usage: %s module/path v1.2.3", verb) return } s, err := parseString(&args[0]) if err != nil { - fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + errorf("invalid quoted string: %v", err) return } v, err := parseVersion(verb, s, &args[1], fix) if err != nil { - fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err) + wrapError(err) return } pathMajor, err := modulePathMajor(s) if err != nil { - fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err) + wrapError(err) return } if err := module.CheckPathMajor(v, pathMajor); err != nil { - fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, &Error{Verb: verb, ModPath: s, Err: err}) + wrapModPathError(s, err) return } if verb == "require" { @@ -239,61 +319,62 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f Syntax: line, }) } + case "replace": arrow := 2 if len(args) >= 2 && args[1] == "=>" { arrow = 1 } if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" { - fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory\n", f.Syntax.Name, line.Start.Line, verb, verb) + errorf("usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory", verb, verb) return } s, err := parseString(&args[0]) if err != nil { - fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + errorf("invalid quoted string: %v", err) return } pathMajor, err := modulePathMajor(s) if err != nil { - fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err) + wrapModPathError(s, err) return } var v string if arrow == 2 { v, err = parseVersion(verb, s, &args[1], fix) if err != nil { - fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err) + wrapError(err) return } if err := module.CheckPathMajor(v, pathMajor); err != nil { - fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, &Error{Verb: verb, ModPath: s, Err: err}) + wrapModPathError(s, err) return } } ns, err := parseString(&args[arrow+1]) if err != nil { - fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + errorf("invalid quoted string: %v", err) return } nv := "" if len(args) == arrow+2 { if !IsDirectoryPath(ns) { - fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)\n", f.Syntax.Name, line.Start.Line) + errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)") return } if filepath.Separator == '/' && strings.Contains(ns, `\`) { - fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)\n", f.Syntax.Name, line.Start.Line) + errorf("replacement directory appears to be Windows path (on a non-windows system)") return } } if len(args) == arrow+3 { nv, err = parseVersion(verb, ns, &args[arrow+2], fix) if err != nil { - fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err) + wrapError(err) return } if IsDirectoryPath(ns) { - fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version\n", f.Syntax.Name, line.Start.Line, ns) + errorf("replacement module directory path %q cannot have version", ns) return } } @@ -302,6 +383,74 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f New: module.Version{Path: ns, Version: nv}, Syntax: line, }) + + case "retract": + rationale := parseRetractRationale(block, line) + vi, err := parseVersionInterval(verb, "", &args, dontFixRetract) + if err != nil { + if strict { + wrapError(err) + return + } else { + // Only report errors parsing intervals in the main module. We may + // support additional syntax in the future, such as open and half-open + // intervals. Those can't be supported now, because they break the + // go.mod parser, even in lax mode. + return + } + } + if len(args) > 0 && strict { + // In the future, there may be additional information after the version. + errorf("unexpected token after version: %q", args[0]) + return + } + retract := &Retract{ + VersionInterval: vi, + Rationale: rationale, + Syntax: line, + } + f.Retract = append(f.Retract, retract) + } +} + +// fixRetract applies fix to each retract directive in f, appending any errors +// to errs. +// +// Most versions are fixed as we parse the file, but for retract directives, +// the relevant module path is the one specified with the module directive, +// and that might appear at the end of the file (or not at all). +func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) { + if fix == nil { + return + } + path := "" + if f.Module != nil { + path = f.Module.Mod.Path + } + var r *Retract + wrapError := func(err error) { + *errs = append(*errs, Error{ + Filename: f.Syntax.Name, + Pos: r.Syntax.Start, + Err: err, + }) + } + + for _, r = range f.Retract { + if path == "" { + wrapError(errors.New("no module directive found, so retract cannot be used")) + return // only print the first one of these + } + + args := r.Syntax.Token + if args[0] == "retract" { + args = args[1:] + } + vi, err := parseVersionInterval("retract", path, &args, fix) + if err != nil { + wrapError(err) + } + r.VersionInterval = vi } } @@ -372,8 +521,19 @@ func IsDirectoryPath(ns string) bool { // a single token in a go.mod line. func MustQuote(s string) bool { for _, r := range s { - if !unicode.IsPrint(r) || r == ' ' || r == '"' || r == '\'' || r == '`' { + switch r { + case ' ', '"', '\'', '`': return true + + case '(', ')', '[', ']', '{', '}', ',': + if len(s) > 1 { + return true + } + + default: + if !unicode.IsPrint(r) { + return true + } } } return s == "" || strings.Contains(s, "//") || strings.Contains(s, "/*") @@ -388,6 +548,53 @@ func AutoQuote(s string) string { return s } +func parseVersionInterval(verb string, path string, args *[]string, fix VersionFixer) (VersionInterval, error) { + toks := *args + if len(toks) == 0 || toks[0] == "(" { + return VersionInterval{}, fmt.Errorf("expected '[' or version") + } + if toks[0] != "[" { + v, err := parseVersion(verb, path, &toks[0], fix) + if err != nil { + return VersionInterval{}, err + } + *args = toks[1:] + return VersionInterval{Low: v, High: v}, nil + } + toks = toks[1:] + + if len(toks) == 0 { + return VersionInterval{}, fmt.Errorf("expected version after '['") + } + low, err := parseVersion(verb, path, &toks[0], fix) + if err != nil { + return VersionInterval{}, err + } + toks = toks[1:] + + if len(toks) == 0 || toks[0] != "," { + return VersionInterval{}, fmt.Errorf("expected ',' after version") + } + toks = toks[1:] + + if len(toks) == 0 { + return VersionInterval{}, fmt.Errorf("expected version after ','") + } + high, err := parseVersion(verb, path, &toks[0], fix) + if err != nil { + return VersionInterval{}, err + } + toks = toks[1:] + + if len(toks) == 0 || toks[0] != "]" { + return VersionInterval{}, fmt.Errorf("expected ']' after version") + } + toks = toks[1:] + + *args = toks + return VersionInterval{Low: low, High: high}, nil +} + func parseString(s *string) (string, error) { t := *s if strings.HasPrefix(t, `"`) { @@ -405,14 +612,65 @@ func parseString(s *string) (string, error) { return t, nil } +// parseRetractRationale extracts the rationale for a retract directive from the +// surrounding comments. If the line does not have comments and is part of a +// block that does have comments, the block's comments are used. +func parseRetractRationale(block *LineBlock, line *Line) string { + comments := line.Comment() + if block != nil && len(comments.Before) == 0 && len(comments.Suffix) == 0 { + comments = block.Comment() + } + groups := [][]Comment{comments.Before, comments.Suffix} + var lines []string + for _, g := range groups { + for _, c := range g { + if !strings.HasPrefix(c.Token, "//") { + continue // blank line + } + lines = append(lines, strings.TrimSpace(strings.TrimPrefix(c.Token, "//"))) + } + } + return strings.Join(lines, "\n") +} + +type ErrorList []Error + +func (e ErrorList) Error() string { + errStrs := make([]string, len(e)) + for i, err := range e { + errStrs[i] = err.Error() + } + return strings.Join(errStrs, "\n") +} + type Error struct { - Verb string - ModPath string - Err error + Filename string + Pos Position + Verb string + ModPath string + Err error } func (e *Error) Error() string { - return fmt.Sprintf("%s %s: %v", e.Verb, e.ModPath, e.Err) + var pos string + if e.Pos.LineRune > 1 { + // Don't print LineRune if it's 1 (beginning of line). + // It's always 1 except in scanner errors, which are rare. + pos = fmt.Sprintf("%s:%d:%d: ", e.Filename, e.Pos.Line, e.Pos.LineRune) + } else if e.Pos.Line > 0 { + pos = fmt.Sprintf("%s:%d: ", e.Filename, e.Pos.Line) + } else if e.Filename != "" { + pos = fmt.Sprintf("%s: ", e.Filename) + } + + var directive string + if e.ModPath != "" { + directive = fmt.Sprintf("%s %s: ", e.Verb, e.ModPath) + } else if e.Verb != "" { + directive = fmt.Sprintf("%s: ", e.Verb) + } + + return pos + directive + e.Err.Error() } func (e *Error) Unwrap() error { return e.Err } @@ -430,8 +688,7 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string } } if fix != nil { - var err error - t, err = fix(path, t) + fixed, err := fix(path, t) if err != nil { if err, ok := err.(*module.ModuleError); ok { return "", &Error{ @@ -442,19 +699,23 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string } return "", err } + t = fixed + } else { + cv := module.CanonicalVersion(t) + if cv == "" { + return "", &Error{ + Verb: verb, + ModPath: path, + Err: &module.InvalidVersionError{ + Version: t, + Err: errors.New("must be of the form v1.2.3"), + }, + } + } + t = cv } - if v := module.CanonicalVersion(t); v != "" { - *s = v - return *s, nil - } - return "", &Error{ - Verb: verb, - ModPath: path, - Err: &module.InvalidVersionError{ - Version: t, - Err: errors.New("must be of the form v1.2.3"), - }, - } + *s = t + return *s, nil } func modulePathMajor(path string) (string, error) { @@ -501,6 +762,15 @@ func (f *File) Cleanup() { } f.Replace = f.Replace[:w] + w = 0 + for _, r := range f.Retract { + if r.Low != "" || r.High != "" { + f.Retract[w] = r + w++ + } + } + f.Retract = f.Retract[:w] + f.Syntax.Cleanup() } @@ -622,7 +892,13 @@ func (f *File) DropRequire(path string) error { return nil } +// AddExclude adds a exclude statement to the mod file. Errors if the provided +// version is not a canonical version string func (f *File) AddExclude(path, vers string) error { + if err := checkCanonicalVersion(path, vers); err != nil { + return err + } + var hint *Line for _, x := range f.Exclude { if x.Mod.Path == path && x.Mod.Version == vers { @@ -694,6 +970,47 @@ func (f *File) DropReplace(oldPath, oldVers string) error { return nil } +// AddRetract adds a retract statement to the mod file. Errors if the provided +// version interval does not consist of canonical version strings +func (f *File) AddRetract(vi VersionInterval, rationale string) error { + var path string + if f.Module != nil { + path = f.Module.Mod.Path + } + if err := checkCanonicalVersion(path, vi.High); err != nil { + return err + } + if err := checkCanonicalVersion(path, vi.Low); err != nil { + return err + } + + r := &Retract{ + VersionInterval: vi, + } + if vi.Low == vi.High { + r.Syntax = f.Syntax.addLine(nil, "retract", AutoQuote(vi.Low)) + } else { + r.Syntax = f.Syntax.addLine(nil, "retract", "[", AutoQuote(vi.Low), ",", AutoQuote(vi.High), "]") + } + if rationale != "" { + for _, line := range strings.Split(rationale, "\n") { + com := Comment{Token: "// " + line} + r.Syntax.Comment().Before = append(r.Syntax.Comment().Before, com) + } + } + return nil +} + +func (f *File) DropRetract(vi VersionInterval) error { + for _, r := range f.Retract { + if r.VersionInterval == vi { + f.Syntax.removeLine(r.Syntax) + *r = Retract{} + } + } + return nil +} + func (f *File) SortBlocks() { f.removeDups() // otherwise sorting is unsafe @@ -702,28 +1019,38 @@ func (f *File) SortBlocks() { if !ok { continue } - sort.Slice(block.Line, func(i, j int) bool { - li := block.Line[i] - lj := block.Line[j] - for k := 0; k < len(li.Token) && k < len(lj.Token); k++ { - if li.Token[k] != lj.Token[k] { - return li.Token[k] < lj.Token[k] - } - } - return len(li.Token) < len(lj.Token) + less := lineLess + if block.Token[0] == "retract" { + less = lineRetractLess + } + sort.SliceStable(block.Line, func(i, j int) bool { + return less(block.Line[i], block.Line[j]) }) } } +// removeDups removes duplicate exclude and replace directives. +// +// Earlier exclude directives take priority. +// +// Later replace directives take priority. +// +// require directives are not de-duplicated. That's left up to higher-level +// logic (MVS). +// +// retract directives are not de-duplicated since comments are +// meaningful, and versions may be retracted multiple times. func (f *File) removeDups() { - have := make(map[module.Version]bool) kill := make(map[*Line]bool) + + // Remove duplicate excludes. + haveExclude := make(map[module.Version]bool) for _, x := range f.Exclude { - if have[x.Mod] { + if haveExclude[x.Mod] { kill[x.Syntax] = true continue } - have[x.Mod] = true + haveExclude[x.Mod] = true } var excl []*Exclude for _, x := range f.Exclude { @@ -733,15 +1060,16 @@ func (f *File) removeDups() { } f.Exclude = excl - have = make(map[module.Version]bool) + // Remove duplicate replacements. // Later replacements take priority over earlier ones. + haveReplace := make(map[module.Version]bool) for i := len(f.Replace) - 1; i >= 0; i-- { x := f.Replace[i] - if have[x.Old] { + if haveReplace[x.Old] { kill[x.Syntax] = true continue } - have[x.Old] = true + haveReplace[x.Old] = true } var repl []*Replace for _, x := range f.Replace { @@ -751,6 +1079,9 @@ func (f *File) removeDups() { } f.Replace = repl + // Duplicate require and retract directives are not removed. + + // Drop killed statements from the syntax tree. var stmts []Expr for _, stmt := range f.Syntax.Stmt { switch stmt := stmt.(type) { @@ -774,3 +1105,76 @@ func (f *File) removeDups() { } f.Syntax.Stmt = stmts } + +// lineLess returns whether li should be sorted before lj. It sorts +// lexicographically without assigning any special meaning to tokens. +func lineLess(li, lj *Line) bool { + for k := 0; k < len(li.Token) && k < len(lj.Token); k++ { + if li.Token[k] != lj.Token[k] { + return li.Token[k] < lj.Token[k] + } + } + return len(li.Token) < len(lj.Token) +} + +// lineRetractLess returns whether li should be sorted before lj for lines in +// a "retract" block. It treats each line as a version interval. Single versions +// are compared as if they were intervals with the same low and high version. +// Intervals are sorted in descending order, first by low version, then by +// high version, using semver.Compare. +func lineRetractLess(li, lj *Line) bool { + interval := func(l *Line) VersionInterval { + if len(l.Token) == 1 { + return VersionInterval{Low: l.Token[0], High: l.Token[0]} + } else if len(l.Token) == 5 && l.Token[0] == "[" && l.Token[2] == "," && l.Token[4] == "]" { + return VersionInterval{Low: l.Token[1], High: l.Token[3]} + } else { + // Line in unknown format. Treat as an invalid version. + return VersionInterval{} + } + } + vii := interval(li) + vij := interval(lj) + if cmp := semver.Compare(vii.Low, vij.Low); cmp != 0 { + return cmp > 0 + } + return semver.Compare(vii.High, vij.High) > 0 +} + +// checkCanonicalVersion returns a non-nil error if vers is not a canonical +// version string or does not match the major version of path. +// +// If path is non-empty, the error text suggests a format with a major version +// corresponding to the path. +func checkCanonicalVersion(path, vers string) error { + _, pathMajor, pathMajorOk := module.SplitPathVersion(path) + + if vers == "" || vers != module.CanonicalVersion(vers) { + if pathMajor == "" { + return &module.InvalidVersionError{ + Version: vers, + Err: fmt.Errorf("must be of the form v1.2.3"), + } + } + return &module.InvalidVersionError{ + Version: vers, + Err: fmt.Errorf("must be of the form %s.2.3", module.PathMajorPrefix(pathMajor)), + } + } + + if pathMajorOk { + if err := module.CheckPathMajor(vers, pathMajor); err != nil { + if pathMajor == "" { + // In this context, the user probably wrote "v2.3.4" when they meant + // "v2.3.4+incompatible". Suggest that instead of "v0 or v1". + return &module.InvalidVersionError{ + Version: vers, + Err: fmt.Errorf("should be %s+incompatible (or module %s/%v)", vers, path, semver.Major(vers)), + } + } + return err + } + } + + return nil +} diff --git a/vendor/golang.org/x/mod/module/module.go b/vendor/golang.org/x/mod/module/module.go index 6cd37280a8..0e03014837 100644 --- a/vendor/golang.org/x/mod/module/module.go +++ b/vendor/golang.org/x/mod/module/module.go @@ -97,6 +97,7 @@ package module import ( "fmt" + "path" "sort" "strings" "unicode" @@ -223,14 +224,18 @@ func firstPathOK(r rune) bool { 'a' <= r && r <= 'z' } -// pathOK reports whether r can appear in an import path element. -// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: + - . _ and ~. -// This matches what "go get" has historically recognized in import paths. +// modPathOK reports whether r can appear in a module path element. +// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~. +// +// This matches what "go get" has historically recognized in import paths, +// and avoids confusing sequences like '%20' or '+' that would change meaning +// if used in a URL. +// // TODO(rsc): We would like to allow Unicode letters, but that requires additional // care in the safe encoding (see "escaped paths" above). -func pathOK(r rune) bool { +func modPathOK(r rune) bool { if r < utf8.RuneSelf { - return r == '+' || r == '-' || r == '.' || r == '_' || r == '~' || + return r == '-' || r == '.' || r == '_' || r == '~' || '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' @@ -238,6 +243,17 @@ func pathOK(r rune) bool { return false } +// modPathOK reports whether r can appear in a package import path element. +// +// Import paths are intermediate between module paths and file paths: we allow +// disallow characters that would be confusing or ambiguous as arguments to +// 'go get' (such as '@' and ' ' ), but allow certain characters that are +// otherwise-unambiguous on the command line and historically used for some +// binary names (such as '++' as a suffix for compiler binaries and wrappers). +func importPathOK(r rune) bool { + return modPathOK(r) || r == '+' +} + // fileNameOK reports whether r can appear in a file name. // For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters. // If we expand the set of allowed characters here, we have to @@ -269,7 +285,7 @@ func fileNameOK(r rune) bool { // CheckPath checks that a module path is valid. // A valid module path is a valid import path, as checked by CheckImportPath, -// with two additional constraints. +// with three additional constraints. // First, the leading path element (up to the first slash, if any), // by convention a domain name, must contain only lower-case ASCII letters, // ASCII digits, dots (U+002E), and dashes (U+002D); @@ -279,8 +295,9 @@ func fileNameOK(r rune) bool { // and must not contain any dots. For paths beginning with "gopkg.in/", // this second requirement is replaced by a requirement that the path // follow the gopkg.in server's conventions. +// Third, no path element may begin with a dot. func CheckPath(path string) error { - if err := checkPath(path, false); err != nil { + if err := checkPath(path, modulePath); err != nil { return fmt.Errorf("malformed module path %q: %v", path, err) } i := strings.Index(path, "/") @@ -313,29 +330,41 @@ func CheckPath(path string) error { // separated by slashes (U+002F). (It must not begin with nor end in a slash.) // // A valid path element is a non-empty string made up of -// ASCII letters, ASCII digits, and limited ASCII punctuation: + - . _ and ~. -// It must not begin or end with a dot (U+002E), nor contain two dots in a row. +// ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~. +// It must not end with a dot (U+002E), nor contain two dots in a row. // // The element prefix up to the first dot must not be a reserved file name -// on Windows, regardless of case (CON, com1, NuL, and so on). +// on Windows, regardless of case (CON, com1, NuL, and so on). The element +// must not have a suffix of a tilde followed by one or more ASCII digits +// (to exclude paths elements that look like Windows short-names). // // CheckImportPath may be less restrictive in the future, but see the // top-level package documentation for additional information about // subtleties of Unicode. func CheckImportPath(path string) error { - if err := checkPath(path, false); err != nil { + if err := checkPath(path, importPath); err != nil { return fmt.Errorf("malformed import path %q: %v", path, err) } return nil } +// pathKind indicates what kind of path we're checking. Module paths, +// import paths, and file paths have different restrictions. +type pathKind int + +const ( + modulePath pathKind = iota + importPath + filePath +) + // checkPath checks that a general path is valid. // It returns an error describing why but not mentioning path. // Because these checks apply to both module paths and import paths, // the caller is expected to add the "malformed ___ path %q: " prefix. // fileName indicates whether the final element of the path is a file name // (as opposed to a directory name). -func checkPath(path string, fileName bool) error { +func checkPath(path string, kind pathKind) error { if !utf8.ValidString(path) { return fmt.Errorf("invalid UTF-8") } @@ -354,39 +383,45 @@ func checkPath(path string, fileName bool) error { elemStart := 0 for i, r := range path { if r == '/' { - if err := checkElem(path[elemStart:i], fileName); err != nil { + if err := checkElem(path[elemStart:i], kind); err != nil { return err } elemStart = i + 1 } } - if err := checkElem(path[elemStart:], fileName); err != nil { + if err := checkElem(path[elemStart:], kind); err != nil { return err } return nil } // checkElem checks whether an individual path element is valid. -// fileName indicates whether the element is a file name (not a directory name). -func checkElem(elem string, fileName bool) error { +func checkElem(elem string, kind pathKind) error { if elem == "" { return fmt.Errorf("empty path element") } if strings.Count(elem, ".") == len(elem) { return fmt.Errorf("invalid path element %q", elem) } - if elem[0] == '.' && !fileName { + if elem[0] == '.' && kind == modulePath { return fmt.Errorf("leading dot in path element") } if elem[len(elem)-1] == '.' { return fmt.Errorf("trailing dot in path element") } - charOK := pathOK - if fileName { - charOK = fileNameOK - } for _, r := range elem { - if !charOK(r) { + ok := false + switch kind { + case modulePath: + ok = modPathOK(r) + case importPath: + ok = importPathOK(r) + case filePath: + ok = fileNameOK(r) + default: + panic(fmt.Sprintf("internal error: invalid kind %v", kind)) + } + if !ok { return fmt.Errorf("invalid char %q", r) } } @@ -402,6 +437,29 @@ func checkElem(elem string, fileName bool) error { return fmt.Errorf("%q disallowed as path element component on Windows", short) } } + + if kind == filePath { + // don't check for Windows short-names in file names. They're + // only an issue for import paths. + return nil + } + + // Reject path components that look like Windows short-names. + // Those usually end in a tilde followed by one or more ASCII digits. + if tilde := strings.LastIndexByte(short, '~'); tilde >= 0 && tilde < len(short)-1 { + suffix := short[tilde+1:] + suffixIsDigits := true + for _, r := range suffix { + if r < '0' || r > '9' { + suffixIsDigits = false + break + } + } + if suffixIsDigits { + return fmt.Errorf("trailing tilde and digits in path element") + } + } + return nil } @@ -418,7 +476,7 @@ func checkElem(elem string, fileName bool) error { // top-level package documentation for additional information about // subtleties of Unicode. func CheckFilePath(path string) error { - if err := checkPath(path, true); err != nil { + if err := checkPath(path, filePath); err != nil { return fmt.Errorf("malformed file path %q: %v", path, err) } return nil @@ -621,7 +679,7 @@ func EscapePath(path string) (escaped string, err error) { // Versions are allowed to be in non-semver form but must be valid file names // and not contain exclamation marks. func EscapeVersion(v string) (escaped string, err error) { - if err := checkElem(v, true); err != nil || strings.Contains(v, "!") { + if err := checkElem(v, filePath); err != nil || strings.Contains(v, "!") { return "", &InvalidVersionError{ Version: v, Err: fmt.Errorf("disallowed version string"), @@ -680,7 +738,7 @@ func UnescapeVersion(escaped string) (v string, err error) { if !ok { return "", fmt.Errorf("invalid escaped version %q", escaped) } - if err := checkElem(v, true); err != nil { + if err := checkElem(v, filePath); err != nil { return "", fmt.Errorf("invalid escaped version %q: %v", v, err) } return v, nil @@ -716,3 +774,49 @@ func unescapeString(escaped string) (string, bool) { } return string(buf), true } + +// MatchPrefixPatterns reports whether any path prefix of target matches one of +// the glob patterns (as defined by path.Match) in the comma-separated globs +// list. This implements the algorithm used when matching a module path to the +// GOPRIVATE environment variable, as described by 'go help module-private'. +// +// It ignores any empty or malformed patterns in the list. +func MatchPrefixPatterns(globs, target string) bool { + for globs != "" { + // Extract next non-empty glob in comma-separated list. + var glob string + if i := strings.Index(globs, ","); i >= 0 { + glob, globs = globs[:i], globs[i+1:] + } else { + glob, globs = globs, "" + } + if glob == "" { + continue + } + + // A glob with N+1 path elements (N slashes) needs to be matched + // against the first N+1 path elements of target, + // which end just before the N+1'th slash. + n := strings.Count(glob, "/") + prefix := target + // Walk target, counting slashes, truncating at the N+1'th slash. + for i := 0; i < len(target); i++ { + if target[i] == '/' { + if n == 0 { + prefix = target[:i] + break + } + n-- + } + } + if n > 0 { + // Not enough prefix elements. + continue + } + matched, _ := path.Match(glob, prefix) + if matched { + return true + } + } + return false +} diff --git a/vendor/golang.org/x/mod/semver/semver.go b/vendor/golang.org/x/mod/semver/semver.go index 2988e3cf9c..4338f35177 100644 --- a/vendor/golang.org/x/mod/semver/semver.go +++ b/vendor/golang.org/x/mod/semver/semver.go @@ -138,6 +138,9 @@ func Compare(v, w string) int { // Max canonicalizes its arguments and then returns the version string // that compares greater. +// +// Deprecated: use Compare instead. In most cases, returning a canonicalized +// version is not expected or desired. func Max(v, w string) string { v = Canonical(v) w = Canonical(w) diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go index 73804d3472..ff7acf2d5b 100644 --- a/vendor/golang.org/x/net/html/const.go +++ b/vendor/golang.org/x/net/html/const.go @@ -52,7 +52,7 @@ var isSpecialElementMap = map[string]bool{ "iframe": true, "img": true, "input": true, - "keygen": true, + "keygen": true, // "keygen" has been removed from the spec, but are kept here for backwards compatibility. "li": true, "link": true, "listing": true, diff --git a/vendor/golang.org/x/net/html/foreign.go b/vendor/golang.org/x/net/html/foreign.go index 74774c458a..9da9e9dc42 100644 --- a/vendor/golang.org/x/net/html/foreign.go +++ b/vendor/golang.org/x/net/html/foreign.go @@ -161,65 +161,62 @@ var mathMLAttributeAdjustments = map[string]string{ } var svgAttributeAdjustments = map[string]string{ - "attributename": "attributeName", - "attributetype": "attributeType", - "basefrequency": "baseFrequency", - "baseprofile": "baseProfile", - "calcmode": "calcMode", - "clippathunits": "clipPathUnits", - "contentscripttype": "contentScriptType", - "contentstyletype": "contentStyleType", - "diffuseconstant": "diffuseConstant", - "edgemode": "edgeMode", - "externalresourcesrequired": "externalResourcesRequired", - "filterunits": "filterUnits", - "glyphref": "glyphRef", - "gradienttransform": "gradientTransform", - "gradientunits": "gradientUnits", - "kernelmatrix": "kernelMatrix", - "kernelunitlength": "kernelUnitLength", - "keypoints": "keyPoints", - "keysplines": "keySplines", - "keytimes": "keyTimes", - "lengthadjust": "lengthAdjust", - "limitingconeangle": "limitingConeAngle", - "markerheight": "markerHeight", - "markerunits": "markerUnits", - "markerwidth": "markerWidth", - "maskcontentunits": "maskContentUnits", - "maskunits": "maskUnits", - "numoctaves": "numOctaves", - "pathlength": "pathLength", - "patterncontentunits": "patternContentUnits", - "patterntransform": "patternTransform", - "patternunits": "patternUnits", - "pointsatx": "pointsAtX", - "pointsaty": "pointsAtY", - "pointsatz": "pointsAtZ", - "preservealpha": "preserveAlpha", - "preserveaspectratio": "preserveAspectRatio", - "primitiveunits": "primitiveUnits", - "refx": "refX", - "refy": "refY", - "repeatcount": "repeatCount", - "repeatdur": "repeatDur", - "requiredextensions": "requiredExtensions", - "requiredfeatures": "requiredFeatures", - "specularconstant": "specularConstant", - "specularexponent": "specularExponent", - "spreadmethod": "spreadMethod", - "startoffset": "startOffset", - "stddeviation": "stdDeviation", - "stitchtiles": "stitchTiles", - "surfacescale": "surfaceScale", - "systemlanguage": "systemLanguage", - "tablevalues": "tableValues", - "targetx": "targetX", - "targety": "targetY", - "textlength": "textLength", - "viewbox": "viewBox", - "viewtarget": "viewTarget", - "xchannelselector": "xChannelSelector", - "ychannelselector": "yChannelSelector", - "zoomandpan": "zoomAndPan", + "attributename": "attributeName", + "attributetype": "attributeType", + "basefrequency": "baseFrequency", + "baseprofile": "baseProfile", + "calcmode": "calcMode", + "clippathunits": "clipPathUnits", + "diffuseconstant": "diffuseConstant", + "edgemode": "edgeMode", + "filterunits": "filterUnits", + "glyphref": "glyphRef", + "gradienttransform": "gradientTransform", + "gradientunits": "gradientUnits", + "kernelmatrix": "kernelMatrix", + "kernelunitlength": "kernelUnitLength", + "keypoints": "keyPoints", + "keysplines": "keySplines", + "keytimes": "keyTimes", + "lengthadjust": "lengthAdjust", + "limitingconeangle": "limitingConeAngle", + "markerheight": "markerHeight", + "markerunits": "markerUnits", + "markerwidth": "markerWidth", + "maskcontentunits": "maskContentUnits", + "maskunits": "maskUnits", + "numoctaves": "numOctaves", + "pathlength": "pathLength", + "patterncontentunits": "patternContentUnits", + "patterntransform": "patternTransform", + "patternunits": "patternUnits", + "pointsatx": "pointsAtX", + "pointsaty": "pointsAtY", + "pointsatz": "pointsAtZ", + "preservealpha": "preserveAlpha", + "preserveaspectratio": "preserveAspectRatio", + "primitiveunits": "primitiveUnits", + "refx": "refX", + "refy": "refY", + "repeatcount": "repeatCount", + "repeatdur": "repeatDur", + "requiredextensions": "requiredExtensions", + "requiredfeatures": "requiredFeatures", + "specularconstant": "specularConstant", + "specularexponent": "specularExponent", + "spreadmethod": "spreadMethod", + "startoffset": "startOffset", + "stddeviation": "stdDeviation", + "stitchtiles": "stitchTiles", + "surfacescale": "surfaceScale", + "systemlanguage": "systemLanguage", + "tablevalues": "tableValues", + "targetx": "targetX", + "targety": "targetY", + "textlength": "textLength", + "viewbox": "viewBox", + "viewtarget": "viewTarget", + "xchannelselector": "xChannelSelector", + "ychannelselector": "yChannelSelector", + "zoomandpan": "zoomAndPan", } diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go index 2cd12fc816..f91466f7cd 100644 --- a/vendor/golang.org/x/net/html/parse.go +++ b/vendor/golang.org/x/net/html/parse.go @@ -728,7 +728,13 @@ func inHeadNoscriptIM(p *parser) bool { return inBodyIM(p) case a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Style: return inHeadIM(p) - case a.Head, a.Noscript: + case a.Head: + // Ignore the token. + return true + case a.Noscript: + // Don't let the tokenizer go into raw text mode even when a