mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/go: move 'go install cmd@version' code into internal/load
'go run cmd@version' will use the same code. This changes error messages a bit. For #42088 Change-Id: Iaed3997a3d27f9fc0e868013ab765f1fb638a0b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/310410 Trust: Jay Conrod <jayconrod@google.com> Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
dc76c47565
commit
0613c748e8
3 changed files with 210 additions and 147 deletions
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"go/build"
|
"go/build"
|
||||||
"go/scanner"
|
"go/scanner"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"internal/goroot"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
@ -30,6 +31,7 @@ import (
|
||||||
"cmd/go/internal/cfg"
|
"cmd/go/internal/cfg"
|
||||||
"cmd/go/internal/fsys"
|
"cmd/go/internal/fsys"
|
||||||
"cmd/go/internal/imports"
|
"cmd/go/internal/imports"
|
||||||
|
"cmd/go/internal/modfetch"
|
||||||
"cmd/go/internal/modinfo"
|
"cmd/go/internal/modinfo"
|
||||||
"cmd/go/internal/modload"
|
"cmd/go/internal/modload"
|
||||||
"cmd/go/internal/par"
|
"cmd/go/internal/par"
|
||||||
|
|
@ -38,6 +40,7 @@ import (
|
||||||
"cmd/go/internal/trace"
|
"cmd/go/internal/trace"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
|
|
||||||
|
"golang.org/x/mod/modfile"
|
||||||
"golang.org/x/mod/module"
|
"golang.org/x/mod/module"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -2390,6 +2393,13 @@ type PackageOpts struct {
|
||||||
// of those packages could be missing, and resolving those missing dependencies
|
// of those packages could be missing, and resolving those missing dependencies
|
||||||
// could change the selected versions of modules that provide other packages.
|
// could change the selected versions of modules that provide other packages.
|
||||||
ModResolveTests bool
|
ModResolveTests bool
|
||||||
|
|
||||||
|
// MainOnly is true if the caller only wants to load main packages.
|
||||||
|
// For a literal argument matching a non-main package, a stub may be returned
|
||||||
|
// with an error. For a non-literal argument (with "..."), non-main packages
|
||||||
|
// are not be matched, and their dependencies may not be loaded. A warning
|
||||||
|
// may be printed for non-literal arguments that match no main packages.
|
||||||
|
MainOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackagesAndErrors returns the packages named by the command line arguments
|
// PackagesAndErrors returns the packages named by the command line arguments
|
||||||
|
|
@ -2480,6 +2490,10 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.MainOnly {
|
||||||
|
pkgs = mainPackagesOnly(pkgs, patterns)
|
||||||
|
}
|
||||||
|
|
||||||
// Now that CmdlinePkg is set correctly,
|
// Now that CmdlinePkg is set correctly,
|
||||||
// compute the effective flags for all loaded packages
|
// compute the effective flags for all loaded packages
|
||||||
// (not just the ones matching the patterns but also
|
// (not just the ones matching the patterns but also
|
||||||
|
|
@ -2528,6 +2542,51 @@ func CheckPackageErrors(pkgs []*Package) {
|
||||||
base.ExitIfErrors()
|
base.ExitIfErrors()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mainPackagesOnly filters out non-main packages matched only by arguments
|
||||||
|
// containing "..." and returns the remaining main packages.
|
||||||
|
//
|
||||||
|
// mainPackagesOnly sets a package's error if it is named by a literal argument.
|
||||||
|
//
|
||||||
|
// mainPackagesOnly prints warnings for non-literal arguments that only match
|
||||||
|
// non-main packages.
|
||||||
|
func mainPackagesOnly(pkgs []*Package, patterns []string) []*Package {
|
||||||
|
matchers := make([]func(string) bool, len(patterns))
|
||||||
|
for i, p := range patterns {
|
||||||
|
if strings.Contains(p, "...") {
|
||||||
|
matchers[i] = search.MatchPattern(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mainPkgs := make([]*Package, 0, len(pkgs))
|
||||||
|
mainCount := make([]int, len(patterns))
|
||||||
|
nonMainCount := make([]int, len(patterns))
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
if pkg.Name == "main" {
|
||||||
|
mainPkgs = append(mainPkgs, pkg)
|
||||||
|
for i := range patterns {
|
||||||
|
if matchers[i] != nil && matchers[i](pkg.ImportPath) {
|
||||||
|
mainCount[i]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := range patterns {
|
||||||
|
if matchers[i] == nil && patterns[i] == pkg.ImportPath && pkg.Error == nil {
|
||||||
|
pkg.Error = &PackageError{Err: ImportErrorf(pkg.ImportPath, "package %s is not a main package", pkg.ImportPath)}
|
||||||
|
} else if matchers[i] != nil && matchers[i](pkg.ImportPath) {
|
||||||
|
nonMainCount[i]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, p := range patterns {
|
||||||
|
if matchers[i] != nil && mainCount[i] == 0 && nonMainCount[i] > 0 {
|
||||||
|
fmt.Fprintf(os.Stderr, "go: warning: %q matched no main packages\n", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainPkgs
|
||||||
|
}
|
||||||
|
|
||||||
func setToolFlags(pkgs ...*Package) {
|
func setToolFlags(pkgs ...*Package) {
|
||||||
for _, p := range PackageList(pkgs) {
|
for _, p := range PackageList(pkgs) {
|
||||||
p.Internal.Asmflags = BuildAsmflags.For(p)
|
p.Internal.Asmflags = BuildAsmflags.For(p)
|
||||||
|
|
@ -2624,3 +2683,131 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa
|
||||||
|
|
||||||
return pkg
|
return pkg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PackagesAndErrorsOutsideModule is like PackagesAndErrors but runs in
|
||||||
|
// module-aware mode and ignores the go.mod file in the current directory or any
|
||||||
|
// parent directory, if there is one. This is used in the implementation of 'go
|
||||||
|
// install pkg@version' and other commands that support similar forms.
|
||||||
|
//
|
||||||
|
// modload.ForceUseModules must be true, and modload.RootMode must be NoRoot
|
||||||
|
// before calling this function.
|
||||||
|
//
|
||||||
|
// PackagesAndErrorsOutsideModule imposes several constraints to avoid
|
||||||
|
// ambiguity. All arguments must have the same version suffix (not just a suffix
|
||||||
|
// that resolves to the same version). They must refer to packages in the same
|
||||||
|
// module, which must not be std or cmd. That module is not considered the main
|
||||||
|
// module, but its go.mod file (if it has one) must not contain directives that
|
||||||
|
// would cause it to be interpreted differently if it were the main module
|
||||||
|
// (replace, exclude).
|
||||||
|
func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) {
|
||||||
|
if !modload.ForceUseModules {
|
||||||
|
panic("modload.ForceUseModules must be true")
|
||||||
|
}
|
||||||
|
if modload.RootMode != modload.NoRoot {
|
||||||
|
panic("modload.RootMode must be NoRoot")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the arguments satisfy syntactic constraints.
|
||||||
|
var version string
|
||||||
|
for _, arg := range args {
|
||||||
|
if i := strings.Index(arg, "@"); i >= 0 {
|
||||||
|
version = arg[i+1:]
|
||||||
|
if version == "" {
|
||||||
|
return nil, fmt.Errorf("%s: version must not be empty", arg)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patterns := make([]string, len(args))
|
||||||
|
for i, arg := range args {
|
||||||
|
if !strings.HasSuffix(arg, "@"+version) {
|
||||||
|
return nil, fmt.Errorf("%s: all arguments must have the same version (@%s)", arg, version)
|
||||||
|
}
|
||||||
|
p := arg[:len(arg)-len(version)-1]
|
||||||
|
switch {
|
||||||
|
case build.IsLocalImport(p):
|
||||||
|
return nil, fmt.Errorf("%s: argument must be a package path, not a relative path", arg)
|
||||||
|
case filepath.IsAbs(p):
|
||||||
|
return nil, fmt.Errorf("%s: argument must be a package path, not an absolute path", arg)
|
||||||
|
case search.IsMetaPackage(p):
|
||||||
|
return nil, fmt.Errorf("%s: argument must be a package path, not a meta-package", arg)
|
||||||
|
case path.Clean(p) != p:
|
||||||
|
return nil, fmt.Errorf("%s: argument must be a clean package path", arg)
|
||||||
|
case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p):
|
||||||
|
return nil, fmt.Errorf("%s: argument must not be a package in the standard library", arg)
|
||||||
|
default:
|
||||||
|
patterns[i] = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query the module providing the first argument, load its go.mod file, and
|
||||||
|
// check that it doesn't contain directives that would cause it to be
|
||||||
|
// interpreted differently if it were the main module.
|
||||||
|
//
|
||||||
|
// If multiple modules match the first argument, accept the longest match
|
||||||
|
// (first result). It's possible this module won't provide packages named by
|
||||||
|
// later arguments, and other modules would. Let's not try to be too
|
||||||
|
// magical though.
|
||||||
|
allowed := modload.CheckAllowed
|
||||||
|
if modload.IsRevisionQuery(version) {
|
||||||
|
// Don't check for retractions if a specific revision is requested.
|
||||||
|
allowed = nil
|
||||||
|
}
|
||||||
|
noneSelected := func(path string) (version string) { return "none" }
|
||||||
|
qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: %w", args[0], err)
|
||||||
|
}
|
||||||
|
rootMod := qrs[0].Mod
|
||||||
|
data, err := modfetch.GoMod(rootMod.Path, rootMod.Version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: %w", args[0], err)
|
||||||
|
}
|
||||||
|
f, err := modfile.Parse("go.mod", data, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s (in %s): %w", args[0], rootMod, err)
|
||||||
|
}
|
||||||
|
directiveFmt := "%s (in %s):\n" +
|
||||||
|
"\tThe go.mod file for the module providing named packages contains one or\n" +
|
||||||
|
"\tmore %s directives. It must not contain directives that would cause\n" +
|
||||||
|
"\tit to be interpreted differently than if it were the main module."
|
||||||
|
if len(f.Replace) > 0 {
|
||||||
|
return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "replace")
|
||||||
|
}
|
||||||
|
if len(f.Exclude) > 0 {
|
||||||
|
return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "exclude")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we are in NoRoot mode, the build list initially contains only
|
||||||
|
// the dummy command-line-arguments module. Add a requirement on the
|
||||||
|
// module that provides the packages named on the command line.
|
||||||
|
if _, err := modload.EditBuildList(ctx, nil, []module.Version{rootMod}); err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: %w", args[0], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load packages for all arguments.
|
||||||
|
pkgs := PackagesAndErrors(ctx, opts, patterns)
|
||||||
|
|
||||||
|
// Check that named packages are all provided by the same module.
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
var pkgErr error
|
||||||
|
if pkg.Module == nil {
|
||||||
|
// Packages in std, cmd, and their vendored dependencies
|
||||||
|
// don't have this field set.
|
||||||
|
pkgErr = fmt.Errorf("package %s not provided by module %s", pkg.ImportPath, rootMod)
|
||||||
|
} else if pkg.Module.Path != rootMod.Path || pkg.Module.Version != rootMod.Version {
|
||||||
|
pkgErr = fmt.Errorf("package %s provided by module %s@%s\n\tAll packages must be provided by the same module (%s).", pkg.ImportPath, pkg.Module.Path, pkg.Module.Version, rootMod)
|
||||||
|
}
|
||||||
|
if pkgErr != nil && pkg.Error == nil {
|
||||||
|
pkg.Error = &PackageError{Err: pkgErr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matchers := make([]func(string) bool, len(patterns))
|
||||||
|
for i, p := range patterns {
|
||||||
|
if strings.Contains(p, "...") {
|
||||||
|
matchers[i] = search.MatchPattern(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pkgs, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
exec "internal/execabs"
|
exec "internal/execabs"
|
||||||
"internal/goroot"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -21,13 +19,9 @@ import (
|
||||||
"cmd/go/internal/cfg"
|
"cmd/go/internal/cfg"
|
||||||
"cmd/go/internal/fsys"
|
"cmd/go/internal/fsys"
|
||||||
"cmd/go/internal/load"
|
"cmd/go/internal/load"
|
||||||
"cmd/go/internal/modfetch"
|
|
||||||
"cmd/go/internal/modload"
|
"cmd/go/internal/modload"
|
||||||
"cmd/go/internal/search"
|
"cmd/go/internal/search"
|
||||||
"cmd/go/internal/trace"
|
"cmd/go/internal/trace"
|
||||||
|
|
||||||
"golang.org/x/mod/modfile"
|
|
||||||
"golang.org/x/mod/module"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var CmdBuild = &base.Command{
|
var CmdBuild = &base.Command{
|
||||||
|
|
@ -762,145 +756,27 @@ func installOutsideModule(ctx context.Context, args []string) {
|
||||||
modload.RootMode = modload.NoRoot
|
modload.RootMode = modload.NoRoot
|
||||||
modload.AllowMissingModuleImports()
|
modload.AllowMissingModuleImports()
|
||||||
modload.Init()
|
modload.Init()
|
||||||
|
|
||||||
// Check that the arguments satisfy syntactic constraints.
|
|
||||||
var version string
|
|
||||||
for _, arg := range args {
|
|
||||||
if i := strings.Index(arg, "@"); i >= 0 {
|
|
||||||
version = arg[i+1:]
|
|
||||||
if version == "" {
|
|
||||||
base.Fatalf("go install %s: version must not be empty", arg)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
patterns := make([]string, len(args))
|
|
||||||
for i, arg := range args {
|
|
||||||
if !strings.HasSuffix(arg, "@"+version) {
|
|
||||||
base.Errorf("go install %s: all arguments must have the same version (@%s)", arg, version)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p := arg[:len(arg)-len(version)-1]
|
|
||||||
switch {
|
|
||||||
case build.IsLocalImport(p):
|
|
||||||
base.Errorf("go install %s: argument must be a package path, not a relative path", arg)
|
|
||||||
case filepath.IsAbs(p):
|
|
||||||
base.Errorf("go install %s: argument must be a package path, not an absolute path", arg)
|
|
||||||
case search.IsMetaPackage(p):
|
|
||||||
base.Errorf("go install %s: argument must be a package path, not a meta-package", arg)
|
|
||||||
case path.Clean(p) != p:
|
|
||||||
base.Errorf("go install %s: argument must be a clean package path", arg)
|
|
||||||
case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p):
|
|
||||||
base.Errorf("go install %s: argument must not be a package in the standard library", arg)
|
|
||||||
default:
|
|
||||||
patterns[i] = p
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.ExitIfErrors()
|
|
||||||
BuildInit()
|
BuildInit()
|
||||||
|
|
||||||
// Query the module providing the first argument, load its go.mod file, and
|
// Load packages. Ignore non-main packages.
|
||||||
// check that it doesn't contain directives that would cause it to be
|
|
||||||
// interpreted differently if it were the main module.
|
|
||||||
//
|
|
||||||
// If multiple modules match the first argument, accept the longest match
|
|
||||||
// (first result). It's possible this module won't provide packages named by
|
|
||||||
// later arguments, and other modules would. Let's not try to be too
|
|
||||||
// magical though.
|
|
||||||
allowed := modload.CheckAllowed
|
|
||||||
if modload.IsRevisionQuery(version) {
|
|
||||||
// Don't check for retractions if a specific revision is requested.
|
|
||||||
allowed = nil
|
|
||||||
}
|
|
||||||
noneSelected := func(path string) (version string) { return "none" }
|
|
||||||
qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed)
|
|
||||||
if err != nil {
|
|
||||||
base.Fatalf("go install %s: %v", args[0], err)
|
|
||||||
}
|
|
||||||
installMod := qrs[0].Mod
|
|
||||||
data, err := modfetch.GoMod(installMod.Path, installMod.Version)
|
|
||||||
if err != nil {
|
|
||||||
base.Fatalf("go install %s: %v", args[0], err)
|
|
||||||
}
|
|
||||||
f, err := modfile.Parse("go.mod", data, nil)
|
|
||||||
if err != nil {
|
|
||||||
base.Fatalf("go install %s: %s: %v", args[0], installMod, err)
|
|
||||||
}
|
|
||||||
directiveFmt := "go install %s: %s\n" +
|
|
||||||
"\tThe go.mod file for the module providing named packages contains one or\n" +
|
|
||||||
"\tmore %s directives. It must not contain directives that would cause\n" +
|
|
||||||
"\tit to be interpreted differently than if it were the main module."
|
|
||||||
if len(f.Replace) > 0 {
|
|
||||||
base.Fatalf(directiveFmt, args[0], installMod, "replace")
|
|
||||||
}
|
|
||||||
if len(f.Exclude) > 0 {
|
|
||||||
base.Fatalf(directiveFmt, args[0], installMod, "exclude")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since we are in NoRoot mode, the build list initially contains only
|
|
||||||
// the dummy command-line-arguments module. Add a requirement on the
|
|
||||||
// module that provides the packages named on the command line.
|
|
||||||
if _, err := modload.EditBuildList(ctx, nil, []module.Version{installMod}); err != nil {
|
|
||||||
base.Fatalf("go install %s: %v", args[0], err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load packages for all arguments. Ignore non-main packages.
|
|
||||||
// Print a warning if an argument contains "..." and matches no main packages.
|
// Print a warning if an argument contains "..." and matches no main packages.
|
||||||
// PackagesAndErrors already prints warnings for patterns that don't match any
|
// PackagesAndErrors already prints warnings for patterns that don't match any
|
||||||
// packages, so be careful not to double print.
|
// packages, so be careful not to double print.
|
||||||
matchers := make([]func(string) bool, len(patterns))
|
|
||||||
for i, p := range patterns {
|
|
||||||
if strings.Contains(p, "...") {
|
|
||||||
matchers[i] = search.MatchPattern(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(golang.org/issue/40276): don't report errors loading non-main packages
|
// TODO(golang.org/issue/40276): don't report errors loading non-main packages
|
||||||
// matched by a pattern.
|
// matched by a pattern.
|
||||||
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, patterns)
|
pkgOpts := load.PackageOpts{MainOnly: true}
|
||||||
|
pkgs, err := load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args)
|
||||||
|
if err != nil {
|
||||||
|
base.Fatalf("go install: %v", err)
|
||||||
|
}
|
||||||
load.CheckPackageErrors(pkgs)
|
load.CheckPackageErrors(pkgs)
|
||||||
mainPkgs := make([]*load.Package, 0, len(pkgs))
|
patterns := make([]string, len(args))
|
||||||
mainCount := make([]int, len(patterns))
|
for i, arg := range args {
|
||||||
nonMainCount := make([]int, len(patterns))
|
patterns[i] = arg[:strings.Index(arg, "@")]
|
||||||
for _, pkg := range pkgs {
|
|
||||||
if pkg.Name == "main" {
|
|
||||||
mainPkgs = append(mainPkgs, pkg)
|
|
||||||
for i := range patterns {
|
|
||||||
if matchers[i] != nil && matchers[i](pkg.ImportPath) {
|
|
||||||
mainCount[i]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i := range patterns {
|
|
||||||
if matchers[i] == nil && patterns[i] == pkg.ImportPath {
|
|
||||||
base.Errorf("go install: package %s is not a main package", pkg.ImportPath)
|
|
||||||
} else if matchers[i] != nil && matchers[i](pkg.ImportPath) {
|
|
||||||
nonMainCount[i]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
base.ExitIfErrors()
|
|
||||||
for i, p := range patterns {
|
|
||||||
if matchers[i] != nil && mainCount[i] == 0 && nonMainCount[i] > 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "go: warning: %q matched no main packages\n", p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that named packages are all provided by the same module.
|
|
||||||
for _, pkg := range mainPkgs {
|
|
||||||
if pkg.Module == nil {
|
|
||||||
// Packages in std, cmd, and their vendored dependencies
|
|
||||||
// don't have this field set.
|
|
||||||
base.Errorf("go install: package %s not provided by module %s", pkg.ImportPath, installMod)
|
|
||||||
} else if pkg.Module.Path != installMod.Path || pkg.Module.Version != installMod.Version {
|
|
||||||
base.Errorf("go install: package %s provided by module %s@%s\n\tAll packages must be provided by the same module (%s).", pkg.ImportPath, pkg.Module.Path, pkg.Module.Version, installMod)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.ExitIfErrors()
|
|
||||||
|
|
||||||
// Build and install the packages.
|
// Build and install the packages.
|
||||||
InstallPackages(ctx, patterns, mainPkgs)
|
InstallPackages(ctx, patterns, pkgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecCmd is the command to use to run user binaries.
|
// ExecCmd is the command to use to run user binaries.
|
||||||
|
|
|
||||||
|
|
@ -81,17 +81,17 @@ env GO111MODULE=auto
|
||||||
# 'go install pkg@version' reports errors for meta packages, std packages,
|
# 'go install pkg@version' reports errors for meta packages, std packages,
|
||||||
# and directories.
|
# and directories.
|
||||||
! go install std@v1.0.0
|
! go install std@v1.0.0
|
||||||
stderr '^go install std@v1.0.0: argument must be a package path, not a meta-package$'
|
stderr '^go install: std@v1.0.0: argument must be a package path, not a meta-package$'
|
||||||
! go install fmt@v1.0.0
|
! go install fmt@v1.0.0
|
||||||
stderr '^go install fmt@v1.0.0: argument must not be a package in the standard library$'
|
stderr '^go install: fmt@v1.0.0: argument must not be a package in the standard library$'
|
||||||
! go install example.com//cmd/a@v1.0.0
|
! go install example.com//cmd/a@v1.0.0
|
||||||
stderr '^go install example.com//cmd/a@v1.0.0: argument must be a clean package path$'
|
stderr '^go install: example.com//cmd/a@v1.0.0: argument must be a clean package path$'
|
||||||
! go install example.com/cmd/a@v1.0.0 ./x@v1.0.0
|
! go install example.com/cmd/a@v1.0.0 ./x@v1.0.0
|
||||||
stderr '^go install ./x@v1.0.0: argument must be a package path, not a relative path$'
|
stderr '^go install: ./x@v1.0.0: argument must be a package path, not a relative path$'
|
||||||
! go install example.com/cmd/a@v1.0.0 $GOPATH/src/x@v1.0.0
|
! go install example.com/cmd/a@v1.0.0 $GOPATH/src/x@v1.0.0
|
||||||
stderr '^go install '$WORK'[/\\]gopath/src/x@v1.0.0: argument must be a package path, not an absolute path$'
|
stderr '^go install: '$WORK'[/\\]gopath/src/x@v1.0.0: argument must be a package path, not an absolute path$'
|
||||||
! go install example.com/cmd/a@v1.0.0 cmd/...@v1.0.0
|
! go install example.com/cmd/a@v1.0.0 cmd/...@v1.0.0
|
||||||
stderr '^go install: package cmd/go not provided by module example.com/cmd@v1.0.0$'
|
stderr '^package cmd/go not provided by module example.com/cmd@v1.0.0$'
|
||||||
|
|
||||||
# 'go install pkg@version' should accept multiple arguments but report an error
|
# 'go install pkg@version' should accept multiple arguments but report an error
|
||||||
# if the version suffixes are different, even if they refer to the same version.
|
# if the version suffixes are different, even if they refer to the same version.
|
||||||
|
|
@ -106,19 +106,19 @@ stdout '^example.com/cmd v1.0.0$'
|
||||||
env GO111MODULE=auto
|
env GO111MODULE=auto
|
||||||
|
|
||||||
! go install example.com/cmd/a@v1.0.0 example.com/cmd/b@latest
|
! go install example.com/cmd/a@v1.0.0 example.com/cmd/b@latest
|
||||||
stderr '^go install example.com/cmd/b@latest: all arguments must have the same version \(@v1.0.0\)$'
|
stderr '^go install: example.com/cmd/b@latest: all arguments must have the same version \(@v1.0.0\)$'
|
||||||
|
|
||||||
|
|
||||||
# 'go install pkg@version' should report an error if the arguments are in
|
# 'go install pkg@version' should report an error if the arguments are in
|
||||||
# different modules.
|
# different modules.
|
||||||
! go install example.com/cmd/a@v1.0.0 rsc.io/fortune@v1.0.0
|
! go install example.com/cmd/a@v1.0.0 rsc.io/fortune@v1.0.0
|
||||||
stderr '^go install: package rsc.io/fortune provided by module rsc.io/fortune@v1.0.0\n\tAll packages must be provided by the same module \(example.com/cmd@v1.0.0\).$'
|
stderr '^package rsc.io/fortune provided by module rsc.io/fortune@v1.0.0\n\tAll packages must be provided by the same module \(example.com/cmd@v1.0.0\).$'
|
||||||
|
|
||||||
|
|
||||||
# 'go install pkg@version' should report an error if an argument is not
|
# 'go install pkg@version' should report an error if an argument is not
|
||||||
# a main package.
|
# a main package.
|
||||||
! go install example.com/cmd/a@v1.0.0 example.com/cmd/err@v1.0.0
|
! go install example.com/cmd/a@v1.0.0 example.com/cmd/err@v1.0.0
|
||||||
stderr '^go install: package example.com/cmd/err is not a main package$'
|
stderr '^go: package example.com/cmd/err is not a main package$'
|
||||||
|
|
||||||
# Wildcards should match only main packages. This module has a non-main package
|
# Wildcards should match only main packages. This module has a non-main package
|
||||||
# with an error, so we'll know if that gets built.
|
# with an error, so we'll know if that gets built.
|
||||||
|
|
@ -137,7 +137,7 @@ rm $GOPATH/bin
|
||||||
|
|
||||||
# If a wildcard matches no packages, we should see a warning.
|
# If a wildcard matches no packages, we should see a warning.
|
||||||
! go install example.com/cmd/nomatch...@v1.0.0
|
! go install example.com/cmd/nomatch...@v1.0.0
|
||||||
stderr '^go install example.com/cmd/nomatch\.\.\.@v1.0.0: module example.com/cmd@v1.0.0 found, but does not contain packages matching example.com/cmd/nomatch\.\.\.$'
|
stderr '^go install: example.com/cmd/nomatch\.\.\.@v1.0.0: module example.com/cmd@v1.0.0 found, but does not contain packages matching example.com/cmd/nomatch\.\.\.$'
|
||||||
go install example.com/cmd/a@v1.0.0 example.com/cmd/nomatch...@v1.0.0
|
go install example.com/cmd/a@v1.0.0 example.com/cmd/nomatch...@v1.0.0
|
||||||
stderr '^go: warning: "example.com/cmd/nomatch\.\.\." matched no packages$'
|
stderr '^go: warning: "example.com/cmd/nomatch\.\.\." matched no packages$'
|
||||||
|
|
||||||
|
|
@ -159,7 +159,7 @@ cmp stderr exclude-err
|
||||||
# 'go install pkg@version' should report an error if the module requires a
|
# 'go install pkg@version' should report an error if the module requires a
|
||||||
# higher version of itself.
|
# higher version of itself.
|
||||||
! go install example.com/cmd/a@v1.0.0-newerself
|
! go install example.com/cmd/a@v1.0.0-newerself
|
||||||
stderr '^go install example.com/cmd/a@v1.0.0-newerself: version constraints conflict:\n\texample.com/cmd@v1.0.0-newerself requires example.com/cmd@v1.0.0, but example.com/cmd@v1.0.0-newerself is requested$'
|
stderr '^go install: example.com/cmd/a@v1.0.0-newerself: version constraints conflict:\n\texample.com/cmd@v1.0.0-newerself requires example.com/cmd@v1.0.0, but example.com/cmd@v1.0.0-newerself is requested$'
|
||||||
|
|
||||||
|
|
||||||
# 'go install pkg@version' will only match a retracted version if it's
|
# 'go install pkg@version' will only match a retracted version if it's
|
||||||
|
|
@ -192,12 +192,12 @@ package main
|
||||||
|
|
||||||
func main() {}
|
func main() {}
|
||||||
-- replace-err --
|
-- replace-err --
|
||||||
go install example.com/cmd/a@v1.0.0-replace: example.com/cmd@v1.0.0-replace
|
go install: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace):
|
||||||
The go.mod file for the module providing named packages contains one or
|
The go.mod file for the module providing named packages contains one or
|
||||||
more replace directives. It must not contain directives that would cause
|
more replace directives. It must not contain directives that would cause
|
||||||
it to be interpreted differently than if it were the main module.
|
it to be interpreted differently than if it were the main module.
|
||||||
-- exclude-err --
|
-- exclude-err --
|
||||||
go install example.com/cmd/a@v1.0.0-exclude: example.com/cmd@v1.0.0-exclude
|
go install: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude):
|
||||||
The go.mod file for the module providing named packages contains one or
|
The go.mod file for the module providing named packages contains one or
|
||||||
more exclude directives. It must not contain directives that would cause
|
more exclude directives. It must not contain directives that would cause
|
||||||
it to be interpreted differently than if it were the main module.
|
it to be interpreted differently than if it were the main module.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue