Skip to content

Commit

Permalink
cmd/go/internal/load: always use DefaultExecName to determine binary …
Browse files Browse the repository at this point in the history
…name

It should produce equivalent results to split on the import path of the
package rather than its directory, in GOPATH mode. That means the common
code in DefaultExecName can be used.

We're in the middle of Go 1.12 cycle, so now is a good time to make it
happen for Go 1.13.

Modify isVersionElement to accept path elements like "v2", "v3", "v10",
rather than "/v2", "/v3", "/v10". Then use it in DefaultExecName instead
of the ad-hoc isVersion function. There is no change in behavior.

Add tests for DefaultExecName and isVersionElement.

Updates #26869

Change-Id: Ic6da2c92587459aa2b327385e994b72a6e183092
Reviewed-on: https://go-review.googlesource.com/c/go/+/168678
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
  • Loading branch information
dmitshur committed Mar 26, 2019
1 parent db7e746 commit e007916
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 35 deletions.
46 changes: 11 additions & 35 deletions src/cmd/go/internal/load/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ func findVersionElement(path string) (i, j int) {
j = len(path)
for i = len(path) - 1; i >= 0; i-- {
if path[i] == '/' {
if isVersionElement(path[i:j]) {
if isVersionElement(path[i+1 : j]) {
return i, j
}
j = i
Expand All @@ -814,10 +814,10 @@ func findVersionElement(path string) (i, j int) {
// isVersionElement reports whether s is a well-formed path version element:
// v2, v3, v10, etc, but not v0, v05, v1.
func isVersionElement(s string) bool {
if len(s) < 3 || s[0] != '/' || s[1] != 'v' || s[2] == '0' || s[2] == '1' && len(s) == 3 {
if len(s) < 2 || s[0] != 'v' || s[1] == '0' || s[1] == '1' && len(s) == 2 {
return false
}
for i := 2; i < len(s); i++ {
for i := 1; i < len(s); i++ {
if s[i] < '0' || '9' < s[i] {
return false
}
Expand Down Expand Up @@ -1190,26 +1190,16 @@ var foldPath = make(map[string]string)
// for a package with the import path importPath.
//
// The default executable name is the last element of the import path.
// In module-aware mode, an additional rule is used. If the last element
// is a vN path element specifying the major version, then the second last
// element of the import path is used instead.
// In module-aware mode, an additional rule is used on import paths
// consisting of two or more path elements. If the last element is
// a vN path element specifying the major version, then the
// second last element of the import path is used instead.
func DefaultExecName(importPath string) string {
_, elem := pathpkg.Split(importPath)
if cfg.ModulesEnabled {
// If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
// See golang.org/issue/24667.
isVersion := func(v string) bool {
if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
return false
}
for i := 2; i < len(v); i++ {
if c := v[i]; c < '0' || '9' < c {
return false
}
}
return true
}
if isVersion(elem) {
// If this is example.com/mycmd/v2, it's more useful to
// install it as mycmd than as v2. See golang.org/issue/24667.
if elem != importPath && isVersionElement(elem) {
_, elem = pathpkg.Split(pathpkg.Dir(importPath))
}
}
Expand Down Expand Up @@ -1256,21 +1246,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
p.Error = &PackageError{Err: e}
return
}
_, elem := filepath.Split(p.Dir)
if cfg.ModulesEnabled {
// NOTE(rsc,dmitshur): Using p.ImportPath instead of p.Dir
// makes sure we install a package in the root of a
// cached module directory as that package name
// not name@v1.2.3.
// Using p.ImportPath instead of p.Dir
// is probably correct all the time,
// even for non-module-enabled code,
// but I'm not brave enough to change the
// non-module behavior this late in the
// release cycle. Can be done for Go 1.13.
// See golang.org/issue/26869.
elem = DefaultExecName(p.ImportPath)
}
elem := DefaultExecName(p.ImportPath)
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
// Install cross-compiled binaries to subdirectories of bin.
Expand Down
68 changes: 68 additions & 0 deletions src/cmd/go/internal/load/pkg_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package load

import (
"cmd/go/internal/cfg"
"testing"
)

func TestDefaultExecName(t *testing.T) {
oldModulesEnabled := cfg.ModulesEnabled
defer func() { cfg.ModulesEnabled = oldModulesEnabled }()
for _, tt := range []struct {
in string
wantMod string
wantGopath string
}{
{"example.com/mycmd", "mycmd", "mycmd"},
{"example.com/mycmd/v0", "v0", "v0"},
{"example.com/mycmd/v1", "v1", "v1"},
{"example.com/mycmd/v2", "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
{"example.com/mycmd/v3", "mycmd", "v3"}, // Semantic import versioning, use second last element in module mode.
{"mycmd", "mycmd", "mycmd"},
{"mycmd/v0", "v0", "v0"},
{"mycmd/v1", "v1", "v1"},
{"mycmd/v2", "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
{"v0", "v0", "v0"},
{"v1", "v1", "v1"},
{"v2", "v2", "v2"},
} {
{
cfg.ModulesEnabled = true
gotMod := DefaultExecName(tt.in)
if gotMod != tt.wantMod {
t.Errorf("DefaultExecName(%q) in module mode = %v; want %v", tt.in, gotMod, tt.wantMod)
}
}
{
cfg.ModulesEnabled = false
gotGopath := DefaultExecName(tt.in)
if gotGopath != tt.wantGopath {
t.Errorf("DefaultExecName(%q) in gopath mode = %v; want %v", tt.in, gotGopath, tt.wantGopath)
}
}
}
}

func TestIsVersionElement(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
in string
want bool
}{
{"v0", false},
{"v05", false},
{"v1", false},
{"v2", true},
{"v3", true},
{"v9", true},
{"v10", true},
{"v11", true},
{"v", false},
{"vx", false},
} {
got := isVersionElement(tt.in)
if got != tt.want {
t.Errorf("isVersionElement(%q) = %v; want %v", tt.in, got, tt.want)
}
}
}

0 comments on commit e007916

Please sign in to comment.