From 98534fd1a0dbb354a5e10d3de3a58ebdcfd2b5f6 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 5 Dec 2024 15:31:39 -0500 Subject: [PATCH] cmd/go: consistently use DefaultExecName for executable name go tool, go run, and the executable caching logic have all used path.Base of a package's import path to set the name of the executable produced. But the base name for a package name that's the same as a module name ending in a major version is just that major version, which is not very useful. For go build and go install, we use load.DefaultExecName as the name of the binary which will select the second to last element of the import path as the name of the executable produced. This change changes go tool, go run, and the executable caching logic to all use DefaultExecName consistently to pick the name of the executable. Change-Id: I8e615bbc6a4f9cc4549165c31954fab181d63318 Reviewed-on: https://go-review.googlesource.com/c/go/+/634039 Reviewed-by: Sam Thanawalla LUCI-TryBot-Result: Go LUCI Reviewed-by: Conrad Irwin --- src/cmd/go/internal/run/run.go | 3 +- src/cmd/go/internal/tool/tool.go | 11 ++++-- src/cmd/go/internal/work/buildid.go | 3 +- src/cmd/go/testdata/script/tool_exename.txt | 43 ++++++++++++++++++++- 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index e72b2412e5..5067cb2835 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -8,7 +8,6 @@ package run import ( "context" "go/build" - "path" "path/filepath" "strings" @@ -166,7 +165,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { } p.Internal.ExeName = src[:len(src)-len(".go")] } else { - p.Internal.ExeName = path.Base(p.ImportPath) + p.Internal.ExeName = p.DefaultExecName() } a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p) diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go index 2b18a42384..87c098491f 100644 --- a/src/cmd/go/internal/tool/tool.go +++ b/src/cmd/go/internal/tool/tool.go @@ -18,7 +18,6 @@ import ( "os" "os/exec" "os/signal" - "path" "path/filepath" "slices" "sort" @@ -250,13 +249,19 @@ func impersonateDistList(args []string) (handled bool) { return true } +func defaultExecName(importPath string) string { + var p load.Package + p.ImportPath = importPath + return p.DefaultExecName() +} + func loadModTool(ctx context.Context, name string) string { modload.InitWorkfile() modload.LoadModFile(ctx) matches := []string{} for tool := range modload.MainModules.Tools() { - if tool == name || path.Base(tool) == name { + if tool == name || defaultExecName(tool) == name { matches = append(matches, tool) } } @@ -288,7 +293,7 @@ func buildAndRunModtool(ctx context.Context, tool string, args []string) { pkgOpts := load.PackageOpts{MainOnly: true} p := load.PackagesAndErrors(ctx, pkgOpts, []string{tool})[0] p.Internal.OmitDebug = true - p.Internal.ExeName = path.Base(p.ImportPath) + p.Internal.ExeName = p.DefaultExecName() a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p) a1.CacheExecutable = true diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index ca3dce2df4..55b3190300 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -9,7 +9,6 @@ import ( "fmt" "os" "os/exec" - "path" "strings" "sync" @@ -768,7 +767,7 @@ func (b *Builder) updateBuildID(a *Action, target string) error { } name := a.Package.Internal.ExeName if name == "" { - name = path.Base(a.Package.ImportPath) + name = a.Package.DefaultExecName() } outputID, _, err := c.PutExecutable(a.actionID, name+cfg.ExeSuffix, r) r.Close() diff --git a/src/cmd/go/testdata/script/tool_exename.txt b/src/cmd/go/testdata/script/tool_exename.txt index 012a107388..a8dba8409f 100644 --- a/src/cmd/go/testdata/script/tool_exename.txt +++ b/src/cmd/go/testdata/script/tool_exename.txt @@ -18,12 +18,37 @@ go tool bar --baz stdout 'my name is: bar'$GOEXE ! stdout 'a.out' +# Test tool package paths that end in v2 +# to ensure we use the second to last component. + +# Don't use v2 as the short name of the tool. +! go tool v2 +stderr 'go: no such tool "v2"' + +# Use the second to last component as the short +# name of the tool. +go tool foo +stdout 'my name is: foo'$GOEXE + +# go run should use the same name for the tool +# We need to use a fresh cache, or we'd end up with an executable cache hit +# from when we ran built the tool to run go tool above, and we'd just +# reuse the name from the test case above. +env GOCACHE=$WORK/cache2 +go run example.com/foo/v2 +stdout 'my name is: foo'$GOEXE + -- go.mod -- module example.com/foo go 1.24 tool example.com/foo/bar +tool example.com/foo/v2 + +require example.com/foo/v2 v2.0.0 + +replace example.com/foo/v2 => ./v2 -- bar/bar.go -- package main @@ -35,4 +60,20 @@ import ( func main() { fmt.Println("my name is:", filepath.Base(os.Args[0])) -} \ No newline at end of file +} +-- v2/go.mod -- +module example.com/foo/v2 + +go 1.24 +-- v2/main.go -- +package main + +import ( + "fmt" + "os" + "path/filepath" +) + +func main() { + fmt.Println("my name is:", filepath.Base(os.Args[0])) +} -- 2.48.1