Files
go-legacy-win7/patches/0002-Restore-GOPATH-mode-get.patch
Vorapol Rinsatitnon 3c131dd2f0 Remove extra arg in get
2025-08-13 22:08:57 +07:00

2664 lines
88 KiB
Diff

From 7d330febd42674f6395aad25ea85dce35b4604c5 Mon Sep 17 00:00:00 2001
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
Date: Wed, 13 Aug 2025 22:04:56 +0700
Subject: [PATCH] Restore GOPATH-mode get
---
src/cmd/go/alldocs.go | 66 ++
src/cmd/go/go_test.go | 100 +++
src/cmd/go/internal/get/get.go | 639 ++++++++++++++++++
src/cmd/go/internal/get/tag_test.go | 100 +++
src/cmd/go/internal/help/help.go | 7 +
src/cmd/go/internal/load/pkg.go | 60 ++
src/cmd/go/internal/modget/get.go | 17 +
src/cmd/go/internal/vcs/vcs.go | 39 +-
src/cmd/go/main.go | 10 +
src/cmd/go/testdata/script/get_404_meta.txt | 3 +
src/cmd/go/testdata/script/get_brace.txt | 51 ++
.../script/get_custom_domain_wildcard.txt | 6 +
src/cmd/go/testdata/script/get_dash_t.txt | 9 +
.../go/testdata/script/get_domain_root.txt | 20 +
.../script/get_dot_slash_download.txt | 10 +
src/cmd/go/testdata/script/get_dotfiles.txt | 64 ++
src/cmd/go/testdata/script/get_go_file.txt | 60 ++
src/cmd/go/testdata/script/get_goroot.txt | 53 ++
src/cmd/go/testdata/script/get_insecure.txt | 16 +
.../script/get_insecure_custom_domain.txt | 8 +
.../go/testdata/script/get_insecure_env.txt | 29 +
.../testdata/script/get_insecure_redirect.txt | 14 +
.../testdata/script/get_insecure_update.txt | 14 +
.../testdata/script/get_internal_wildcard.txt | 6 +
src/cmd/go/testdata/script/get_issue11307.txt | 9 +
src/cmd/go/testdata/script/get_issue16471.txt | 23 +
src/cmd/go/testdata/script/get_issue22125.txt | 14 +
src/cmd/go/testdata/script/get_legacy.txt | 58 ++
src/cmd/go/testdata/script/get_non_pkg.txt | 14 +
src/cmd/go/testdata/script/get_race.txt | 8 +
src/cmd/go/testdata/script/get_test_only.txt | 6 +
src/cmd/go/testdata/script/get_tilde.txt | 25 +
src/cmd/go/testdata/script/get_update.txt | 25 +
src/cmd/go/testdata/script/get_update_all.txt | 7 +
.../script/get_update_unknown_protocol.txt | 14 +
.../testdata/script/get_update_wildcard.txt | 16 +
.../testdata/script/get_vcs_error_message.txt | 9 +
src/cmd/go/testdata/script/get_vendor.txt | 95 +++
.../go/testdata/script/get_with_git_trace.txt | 9 +
.../go/testdata/script/gopath_moved_repo.txt | 67 ++
src/cmd/go/testdata/script/govcs.txt | 83 +++
src/cmd/go/testdata/script/help.txt | 2 +-
src/cmd/go/testdata/script/mod_versions.txt | 2 +-
.../script/vendor_list_issue11977.txt | 78 +--
.../script/vendor_test_issue11864.txt | 79 +--
.../script/vendor_test_issue14613.txt | 46 +-
src/cmd/internal/par/work.go | 38 ++
47 files changed, 1933 insertions(+), 195 deletions(-)
create mode 100644 src/cmd/go/internal/get/get.go
create mode 100644 src/cmd/go/internal/get/tag_test.go
create mode 100644 src/cmd/go/testdata/script/get_brace.txt
create mode 100644 src/cmd/go/testdata/script/get_custom_domain_wildcard.txt
create mode 100644 src/cmd/go/testdata/script/get_dash_t.txt
create mode 100644 src/cmd/go/testdata/script/get_domain_root.txt
create mode 100644 src/cmd/go/testdata/script/get_dot_slash_download.txt
create mode 100644 src/cmd/go/testdata/script/get_dotfiles.txt
create mode 100644 src/cmd/go/testdata/script/get_go_file.txt
create mode 100644 src/cmd/go/testdata/script/get_goroot.txt
create mode 100644 src/cmd/go/testdata/script/get_insecure_custom_domain.txt
create mode 100644 src/cmd/go/testdata/script/get_insecure_env.txt
create mode 100644 src/cmd/go/testdata/script/get_insecure_redirect.txt
create mode 100644 src/cmd/go/testdata/script/get_insecure_update.txt
create mode 100644 src/cmd/go/testdata/script/get_internal_wildcard.txt
create mode 100644 src/cmd/go/testdata/script/get_issue11307.txt
create mode 100644 src/cmd/go/testdata/script/get_issue16471.txt
create mode 100644 src/cmd/go/testdata/script/get_issue22125.txt
create mode 100644 src/cmd/go/testdata/script/get_legacy.txt
create mode 100644 src/cmd/go/testdata/script/get_non_pkg.txt
create mode 100644 src/cmd/go/testdata/script/get_race.txt
create mode 100644 src/cmd/go/testdata/script/get_test_only.txt
create mode 100644 src/cmd/go/testdata/script/get_tilde.txt
create mode 100644 src/cmd/go/testdata/script/get_update.txt
create mode 100644 src/cmd/go/testdata/script/get_update_all.txt
create mode 100644 src/cmd/go/testdata/script/get_update_unknown_protocol.txt
create mode 100644 src/cmd/go/testdata/script/get_update_wildcard.txt
create mode 100644 src/cmd/go/testdata/script/get_vcs_error_message.txt
create mode 100644 src/cmd/go/testdata/script/get_vendor.txt
create mode 100644 src/cmd/go/testdata/script/get_with_git_trace.txt
create mode 100644 src/cmd/go/testdata/script/gopath_moved_repo.txt
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 7403b92..de83acf 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -47,9 +47,11 @@
// goauth GOAUTH environment variable
// go.mod the go.mod file
// gopath GOPATH environment variable
+// gopath-get legacy GOPATH go get
// goproxy module proxy protocol
// importpath import path syntax
// modules modules, module versions, and more
+// module-get module-aware go get
// module-auth module authentication using go.sum
// packages package lists and patterns
// private configuration for downloading non-public code
@@ -2845,6 +2847,70 @@
//
// See https://golang.org/s/go15vendor for details.
//
+// # Legacy GOPATH go get
+//
+// The 'go get' command changes behavior depending on whether the
+// go command is running in module-aware mode or legacy GOPATH mode.
+// This help text, accessible as 'go help gopath-get' even in module-aware mode,
+// describes 'go get' as it operates in legacy GOPATH mode.
+//
+// Usage: go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]
+//
+// Get downloads the packages named by the import paths, along with their
+// dependencies. It then installs the named packages, like 'go install'.
+//
+// The -d flag instructs get to stop after downloading the packages; that is,
+// it instructs get not to install the packages.
+//
+// The -f flag, valid only when -u is set, forces get -u not to verify that
+// each package has been checked out from the source control repository
+// implied by its import path. This can be useful if the source is a local fork
+// of the original.
+//
+// The -fix flag instructs get to run the fix tool on the downloaded packages
+// before resolving dependencies or building the code.
+//
+// The -t flag instructs get to also download the packages required to build
+// the tests for the specified packages.
+//
+// The -u flag instructs get to use the network to update the named packages
+// and their dependencies. By default, get uses the network to check out
+// missing packages but does not use it to look for updates to existing packages.
+//
+// The -v flag enables verbose progress and debug output.
+//
+// Get also accepts build flags to control the installation. See 'go help build'.
+//
+// When checking out a new package, get creates the target directory
+// GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
+// get uses the first one. For more details see: 'go help gopath'.
+//
+// When checking out or updating a package, get looks for a branch or tag
+// that matches the locally installed version of Go. The most important
+// rule is that if the local installation is running version "go1", get
+// searches for a branch or tag named "go1". If no such version exists
+// it retrieves the default branch of the package.
+//
+// When go get checks out or updates a Git repository,
+// it also updates any git submodules referenced by the repository.
+//
+// Get never checks out or updates code stored in vendor directories.
+//
+// For more about build flags, see 'go help build'.
+//
+// For more about specifying packages, see 'go help packages'.
+//
+// For more about how 'go get' finds source code to
+// download, see 'go help importpath'.
+//
+// This text describes the behavior of get when using GOPATH
+// to manage source code and dependencies.
+// If instead the go command is running in module-aware mode,
+// the details of get's flags and effects change, as does 'go help get'.
+// See 'go help modules' and 'go help module-get'.
+//
+// See also: go build, go install, go clean.
+//
// # Module proxy protocol
//
// A Go module proxy is any web server that can respond to GET requests for
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 3e691ab..513ea86 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -973,6 +973,77 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
}
+// cmd/go: custom import path checking should not apply to Go packages without import comment.
+func TestIssue10952(t *testing.T) {
+ testenv.MustHaveExecPath(t, "git")
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.acquireNet()
+
+ tg.tempDir("src")
+ tg.setenv("GOPATH", tg.path("."))
+ const importPath = "github.com/zombiezen/go-get-issue-10952"
+ tg.run("get", "-d", "-u", importPath)
+ repoDir := tg.path("src/" + importPath)
+ tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
+ tg.run("get", "-d", "-u", importPath)
+}
+
+// Test git clone URL that uses SCP-like syntax and custom import path checking.
+func TestIssue11457(t *testing.T) {
+ testenv.MustHaveExecPath(t, "git")
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.acquireNet()
+
+ tg.tempDir("src")
+ tg.setenv("GOPATH", tg.path("."))
+ const importPath = "rsc.io/go-get-issue-11457"
+ tg.run("get", "-d", "-u", importPath)
+ repoDir := tg.path("src/" + importPath)
+ tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457")
+
+ // At this time, custom import path checking compares remotes verbatim (rather than
+ // just the host and path, skipping scheme and user), so we expect go get -u to fail.
+ // However, the goal of this test is to verify that gitRemoteRepo correctly parsed
+ // the SCP-like syntax, and we expect it to appear in the error message.
+ tg.runFail("get", "-d", "-u", importPath)
+ want := " is checked out from ssh://git@github.com/rsc/go-get-issue-11457"
+ if !strings.HasSuffix(strings.TrimSpace(tg.getStderr()), want) {
+ t.Error("expected clone URL to appear in stderr")
+ }
+}
+
+func TestGetGitDefaultBranch(t *testing.T) {
+ testenv.MustHaveExecPath(t, "git")
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.acquireNet()
+
+ tg.tempDir("src")
+ tg.setenv("GOPATH", tg.path("."))
+
+ // This repo has two branches, master and another-branch.
+ // The another-branch is the default that you get from 'git clone'.
+ // The go get command variants should not override this.
+ const importPath = "github.com/rsc/go-get-default-branch"
+
+ tg.run("get", "-d", importPath)
+ repoDir := tg.path("src/" + importPath)
+ tg.runGit(repoDir, "branch", "--contains", "HEAD")
+ tg.grepStdout(`\* another-branch`, "not on correct default branch")
+
+ tg.run("get", "-d", "-u", importPath)
+ tg.runGit(repoDir, "branch", "--contains", "HEAD")
+ tg.grepStdout(`\* another-branch`, "not on correct default branch")
+}
+
func TestPackageMainTestCompilerFlags(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -1295,6 +1366,35 @@ func TestDefaultGOPATH(t *testing.T) {
tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
}
+func TestDefaultGOPATHGet(t *testing.T) {
+ testenv.MustHaveExecPath(t, "git")
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.acquireNet()
+
+ tg.setenv("GOPATH", "")
+ tg.tempDir("home")
+ tg.setenv(homeEnvName(), tg.path("home"))
+
+ // warn for creating directory
+ tg.run("get", "-v", "github.com/golang/example/hello")
+ tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
+
+ // no warning if directory already exists
+ tg.must(robustio.RemoveAll(tg.path("home/go")))
+ tg.tempDir("home/go")
+ tg.run("get", "github.com/golang/example/hello")
+ tg.grepStderrNot(".", "expected no output on standard error")
+
+ // error if $HOME/go is a file
+ tg.must(robustio.RemoveAll(tg.path("home/go")))
+ tg.tempFile("home/go", "")
+ tg.runFail("get", "github.com/golang/example/hello")
+ tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
+}
+
func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go
new file mode 100644
index 0000000..6c39640
--- /dev/null
+++ b/src/cmd/go/internal/get/get.go
@@ -0,0 +1,639 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package get implements the “go get” command.
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/search"
+ "cmd/go/internal/str"
+ "cmd/go/internal/vcs"
+ "cmd/go/internal/web"
+ "cmd/go/internal/work"
+
+ "golang.org/x/mod/module"
+)
+
+var CmdGet = &base.Command{
+ UsageLine: "go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]",
+ Short: "download and install packages and dependencies",
+ Long: `
+Get downloads the packages named by the import paths, along with their
+dependencies. It then installs the named packages, like 'go install'.
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+The -f flag, valid only when -u is set, forces get -u not to verify that
+each package has been checked out from the source control repository
+implied by its import path. This can be useful if the source is a local fork
+of the original.
+
+The -fix flag instructs get to run the fix tool on the downloaded packages
+before resolving dependencies or building the code.
+
+The -t flag instructs get to also download the packages required to build
+the tests for the specified packages.
+
+The -u flag instructs get to use the network to update the named packages
+and their dependencies. By default, get uses the network to check out
+missing packages but does not use it to look for updates to existing packages.
+
+The -v flag enables verbose progress and debug output.
+
+Get also accepts build flags to control the installation. See 'go help build'.
+
+When checking out a new package, get creates the target directory
+GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
+get uses the first one. For more details see: 'go help gopath'.
+
+When checking out or updating a package, get looks for a branch or tag
+that matches the locally installed version of Go. The most important
+rule is that if the local installation is running version "go1", get
+searches for a branch or tag named "go1". If no such version exists
+it retrieves the default branch of the package.
+
+When go get checks out or updates a Git repository,
+it also updates any git submodules referenced by the repository.
+
+Get never checks out or updates code stored in vendor directories.
+
+For more about build flags, see 'go help build'.
+
+For more about specifying packages, see 'go help packages'.
+
+For more about how 'go get' finds source code to
+download, see 'go help importpath'.
+
+This text describes the behavior of get when using GOPATH
+to manage source code and dependencies.
+If instead the go command is running in module-aware mode,
+the details of get's flags and effects change, as does 'go help get'.
+See 'go help modules' and 'go help module-get'.
+
+See also: go build, go install, go clean.
+ `,
+}
+
+var HelpGopathGet = &base.Command{
+ UsageLine: "gopath-get",
+ Short: "legacy GOPATH go get",
+ Long: `
+The 'go get' command changes behavior depending on whether the
+go command is running in module-aware mode or legacy GOPATH mode.
+This help text, accessible as 'go help gopath-get' even in module-aware mode,
+describes 'go get' as it operates in legacy GOPATH mode.
+
+Usage: ` + CmdGet.UsageLine + `
+` + CmdGet.Long,
+}
+
+var (
+ getD = CmdGet.Flag.Bool("d", false, "")
+ getF = CmdGet.Flag.Bool("f", false, "")
+ getT = CmdGet.Flag.Bool("t", false, "")
+ getU = CmdGet.Flag.Bool("u", false, "")
+ getFix = CmdGet.Flag.Bool("fix", false, "")
+ getInsecure = CmdGet.Flag.Bool("insecure", false, "")
+)
+
+func init() {
+ work.AddBuildFlags(CmdGet, work.OmitModFlag|work.OmitModCommonFlags)
+ CmdGet.Run = runGet // break init loop
+}
+
+func runGet(ctx context.Context, cmd *base.Command, args []string) {
+ if cfg.ModulesEnabled {
+ // Should not happen: main.go should install the separate module-enabled get code.
+ base.Fatalf("go: modules not implemented")
+ }
+
+ work.BuildInit()
+
+ if *getF && !*getU {
+ base.Fatalf("go: cannot use -f flag without -u")
+ }
+ if *getInsecure {
+ base.Fatalf("go: -insecure flag is no longer supported; use GOINSECURE instead")
+ }
+
+ // Disable any prompting for passwords by Git itself.
+ // Only has an effect for 2.3.0 or later, but avoiding
+ // the prompt in earlier versions is just too hard.
+ // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep
+ // prompting.
+ // See golang.org/issue/9341 and golang.org/issue/12706.
+ if os.Getenv("GIT_TERMINAL_PROMPT") == "" {
+ os.Setenv("GIT_TERMINAL_PROMPT", "0")
+ }
+
+ // Also disable prompting for passwords by the 'ssh' subprocess spawned by
+ // Git, because apparently GIT_TERMINAL_PROMPT isn't sufficient to do that.
+ // Adding '-o BatchMode=yes' should do the trick.
+ //
+ // If a Git subprocess forks a child into the background to cache a new connection,
+ // that child keeps stdout/stderr open. After the Git subprocess exits,
+ // os /exec expects to be able to read from the stdout/stderr pipe
+ // until EOF to get all the data that the Git subprocess wrote before exiting.
+ // The EOF doesn't come until the child exits too, because the child
+ // is holding the write end of the pipe.
+ // This is unfortunate, but it has come up at least twice
+ // (see golang.org/issue/13453 and golang.org/issue/16104)
+ // and confuses users when it does.
+ // If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND,
+ // assume they know what they are doing and don't step on it.
+ // But default to turning off ControlMaster.
+ if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
+ os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no -o BatchMode=yes")
+ }
+
+ // And one more source of Git prompts: the Git Credential Manager Core for Windows.
+ //
+ // See https://github.com/microsoft/Git-Credential-Manager-Core/blob/master/docs/environment.md#gcm_interactive.
+ if os.Getenv("GCM_INTERACTIVE") == "" {
+ os.Setenv("GCM_INTERACTIVE", "never")
+ }
+
+ // Phase 1. Download/update.
+ var stk load.ImportStack
+ mode := 0
+ if *getT {
+ mode |= load.GetTestDeps
+ }
+ for _, pkg := range downloadPaths(args) {
+ download(ctx, pkg, nil, &stk, mode)
+ }
+ base.ExitIfErrors()
+
+ // Phase 2. Rescan packages and re-evaluate args list.
+
+ // Code we downloaded and all code that depends on it
+ // needs to be evicted from the package cache so that
+ // the information will be recomputed. Instead of keeping
+ // track of the reverse dependency information, evict
+ // everything.
+ load.ClearPackageCache()
+
+ pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
+ load.CheckPackageErrors(pkgs)
+
+ // Phase 3. Install.
+ if *getD {
+ // Download only.
+ // Check delayed until now so that downloadPaths
+ // and CheckPackageErrors have a chance to print errors.
+ return
+ }
+
+ work.InstallPackages(ctx, args, pkgs)
+}
+
+// downloadPaths prepares the list of paths to pass to download.
+// It expands ... patterns that can be expanded. If there is no match
+// for a particular pattern, downloadPaths leaves it in the result list,
+// in the hope that we can figure out the repository from the
+// initial ...-free prefix.
+func downloadPaths(patterns []string) []string {
+ for _, arg := range patterns {
+ if strings.Contains(arg, "@") {
+ base.Fatalf("go: can only use path@version syntax with 'go get' and 'go install' in module-aware mode")
+ }
+
+ // Guard against 'go get x.go', a common mistake.
+ // Note that package and module paths may end with '.go', so only print an error
+ // if the argument has no slash or refers to an existing file.
+ if strings.HasSuffix(arg, ".go") {
+ if !strings.Contains(arg, "/") {
+ base.Errorf("go: %s: arguments must be package or module paths", arg)
+ continue
+ }
+ if fi, err := os.Stat(arg); err == nil && !fi.IsDir() {
+ base.Errorf("go: %s exists as a file, but 'go get' requires package arguments", arg)
+ }
+ }
+ }
+ base.ExitIfErrors()
+
+ var pkgs []string
+ for _, m := range search.ImportPathsQuiet(patterns) {
+ if len(m.Pkgs) == 0 && strings.Contains(m.Pattern(), "...") {
+ pkgs = append(pkgs, m.Pattern())
+ } else {
+ pkgs = append(pkgs, m.Pkgs...)
+ }
+ }
+ return pkgs
+}
+
+// downloadCache records the import paths we have already
+// considered during the download, to avoid duplicate work when
+// there is more than one dependency sequence leading to
+// a particular package.
+var downloadCache = map[string]bool{}
+
+// downloadRootCache records the version control repository
+// root directories we have already considered during the download.
+// For example, all the packages in the github.com/google/codesearch repo
+// share the same root (the directory for that path), and we only need
+// to run the hg commands to consider each repository once.
+var downloadRootCache = map[string]bool{}
+
+// download runs the download half of the get command
+// for the package or pattern named by the argument.
+func download(ctx context.Context, arg string, parent *load.Package, stk *load.ImportStack, mode int) {
+ if mode&load.ResolveImport != 0 {
+ // Caller is responsible for expanding vendor paths.
+ panic("internal error: download mode has useVendor set")
+ }
+ load1 := func(path string, mode int) *load.Package {
+ if parent == nil {
+ mode := 0 // don't do module or vendor resolution
+ return load.LoadPackage(ctx, load.PackageOpts{}, path, base.Cwd(), stk, nil, mode)
+ }
+ p, err := load.LoadImport(ctx, load.PackageOpts{}, path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
+ if err != nil {
+ base.Errorf("%s", err)
+ }
+ return p
+ }
+
+ p := load1(arg, mode)
+ if p.Error != nil && p.Error.Hard {
+ base.Errorf("%s", p.Error)
+ return
+ }
+
+ // loadPackage inferred the canonical ImportPath from arg.
+ // Use that in the following to prevent hysteresis effects
+ // in e.g. downloadCache and packageCache.
+ // This allows invocations such as:
+ // mkdir -p $GOPATH/src/github.com/user
+ // cd $GOPATH/src/github.com/user
+ // go get ./foo
+ // see: golang.org/issue/9767
+ arg = p.ImportPath
+
+ // There's nothing to do if this is a package in the standard library.
+ if p.Standard {
+ return
+ }
+
+ // Only process each package once.
+ // (Unless we're fetching test dependencies for this package,
+ // in which case we want to process it again.)
+ if downloadCache[arg] && mode&load.GetTestDeps == 0 {
+ return
+ }
+ downloadCache[arg] = true
+
+ pkgs := []*load.Package{p}
+ wildcardOkay := len(*stk) == 0
+ isWildcard := false
+
+ // Download if the package is missing, or update if we're using -u.
+ if p.Dir == "" || *getU {
+ // The actual download.
+ stk.Push(load.ImportInfo{Pkg: arg})
+ err := downloadPackage(p)
+ if err != nil {
+ base.Errorf("%s", &load.PackageError{ImportStack: stk.Copy(), Err: err})
+ stk.Pop()
+ return
+ }
+ stk.Pop()
+
+ args := []string{arg}
+ // If the argument has a wildcard in it, re-evaluate the wildcard.
+ // We delay this until after reloadPackage so that the old entry
+ // for p has been replaced in the package cache.
+ if wildcardOkay && strings.Contains(arg, "...") {
+ match := search.NewMatch(arg)
+ if match.IsLocal() {
+ noModRoots := []string{} // We're in gopath mode, so there are no modroots.
+ match.MatchDirs(noModRoots)
+ args = match.Dirs
+ } else {
+ match.MatchPackages()
+ args = match.Pkgs
+ }
+ for _, err := range match.Errs {
+ base.Errorf("%s", err)
+ }
+ isWildcard = true
+ }
+
+ // Clear all relevant package cache entries before
+ // doing any new loads.
+ load.ClearPackageCachePartial(args)
+
+ pkgs = pkgs[:0]
+ for _, arg := range args {
+ // Note: load calls loadPackage or loadImport,
+ // which push arg onto stk already.
+ // Do not push here too, or else stk will say arg imports arg.
+ p := load1(arg, mode)
+ if p.Error != nil {
+ base.Errorf("%s", p.Error)
+ continue
+ }
+ pkgs = append(pkgs, p)
+ }
+ }
+
+ // Process package, which might now be multiple packages
+ // due to wildcard expansion.
+ for _, p := range pkgs {
+ if *getFix {
+ files := base.RelPaths(p.InternalAllGoFiles())
+ base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files))
+
+ // The imports might have changed, so reload again.
+ p = load.ReloadPackageNoFlags(arg, stk)
+ if p.Error != nil {
+ base.Errorf("%s", p.Error)
+ return
+ }
+ }
+
+ if isWildcard {
+ // Report both the real package and the
+ // wildcard in any error message.
+ stk.Push(load.ImportInfo{Pkg: p.ImportPath})
+ }
+
+ // Process dependencies, now that we know what they are.
+ imports := p.Imports
+ if mode&load.GetTestDeps != 0 {
+ // Process test dependencies when -t is specified.
+ // (But don't get test dependencies for test dependencies:
+ // we always pass mode 0 to the recursive calls below.)
+ imports = str.StringList(imports, p.TestImports, p.XTestImports)
+ }
+ for i, path := range imports {
+ if path == "C" {
+ continue
+ }
+ // Fail fast on import naming full vendor path.
+ // Otherwise expand path as needed for test imports.
+ // Note that p.Imports can have additional entries beyond p.Internal.Build.Imports.
+ orig := path
+ if i < len(p.Internal.Build.Imports) {
+ orig = p.Internal.Build.Imports[i]
+ }
+ if j, ok := load.FindVendor(orig); ok {
+ stk.Push(load.ImportInfo{Pkg: path})
+ err := &load.PackageError{
+ ImportStack: stk.Copy(),
+ Err: load.ImportErrorf(path, "%s must be imported as %s", path, path[j+len("vendor/"):]),
+ }
+ stk.Pop()
+ base.Errorf("%s", err)
+ continue
+ }
+ // If this is a test import, apply module and vendor lookup now.
+ // We cannot pass ResolveImport to download, because
+ // download does caching based on the value of path,
+ // so it must be the fully qualified path already.
+ if i >= len(p.Imports) {
+ path = load.ResolveImportPath(p, path)
+ }
+ download(ctx, path, p, stk, 0)
+ }
+
+ if isWildcard {
+ stk.Pop()
+ }
+ }
+}
+
+// downloadPackage runs the create or download command
+// to make the first copy of or update a copy of the given package.
+func downloadPackage(p *load.Package) error {
+ var (
+ vcsCmd *vcs.Cmd
+ repo, rootPath, repoDir string
+ err error
+ blindRepo bool // set if the repo has unusual configuration
+ )
+
+ // p can be either a real package, or a pseudo-package whose “import path” is
+ // actually a wildcard pattern.
+ // Trim the path at the element containing the first wildcard,
+ // and hope that it applies to the wildcarded parts too.
+ // This makes 'go get rsc.io/pdf/...' work in a fresh GOPATH.
+ importPrefix := p.ImportPath
+ if i := strings.Index(importPrefix, "..."); i >= 0 {
+ slash := strings.LastIndexByte(importPrefix[:i], '/')
+ if slash < 0 {
+ return fmt.Errorf("cannot expand ... in %q", p.ImportPath)
+ }
+ importPrefix = importPrefix[:slash]
+ }
+ if err := checkImportPath(importPrefix); err != nil {
+ return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err)
+ }
+ security := web.SecureOnly
+ if module.MatchPrefixPatterns(cfg.GOINSECURE, importPrefix) {
+ security = web.Insecure
+ }
+
+ if p.Internal.Build.SrcRoot != "" {
+ // Directory exists. Look for checkout along path to src.
+
+ repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot)
+ if err != nil {
+ return err
+ }
+ if !str.HasFilePathPrefix(repoDir, p.Internal.Build.SrcRoot) {
+ panic(fmt.Sprintf("repository %q not in source root %q", repo, p.Internal.Build.SrcRoot))
+ }
+ rootPath = str.TrimFilePathPrefix(repoDir, p.Internal.Build.SrcRoot)
+ if err := vcs.CheckGOVCS(vcsCmd, rootPath); err != nil {
+ return err
+ }
+
+ repo = "<local>" // should be unused; make distinctive
+
+ // Double-check where it came from.
+ if *getU && vcsCmd.RemoteRepo != nil {
+ dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
+ remote, err := vcsCmd.RemoteRepo(vcsCmd, dir)
+ if err != nil {
+ // Proceed anyway. The package is present; we likely just don't understand
+ // the repo configuration (e.g. unusual remote protocol).
+ blindRepo = true
+ }
+ repo = remote
+ if !*getF && err == nil {
+ if rr, err := vcs.RepoRootForImportPath(importPrefix, vcs.IgnoreMod, security); err == nil {
+ repo := rr.Repo
+ if rr.VCS.ResolveRepo != nil {
+ resolved, err := rr.VCS.ResolveRepo(rr.VCS, dir, repo)
+ if err == nil {
+ repo = resolved
+ }
+ }
+ if remote != repo && rr.IsCustom {
+ return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.Root, repo, dir, remote)
+ }
+ }
+ }
+ }
+ } else {
+ // Analyze the import path to determine the version control system,
+ // repository, and the import path for the root of the repository.
+ rr, err := vcs.RepoRootForImportPath(importPrefix, vcs.IgnoreMod, security)
+ if err != nil {
+ return err
+ }
+ vcsCmd, repo, rootPath = rr.VCS, rr.Repo, rr.Root
+ }
+ if !blindRepo && !vcsCmd.IsSecure(repo) && security != web.Insecure {
+ return fmt.Errorf("cannot download: %v uses insecure protocol", repo)
+ }
+
+ if p.Internal.Build.SrcRoot == "" {
+ // Package not found. Put in first directory of $GOPATH.
+ list := filepath.SplitList(cfg.BuildContext.GOPATH)
+ if len(list) == 0 {
+ return fmt.Errorf("cannot download: $GOPATH not set. For more details see: 'go help gopath'")
+ }
+ // Guard against people setting GOPATH=$GOROOT.
+ if filepath.Clean(list[0]) == filepath.Clean(cfg.GOROOT) {
+ return fmt.Errorf("cannot download: $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
+ }
+ if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
+ return fmt.Errorf("cannot download: %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
+ }
+ p.Internal.Build.Root = list[0]
+ p.Internal.Build.SrcRoot = filepath.Join(list[0], "src")
+ p.Internal.Build.PkgRoot = filepath.Join(list[0], "pkg")
+ }
+ root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
+
+ if err := vcs.CheckNested(vcsCmd, root, p.Internal.Build.SrcRoot); err != nil {
+ return err
+ }
+
+ // If we've considered this repository already, don't do it again.
+ if downloadRootCache[root] {
+ return nil
+ }
+ downloadRootCache[root] = true
+
+ if cfg.BuildV {
+ fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
+ }
+
+ // Check that this is an appropriate place for the repo to be checked out.
+ // The target directory must either not exist or have a repo checked out already.
+ meta := filepath.Join(root, "."+vcsCmd.Cmd)
+ if _, err := os.Stat(meta); err != nil {
+ // Metadata file or directory does not exist. Prepare to checkout new copy.
+ // Some version control tools require the target directory not to exist.
+ // We require that too, just to avoid stepping on existing work.
+ if _, err := os.Stat(root); err == nil {
+ return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
+ }
+
+ _, err := os.Stat(p.Internal.Build.Root)
+ gopathExisted := err == nil
+
+ // Some version control tools require the parent of the target to exist.
+ parent, _ := filepath.Split(root)
+ if err = os.MkdirAll(parent, 0777); err != nil {
+ return err
+ }
+ if cfg.BuildV && !gopathExisted && p.Internal.Build.Root == cfg.BuildContext.GOPATH {
+ fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.Internal.Build.Root)
+ }
+
+ if err = vcsCmd.Create(root, repo); err != nil {
+ return err
+ }
+ } else {
+ // Metadata directory does exist; download incremental updates.
+ if err = vcsCmd.Download(root); err != nil {
+ return err
+ }
+ }
+
+ if cfg.BuildN {
+ // Do not show tag sync in -n; it's noise more than anything,
+ // and since we're not running commands, no tag will be found.
+ // But avoid printing nothing.
+ fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcsCmd.Cmd)
+ return nil
+ }
+
+ // Select and sync to appropriate version of the repository.
+ tags, err := vcsCmd.Tags(root)
+ if err != nil {
+ return err
+ }
+ vers := runtime.Version()
+ if i := strings.Index(vers, " "); i >= 0 {
+ vers = vers[:i]
+ }
+ if err := vcsCmd.TagSync(root, selectTag(vers, tags)); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// selectTag returns the closest matching tag for a given version.
+// Closest means the latest one that is not after the current release.
+// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
+// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
+// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
+//
+// NOTE(rsc): Eventually we will need to decide on some logic here.
+// For now, there is only "go1". This matches the docs in go help get.
+func selectTag(goVersion string, tags []string) (match string) {
+ for _, t := range tags {
+ if t == "go1" {
+ return "go1"
+ }
+ }
+ return ""
+}
+
+// checkImportPath is like module.CheckImportPath, but it forbids leading dots
+// in path elements. This can lead to 'go get' creating .git and other VCS
+// directories in places we might run VCS tools later.
+func checkImportPath(path string) error {
+ if err := module.CheckImportPath(path); err != nil {
+ return err
+ }
+ checkElem := func(elem string) error {
+ if elem[0] == '.' {
+ return fmt.Errorf("malformed import path %q: leading dot in path element", path)
+ }
+ return nil
+ }
+ elemStart := 0
+ for i, r := range path {
+ if r == '/' {
+ if err := checkElem(path[elemStart:]); err != nil {
+ return err
+ }
+ elemStart = i + 1
+ }
+ }
+ if err := checkElem(path[elemStart:]); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/src/cmd/go/internal/get/tag_test.go b/src/cmd/go/internal/get/tag_test.go
new file mode 100644
index 0000000..9a25dfa
--- /dev/null
+++ b/src/cmd/go/internal/get/tag_test.go
@@ -0,0 +1,100 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package get
+
+import "testing"
+
+var selectTagTestTags = []string{
+ "go.r58",
+ "go.r58.1",
+ "go.r59",
+ "go.r59.1",
+ "go.r61",
+ "go.r61.1",
+ "go.weekly.2010-01-02",
+ "go.weekly.2011-10-12",
+ "go.weekly.2011-10-12.1",
+ "go.weekly.2011-10-14",
+ "go.weekly.2011-11-01",
+ "go1",
+ "go1.0.1",
+ "go1.999",
+ "go1.9.2",
+ "go5",
+
+ // these should be ignored:
+ "release.r59",
+ "release.r59.1",
+ "release",
+ "weekly.2011-10-12",
+ "weekly.2011-10-12.1",
+ "weekly",
+ "foo",
+ "bar",
+ "go.f00",
+ "go!r60",
+ "go.1999-01-01",
+ "go.2x",
+ "go.20000000000000",
+ "go.2.",
+ "go.2.0",
+ "go2x",
+ "go20000000000000",
+ "go2.",
+ "go2.0",
+}
+
+var selectTagTests = []struct {
+ version string
+ selected string
+}{
+ /*
+ {"release.r57", ""},
+ {"release.r58.2", "go.r58.1"},
+ {"release.r59", "go.r59"},
+ {"release.r59.1", "go.r59.1"},
+ {"release.r60", "go.r59.1"},
+ {"release.r60.1", "go.r59.1"},
+ {"release.r61", "go.r61"},
+ {"release.r66", "go.r61.1"},
+ {"weekly.2010-01-01", ""},
+ {"weekly.2010-01-02", "go.weekly.2010-01-02"},
+ {"weekly.2010-01-02.1", "go.weekly.2010-01-02"},
+ {"weekly.2010-01-03", "go.weekly.2010-01-02"},
+ {"weekly.2011-10-12", "go.weekly.2011-10-12"},
+ {"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"},
+ {"weekly.2011-10-13", "go.weekly.2011-10-12.1"},
+ {"weekly.2011-10-14", "go.weekly.2011-10-14"},
+ {"weekly.2011-10-14.1", "go.weekly.2011-10-14"},
+ {"weekly.2011-11-01", "go.weekly.2011-11-01"},
+ {"weekly.2014-01-01", "go.weekly.2011-11-01"},
+ {"weekly.3000-01-01", "go.weekly.2011-11-01"},
+ {"go1", "go1"},
+ {"go1.1", "go1.0.1"},
+ {"go1.998", "go1.9.2"},
+ {"go1.1000", "go1.999"},
+ {"go6", "go5"},
+
+ // faulty versions:
+ {"release.f00", ""},
+ {"weekly.1999-01-01", ""},
+ {"junk", ""},
+ {"", ""},
+ {"go2x", ""},
+ {"go200000000000", ""},
+ {"go2.", ""},
+ {"go2.0", ""},
+ */
+ {"anything", "go1"},
+}
+
+func TestSelectTag(t *testing.T) {
+ for _, c := range selectTagTests {
+ selected := selectTag(c.version, selectTagTestTags)
+ if selected != c.selected {
+ t.Errorf("selectTag(%q) = %q, want %q", c.version, selected, c.selected)
+ }
+ }
+}
diff --git a/src/cmd/go/internal/help/help.go b/src/cmd/go/internal/help/help.go
index 4f2607f..229ebc3 100644
--- a/src/cmd/go/internal/help/help.go
+++ b/src/cmd/go/internal/help/help.go
@@ -17,6 +17,7 @@ import (
"cmd/go/internal/base"
"cmd/internal/telemetry/counter"
+ "cmd/go/internal/modload"
)
var counterErrorsHelpUnknownTopic = counter.New("go/errors:help-unknown-topic")
@@ -37,6 +38,12 @@ func Help(w io.Writer, args []string) {
usage := &base.Command{Long: buf.String()}
cmds := []*base.Command{usage}
for _, cmd := range base.Go.Commands {
+ // Avoid duplication of the "get" documentation.
+ if cmd.UsageLine == "module-get" && modload.Enabled() {
+ continue
+ } else if cmd.UsageLine == "gopath-get" && !modload.Enabled() {
+ continue
+ }
cmds = append(cmds, cmd)
cmds = append(cmds, cmd.Commands...)
}
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 1f79154..86a9f9c 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -455,6 +455,7 @@ type PackageError struct {
Pos string // position of error
Err error // the error itself
IsImportCycle bool // the error is an import cycle
+ Hard bool // whether the error is soft or hard; soft errors are ignored in some places
alwaysPrintStack bool // whether to always print the ImportStack
}
@@ -634,6 +635,51 @@ func (sp *ImportStack) shorterThan(t []string) bool {
// we return the same pointer each time.
var packageCache = map[string]*Package{}
+// ClearPackageCache clears the in-memory package cache and the preload caches.
+// It is only for use by GOPATH-based "go get".
+// TODO(jayconrod): When GOPATH-based "go get" is removed, delete this function.
+func ClearPackageCache() {
+ clear(packageCache)
+ resolvedImportCache.Clear()
+ packageDataCache.Clear()
+}
+
+// ClearPackageCachePartial clears packages with the given import paths from the
+// in-memory package cache and the preload caches. It is only for use by
+// GOPATH-based "go get".
+// TODO(jayconrod): When GOPATH-based "go get" is removed, delete this function.
+func ClearPackageCachePartial(args []string) {
+ shouldDelete := make(map[string]bool)
+ for _, arg := range args {
+ shouldDelete[arg] = true
+ if p := packageCache[arg]; p != nil {
+ delete(packageCache, arg)
+ }
+ }
+ resolvedImportCache.DeleteIf(func(key importSpec) bool {
+ return shouldDelete[key.path]
+ })
+ packageDataCache.DeleteIf(func(key string) bool {
+ return shouldDelete[key]
+ })
+}
+
+// ReloadPackageNoFlags is like LoadImport but makes sure
+// not to use the package cache.
+// It is only for use by GOPATH-based "go get".
+// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
+func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package {
+ p := packageCache[arg]
+ if p != nil {
+ delete(packageCache, arg)
+ resolvedImportCache.DeleteIf(func(key importSpec) bool {
+ return key.path == p.ImportPath
+ })
+ packageDataCache.Delete(p.ImportPath)
+ }
+ return LoadPackage(context.TODO(), PackageOpts{}, arg, base.Cwd(), stk, nil, 0)
+}
+
// dirToImportPath returns the pseudo-import path we use for a package
// outside the Go path. It begins with _/ and then contains the full path
// to the directory. If the package lives in c:\home\gopher\my\pkg then
@@ -685,6 +731,20 @@ const (
cmdlinePkgLiteral
)
+// LoadImport scans the directory named by path, which must be an import path,
+// but possibly a local import path (an absolute file system path or one beginning
+// with ./ or ../). A local relative path is interpreted relative to srcDir.
+// It returns a *Package describing the package found in that directory.
+// LoadImport does not set tool flags and should only be used by
+// this package, as part of a bigger load operation, and by GOPATH-based "go get".
+// TODO(rsc): When GOPATH-based "go get" is removed, unexport this function.
+// The returned PackageError, if any, describes why parent is not allowed
+// to import the named package, with the error referring to importPos.
+// The PackageError can only be non-nil when parent is not nil.
+func LoadImport(ctx context.Context, opts PackageOpts, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
+ return loadImport(ctx, opts, nil, path, srcDir, parent, stk, importPos, mode)
+}
+
// LoadPackage does Load import, but without a parent package load context
func LoadPackage(ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
p, err := loadImport(ctx, opts, nil, path, srcDir, nil, stk, importPos, mode)
diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go
index 31e9244..698c45b 100644
--- a/src/cmd/go/internal/modget/get.go
+++ b/src/cmd/go/internal/modget/get.go
@@ -129,6 +129,23 @@ See also: go build, go install, go clean, go mod.
`,
}
+// Note that this help text is a stopgap to make the module-aware get help text
+// available even in non-module settings. It should be deleted when the old get
+// is deleted. It should NOT be considered to set a precedent of having hierarchical
+// help names with dashes.
+var HelpModuleGet = &base.Command{
+ UsageLine: "module-get",
+ Short: "module-aware go get",
+ Long: `
+The 'go get' command changes behavior depending on whether the
+go command is running in module-aware mode or legacy GOPATH mode.
+This help text, accessible as 'go help module-get' even in legacy GOPATH mode,
+describes 'go get' as it operates in module-aware mode.
+
+Usage: ` + CmdGet.UsageLine + `
+` + CmdGet.Long,
+}
+
var HelpVCS = &base.Command{
UsageLine: "vcs",
Short: "controlling version control with GOVCS",
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
index 7e081eb..6b29068 100644
--- a/src/cmd/go/internal/vcs/vcs.go
+++ b/src/cmd/go/internal/vcs/vcs.go
@@ -1061,11 +1061,11 @@ var defaultGOVCS = govcsConfig{
{"public", []string{"git", "hg"}},
}
-// checkGOVCS checks whether the policy defined by the environment variable
+// CheckGOVCS checks whether the policy defined by the environment variable
// GOVCS allows the given vcs command to be used with the given repository
// root path. Note that root may not be a real package or module path; it's
// the same as the root path in the go-import meta tag.
-func checkGOVCS(vcs *Cmd, root string) error {
+func CheckGOVCS(vcs *Cmd, root string) error {
if vcs == vcsMod {
// Direct module (proxy protocol) fetches don't
// involve an external version control system
@@ -1093,6 +1093,37 @@ func checkGOVCS(vcs *Cmd, root string) error {
return nil
}
+// CheckNested checks for an incorrectly-nested VCS-inside-VCS
+// situation for dir, checking parents up until srcRoot.
+func CheckNested(vcs *Cmd, dir, srcRoot string) error {
+ if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
+ return fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
+ }
+
+ otherDir := dir
+ for len(otherDir) > len(srcRoot) {
+ for _, otherVCS := range vcsList {
+ if isVCSRoot(otherDir, otherVCS.RootNames) {
+ // Allow expected vcs in original dir.
+ if otherDir == dir && otherVCS == vcs {
+ continue
+ }
+ // Otherwise, we have one VCS inside a different VCS.
+ return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.Cmd, otherDir, otherVCS.Cmd)
+ }
+ }
+ // Move to parent.
+ newDir := filepath.Dir(otherDir)
+ if len(newDir) >= len(otherDir) {
+ // Shouldn't happen, but just in case, stop.
+ break
+ }
+ otherDir = newDir
+ }
+
+ return nil
+}
+
// RepoRoot describes the repository root for a tree of source code.
type RepoRoot struct {
Repo string // repository URL, including scheme
@@ -1209,7 +1240,7 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
if vcs == nil {
return nil, fmt.Errorf("unknown version control system %q", match["vcs"])
}
- if err := checkGOVCS(vcs, match["root"]); err != nil {
+ if err := CheckGOVCS(vcs, match["root"]); err != nil {
return nil, err
}
var repoURL string
@@ -1398,7 +1429,7 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
}
}
- if err := checkGOVCS(vcs, mmi.Prefix); err != nil {
+ if err := CheckGOVCS(vcs, mmi.Prefix); err != nil {
return nil, err
}
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index e81969c..2246d11 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -27,6 +27,7 @@ import (
"cmd/go/internal/fix"
"cmd/go/internal/fmtcmd"
"cmd/go/internal/generate"
+ "cmd/go/internal/get"
"cmd/go/internal/help"
"cmd/go/internal/list"
"cmd/go/internal/modcmd"
@@ -80,9 +81,11 @@ func init() {
help.HelpGoAuth,
modload.HelpGoMod,
help.HelpGopath,
+ get.HelpGopathGet,
modfetch.HelpGoproxy,
help.HelpImportPath,
modload.HelpModules,
+ modget.HelpModuleGet,
modfetch.HelpModuleAuth,
help.HelpPackages,
modfetch.HelpPrivate,
@@ -119,6 +122,13 @@ func main() {
base.Usage()
}
+ if args[0] == "get" || args[0] == "help" {
+ if !modload.WillBeEnabled() {
+ // Replace module-aware get with GOPATH get if appropriate.
+ *modget.CmdGet = *get.CmdGet
+ }
+ }
+
cfg.CmdName = args[0] // for error messages
if args[0] == "help" {
counter.Inc("go/subcommand:" + strings.Join(append([]string{"help"}, args[1:]...), "-"))
diff --git a/src/cmd/go/testdata/script/get_404_meta.txt b/src/cmd/go/testdata/script/get_404_meta.txt
index 7665155..4ffbdeb 100644
--- a/src/cmd/go/testdata/script/get_404_meta.txt
+++ b/src/cmd/go/testdata/script/get_404_meta.txt
@@ -4,6 +4,9 @@
[!git] skip
env GONOSUMDB=bazil.org,github.com,golang.org
+env GO111MODULE=off
+go get -d bazil.org/fuse/fs/fstestutil
+
env GO111MODULE=on
env GOPROXY=direct
go get bazil.org/fuse/fs/fstestutil
diff --git a/src/cmd/go/testdata/script/get_brace.txt b/src/cmd/go/testdata/script/get_brace.txt
new file mode 100644
index 0000000..34f66a6
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_brace.txt
@@ -0,0 +1,51 @@
+env GO111MODULE=off
+
+[!git] skip
+
+# Set up some empty repositories.
+cd $WORK/_origin/foo
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+cd $WORK
+cd '_origin/{confusing}'
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+# Clone the empty repositories into GOPATH.
+# This tells the Go command where to find them: it takes the place of a user's meta-tag redirector.
+mkdir $GOPATH/src/example.com
+cd $GOPATH/src/example.com
+exec git clone $WORK/_origin/foo
+exec git clone $WORK/_origin/{confusing}
+
+# Commit contents to the repositories.
+cd $WORK/_origin/foo
+exec git add main.go
+exec git commit -m 'add main'
+
+cd $WORK
+cd '_origin/{confusing}'
+exec git add confusing.go
+exec git commit -m 'just try to delete this!'
+
+# 'go get' should refuse to download or update the confusingly-named repo.
+cd $GOPATH/src/example.com/foo
+! go get -u 'example.com/{confusing}'
+stderr 'invalid char'
+! go get -u example.com/foo
+stderr 'invalid import path'
+! exists example.com/{confusing}
+
+-- $WORK/_origin/foo/main.go --
+package main
+import _ "example.com/{confusing}"
+
+func main() {}
+
+-- $WORK/_origin/{confusing}/confusing.go --
+package confusing
diff --git a/src/cmd/go/testdata/script/get_custom_domain_wildcard.txt b/src/cmd/go/testdata/script/get_custom_domain_wildcard.txt
new file mode 100644
index 0000000..45ab524
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_custom_domain_wildcard.txt
@@ -0,0 +1,6 @@
+[!net:rsc.io] skip
+[!git] skip
+env GO111MODULE=off
+
+go get -u rsc.io/pdf/...
+exists $GOPATH/bin/pdfpasswd$GOEXE
diff --git a/src/cmd/go/testdata/script/get_dash_t.txt b/src/cmd/go/testdata/script/get_dash_t.txt
new file mode 100644
index 0000000..8f3a036
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_dash_t.txt
@@ -0,0 +1,9 @@
+# Tests issue 8181
+
+[!net:github.com] skip
+[!git] skip
+env GO111MODULE=off
+
+go get -v -t github.com/rsc/go-get-issue-8181/a github.com/rsc/go-get-issue-8181/b
+go list -test -deps github.com/rsc/go-get-issue-8181/b
+stdout 'x/build/gerrit'
diff --git a/src/cmd/go/testdata/script/get_domain_root.txt b/src/cmd/go/testdata/script/get_domain_root.txt
new file mode 100644
index 0000000..dfcea86
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_domain_root.txt
@@ -0,0 +1,20 @@
+# Tests issue #9357
+# go get foo.io (not foo.io/subdir) was not working consistently.
+
+[!net:go-get-issue-9357.appspot.com] skip
+[!git] skip
+env GO111MODULE=off
+
+# go-get-issue-9357.appspot.com is running
+# the code at github.com/rsc/go-get-issue-9357,
+# a trivial Go on App Engine app that serves a
+# <meta> tag for the domain root.
+go get -d go-get-issue-9357.appspot.com
+go get go-get-issue-9357.appspot.com
+go get -u go-get-issue-9357.appspot.com
+
+rm $GOPATH/src/go-get-issue-9357.appspot.com
+go get go-get-issue-9357.appspot.com
+
+rm $GOPATH/src/go-get-issue-9357.appspot.com
+go get -u go-get-issue-9357.appspot.com
diff --git a/src/cmd/go/testdata/script/get_dot_slash_download.txt b/src/cmd/go/testdata/script/get_dot_slash_download.txt
new file mode 100644
index 0000000..6dbd118
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_dot_slash_download.txt
@@ -0,0 +1,10 @@
+[!net:rsc.io] skip
+[!git] skip
+env GO111MODULE=off
+
+# Tests Issues #9797 and #19769
+
+mkdir $WORK/tmp/src/rsc.io
+env GOPATH=$WORK/tmp
+cd $WORK/tmp/src/rsc.io
+go get ./pprof_mac_fix
diff --git a/src/cmd/go/testdata/script/get_dotfiles.txt b/src/cmd/go/testdata/script/get_dotfiles.txt
new file mode 100644
index 0000000..676a044
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_dotfiles.txt
@@ -0,0 +1,64 @@
+env GO111MODULE=off
+[short] skip
+
+[!git] skip
+
+# Set up a benign repository and a repository with a dotfile name.
+cd $WORK/_origin/foo
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+cd $WORK/_origin/.hidden
+exec git init
+exec git config user.name 'Nameless Gopher'
+exec git config user.email 'nobody@golang.org'
+exec git commit --allow-empty -m 'create master branch'
+
+# Clone the empty repositories into GOPATH.
+# This tells the Go command where to find them: it takes the place of a user's meta-tag redirector.
+mkdir $GOPATH/src/example.com
+cd $GOPATH/src/example.com
+exec git clone $WORK/_origin/foo
+exec git clone $WORK/_origin/.hidden
+
+# Add a benign commit.
+cd $WORK/_origin/foo
+cp _ok/main.go main.go
+exec git add main.go
+exec git commit -m 'add ok'
+
+# 'go get' should install the benign commit.
+cd $GOPATH
+go get -u example.com/foo
+
+# Now sneak in an import of a dotfile path.
+cd $WORK/_origin/.hidden
+exec git add hidden.go
+exec git commit -m 'nothing to see here, move along'
+
+cd $WORK/_origin/foo
+cp _sneaky/main.go main.go
+exec git add main.go
+exec git commit -m 'fix typo (heh heh heh)'
+
+# 'go get -u' should refuse to download or update the dotfile-named repo.
+cd $GOPATH/src/example.com/foo
+! go get -u example.com/foo
+stderr 'leading dot'
+! exists example.com/.hidden/hidden.go
+
+-- $WORK/_origin/foo/_ok/main.go --
+package main
+
+func main() {}
+
+-- $WORK/_origin/foo/_sneaky/main.go --
+package main
+import _ "example.com/.hidden"
+
+func main() {}
+
+-- $WORK/_origin/.hidden/hidden.go --
+package hidden
diff --git a/src/cmd/go/testdata/script/get_go_file.txt b/src/cmd/go/testdata/script/get_go_file.txt
new file mode 100644
index 0000000..f6d0de4
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_go_file.txt
@@ -0,0 +1,60 @@
+# Tests Issue #38478
+# Tests that go get in GOPATH mode returns a specific error if the argument
+# ends with '.go', and either has no slash or refers to an existing file.
+
+env GO111MODULE=off
+
+# argument doesn't have .go suffix
+go get -d test
+
+# argument has .go suffix, is a file and exists
+! go get -d test.go
+stderr 'go: test.go: arguments must be package or module paths'
+
+# argument has .go suffix, doesn't exist and has no slashes
+! go get -d test_missing.go
+stderr 'go: test_missing.go: arguments must be package or module paths'
+
+# argument has .go suffix, is a file and exists in sub-directory
+! go get -d test/test.go
+stderr 'go: test/test.go exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, doesn't exist and has slashes
+! go get -d test/test_missing.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+
+# argument has .go suffix, is a symlink and exists
+[symlink] symlink test_sym.go -> test.go
+[symlink] ! go get -d test_sym.go
+[symlink] stderr 'go: test_sym.go: arguments must be package or module paths'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a symlink and exists in sub-directory
+[symlink] symlink test/test_sym.go -> test.go
+[symlink] ! go get -d test/test_sym.go
+[symlink] stderr 'go: test/test_sym.go exists as a file, but ''go get'' requires package arguments'
+[symlink] rm test_sym.go
+
+# argument has .go suffix, is a directory and exists
+mkdir test_dir.go
+! go get -d test_dir.go
+stderr 'go: test_dir.go: arguments must be package or module paths'
+rm test_dir.go
+
+# argument has .go suffix, is a directory and exists in sub-directory
+mkdir test/test_dir.go
+! go get -d test/test_dir.go
+! stderr 'arguments must be package or module paths'
+! stderr 'exists as a file, but ''go get'' requires package arguments'
+rm test/test_dir.go
+
+
+-- test.go --
+package main
+func main() {println("test")}
+
+
+-- test/test.go --
+package main
+func main() {println("test")}
diff --git a/src/cmd/go/testdata/script/get_goroot.txt b/src/cmd/go/testdata/script/get_goroot.txt
new file mode 100644
index 0000000..7510692
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_goroot.txt
@@ -0,0 +1,53 @@
+[!net:github.com] skip
+env GO111MODULE=off
+
+# Issue 4186. go get cannot be used to download packages to $GOROOT.
+# Test that without GOPATH set, go get should fail.
+
+# Fails because GOROOT=GOPATH
+env GOPATH=$WORK/tmp
+env GOROOT=$WORK/tmp
+! go get -d github.com/golang/example/hello
+stderr 'warning: GOPATH set to GOROOT'
+stderr '\$GOPATH must not be set to \$GOROOT'
+
+# Fails because GOROOT=GOPATH after cleaning.
+env GOPATH=$WORK/tmp/
+env GOROOT=$WORK/tmp
+! go get -d github.com/golang/example/hello
+stderr 'warning: GOPATH set to GOROOT'
+stderr '\$GOPATH must not be set to \$GOROOT'
+
+env GOPATH=$WORK/tmp
+env GOROOT=$WORK/tmp/
+! go get -d github.com/golang/example/hello
+stderr 'warning: GOPATH set to GOROOT'
+stderr '\$GOPATH must not be set to \$GOROOT'
+
+# Make a home directory
+mkdir $WORK/home/go
+
+# Fails because GOROOT=$HOME/go so default GOPATH unset.
+[GOOS:windows] env USERPROFILE=$WORK/home
+[GOOS:plan9] env home=$WORK/home
+[!GOOS:windows] [!GOOS:plan9] env HOME=$WORK/home
+env GOPATH=
+env GOROOT=$WORK/home/go
+! go get -d github.com/golang/example/hello
+stderr '\$GOPATH not set'
+
+[GOOS:windows] env USERPROFILE=$WORK/home/
+[GOOS:plan9] env home=$WORK/home/
+[!GOOS:windows] [!GOOS:plan9] env HOME=$WORK/home/
+env GOPATH=
+env GOROOT=$WORK/home/go
+! go get -d github.com/golang/example/hello
+stderr '\$GOPATH not set'
+
+[GOOS:windows] env USERPROFILE=$WORK/home
+[GOOS:plan9] env home=$WORK/home
+[!GOOS:windows] [!GOOS:plan9] env HOME=$WORK/home
+env GOPATH=
+env GOROOT=$WORK/home/go/
+! go get -d github.com/golang/example/hello
+stderr '\$GOPATH not set'
diff --git a/src/cmd/go/testdata/script/get_insecure.txt b/src/cmd/go/testdata/script/get_insecure.txt
index f29ec2d..afe64b8 100644
--- a/src/cmd/go/testdata/script/get_insecure.txt
+++ b/src/cmd/go/testdata/script/get_insecure.txt
@@ -1,9 +1,25 @@
+# TODO(matloob): Split this test into two? It's one of the slowest tests we have.
+
[!net:insecure.go-get-issue-15410.appspot.com] skip
[!git] skip
env PATH=$WORK/tmp/bin${:}$PATH
go build -o $WORK/tmp/bin/ssh ssh.go
+# GOPATH: Set up
+env GO111MODULE=off
+
+# GOPATH: Try go get -d of HTTP-only repo (should fail).
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try again with GOINSECURE (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating without GOINSECURE (should fail).
+env GOINSECURE=''
+! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
# Modules: Set up
env GOPATH=$WORK/m/gp
mkdir $WORK/m
diff --git a/src/cmd/go/testdata/script/get_insecure_custom_domain.txt b/src/cmd/go/testdata/script/get_insecure_custom_domain.txt
new file mode 100644
index 0000000..4b3c9d6
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_insecure_custom_domain.txt
@@ -0,0 +1,8 @@
+[!net:insecure.go-get-issue-15410.appspot.com] skip
+[!git] skip
+env GO111MODULE=off
+
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
diff --git a/src/cmd/go/testdata/script/get_insecure_env.txt b/src/cmd/go/testdata/script/get_insecure_env.txt
new file mode 100644
index 0000000..98e7053
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_insecure_env.txt
@@ -0,0 +1,29 @@
+[!net:insecure.go-get-issue-15410.appspot.com] skip
+[!git] skip
+
+# GOPATH: Set up
+env GO111MODULE=off
+
+# GOPATH: Try go get -d of HTTP-only repo (should fail).
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try again with invalid GOINSECURE (should fail).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com/pkg/q
+! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try with correct GOINSECURE (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com/pkg/p
+go get -d insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating without GOINSECURE (should fail).
+env GOINSECURE=
+! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating with GOINSECURE glob (should succeed).
+env GOINSECURE=*.go-get-*.appspot.com
+go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
+# GOPATH: Try updating with GOINSECURE base URL (should succeed).
+env GOINSECURE=insecure.go-get-issue-15410.appspot.com
+go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p
+
diff --git a/src/cmd/go/testdata/script/get_insecure_redirect.txt b/src/cmd/go/testdata/script/get_insecure_redirect.txt
new file mode 100644
index 0000000..2e53c58
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_insecure_redirect.txt
@@ -0,0 +1,14 @@
+# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure (now replaced by GOINSECURE).
+# golang.org/issue/34049: 'go get' would panic in case of an insecure redirect in GOPATH mode
+
+[!git] skip
+
+env GO111MODULE=off
+
+! go get -d vcs-test.golang.org/insecure/go/insecure
+stderr 'redirected .* to insecure URL'
+
+[short] stop 'builds a git repo'
+
+env GOINSECURE=vcs-test.golang.org/insecure/go/insecure
+go get -d vcs-test.golang.org/insecure/go/insecure
diff --git a/src/cmd/go/testdata/script/get_insecure_update.txt b/src/cmd/go/testdata/script/get_insecure_update.txt
new file mode 100644
index 0000000..7cddd6b
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_insecure_update.txt
@@ -0,0 +1,14 @@
+[!net:github.com] skip
+[!git] skip
+env GO111MODULE=off
+
+# Clone the repo via HTTP manually.
+exec git clone -q http://github.com/golang/example github.com/golang/example
+
+# Update without GOINSECURE should fail.
+# We need -f to ignore import comments.
+! go get -d -u -f github.com/golang/example/hello
+
+# Update with GOINSECURE should succeed.
+env GOINSECURE=github.com/golang/example/hello
+go get -d -u -f github.com/golang/example/hello
diff --git a/src/cmd/go/testdata/script/get_internal_wildcard.txt b/src/cmd/go/testdata/script/get_internal_wildcard.txt
new file mode 100644
index 0000000..b25e746
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_internal_wildcard.txt
@@ -0,0 +1,6 @@
+[!net:github.com] skip
+[!git] skip
+env GO111MODULE=off
+
+# This used to fail with errors about internal packages
+go get github.com/rsc/go-get-issue-11960/...
diff --git a/src/cmd/go/testdata/script/get_issue11307.txt b/src/cmd/go/testdata/script/get_issue11307.txt
new file mode 100644
index 0000000..d490959
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_issue11307.txt
@@ -0,0 +1,9 @@
+# go get -u was not working except in checkout directory
+
+[!net:github.com] skip
+[!git] skip
+env GO111MODULE=off
+
+env GOPATH=$WORK/tmp/gopath
+go get github.com/rsc/go-get-issue-11307
+go get -u github.com/rsc/go-get-issue-11307 # was failing
diff --git a/src/cmd/go/testdata/script/get_issue16471.txt b/src/cmd/go/testdata/script/get_issue16471.txt
new file mode 100644
index 0000000..1aeae58
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_issue16471.txt
@@ -0,0 +1,23 @@
+[!net:rsc.io] skip
+[!net:github.com] skip
+[!git] skip
+
+env GO111MODULE=off
+
+cd rsc.io/go-get-issue-10952
+
+exec git init
+exec git add foo.go
+exec git config user.name Gopher
+exec git config user.email gopher@golang.org
+exec git commit -a -m 'initial commit'
+exec git remote add origin https://github.com/golang/go-get-issue-10952
+
+exec git status
+
+! go get -x -u rsc.io/go-get-issue-10952
+stderr '^package rsc.io/go-get-issue-10952: rsc\.io/go-get-issue-10952 is a custom import path for https://github.com/rsc/go-get-issue-10952, but .* is checked out from https://github.com/golang/go-get-issue-10952$'
+
+-- rsc.io/go-get-issue-10952/foo.go --
+// Junk package to test go get.
+package foo
diff --git a/src/cmd/go/testdata/script/get_issue22125.txt b/src/cmd/go/testdata/script/get_issue22125.txt
new file mode 100644
index 0000000..086081f
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_issue22125.txt
@@ -0,0 +1,14 @@
+# This test verifies a fix for a security issue; see https://go.dev/issue/22125.
+
+[short] skip
+[!git] skip
+[!exec:svn] skip
+
+env GO111MODULE=off
+
+cd $GOPATH
+! go get -u vcs-test.golang.org/go/test1-svn-git
+stderr 'src'${/}'vcs-test.* uses git, but parent .*src'${/}'vcs-test.* uses svn'
+
+[!case-sensitive] ! go get -u vcs-test.golang.org/go/test2-svn-git/test2main
+[!case-sensitive] stderr 'src'${/}'vcs-test.* uses git, but parent .*src'${/}'vcs-test.* uses svn'
diff --git a/src/cmd/go/testdata/script/get_legacy.txt b/src/cmd/go/testdata/script/get_legacy.txt
new file mode 100644
index 0000000..2909b73
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_legacy.txt
@@ -0,0 +1,58 @@
+# This test was converted from a test in vendor_test.go (which no longer exists).
+# That seems to imply that it's about vendoring semantics, but the test doesn't
+# use 'go -mod=vendor' (and none of the fetched repos have vendor folders).
+# The test still seems to be useful as a test of direct-mode go get.
+
+[short] skip
+[!git] skip
+env GO111MODULE=off
+
+env GOPATH=$WORK/tmp/d1
+go get vcs-test.golang.org/git/modlegacy1-old.git/p1
+go list -f '{{.Deps}}' vcs-test.golang.org/git/modlegacy1-old.git/p1
+stdout 'new.git/p2' # old/p1 should depend on new/p2
+! stdout new.git/v2/p2 # old/p1 should NOT depend on new/v2/p2
+go build vcs-test.golang.org/git/modlegacy1-old.git/p1 vcs-test.golang.org/git/modlegacy1-new.git/p1
+! stdout .
+
+env GOPATH=$WORK/tmp/d2
+
+rm $GOPATH
+go get github.com/rsc/vgotest5
+go get github.com/rsc/vgotest4
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest4
+go get github.com/rsc/vgotest5
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest4 github.com/rsc/vgotest5
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest5 github.com/rsc/vgotest4
+go get github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/myitcv/vgo_example_compat
+go get github.com/rsc/vgotest5 github.com/rsc/vgotest4
+
+rm $GOPATH
+go get github.com/myitcv/vgo_example_compat github.com/rsc/vgotest4 github.com/rsc/vgotest5
+
+rm $GOPATH
+go get github.com/myitcv/vgo_example_compat github.com/rsc/vgotest5 github.com/rsc/vgotest4
+
+rm $GOPATH
+go get github.com/rsc/vgotest4 github.com/myitcv/vgo_example_compat github.com/rsc/vgotest5
+
+rm $GOPATH
+go get github.com/rsc/vgotest4 github.com/rsc/vgotest5 github.com/myitcv/vgo_example_compat
+
+rm $GOPATH
+go get github.com/rsc/vgotest5 github.com/myitcv/vgo_example_compat github.com/rsc/vgotest4
+
+rm $GOPATH
+go get github.com/rsc/vgotest5 github.com/rsc/vgotest4 github.com/myitcv/vgo_example_compat
diff --git a/src/cmd/go/testdata/script/get_non_pkg.txt b/src/cmd/go/testdata/script/get_non_pkg.txt
new file mode 100644
index 0000000..5202e88
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_non_pkg.txt
@@ -0,0 +1,14 @@
+[!net:golang.org] skip
+[!git] skip
+
+env GOBIN=$WORK/tmp/gobin
+env GO111MODULE=off
+
+! go get -d golang.org/x/tools
+stderr 'golang.org/x/tools: no Go files'
+
+! go get -d -u golang.org/x/tools
+stderr 'golang.org/x/tools: no Go files'
+
+! go get -d golang.org/x/tools
+stderr 'golang.org/x/tools: no Go files'
diff --git a/src/cmd/go/testdata/script/get_race.txt b/src/cmd/go/testdata/script/get_race.txt
new file mode 100644
index 0000000..1e06c80
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_race.txt
@@ -0,0 +1,8 @@
+# Tests issue #20502
+
+[!net:github.com] skip
+[!git] skip
+[!race] skip
+env GO111MODULE=off
+
+go get -race github.com/rsc/go-get-issue-9224-cmd
diff --git a/src/cmd/go/testdata/script/get_test_only.txt b/src/cmd/go/testdata/script/get_test_only.txt
new file mode 100644
index 0000000..af90f74
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_test_only.txt
@@ -0,0 +1,6 @@
+[!net:golang.org] skip
+[!git] skip
+env GO111MODULE=off
+
+go get golang.org/x/tour/content...
+go get -t golang.org/x/tour/content...
diff --git a/src/cmd/go/testdata/script/get_tilde.txt b/src/cmd/go/testdata/script/get_tilde.txt
new file mode 100644
index 0000000..1c3a029
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_tilde.txt
@@ -0,0 +1,25 @@
+env GO111MODULE=off
+
+# Paths containing windows short names should be rejected before attempting to fetch.
+! go get vcs-test.golang.org/longna~1.dir/thing
+stderr 'trailing tilde and digits'
+! go get vcs-test.golang.org/longna~1/thing
+stderr 'trailing tilde and digits'
+! go get vcs-test.golang.org/~9999999/thing
+stderr 'trailing tilde and digits'
+
+[short] stop
+
+# A path containing an element that is just a tilde, or a tilde followed by non-digits,
+# should attempt to resolve.
+! go get vcs-test.golang.org/~glenda/notfound
+! stderr 'trailing tilde and digits'
+stderr 'unrecognized import path'
+
+! go get vcs-test.golang.org/~glenda2/notfound
+! stderr 'trailing tilde and digits'
+stderr 'unrecognized import path'
+
+! go get vcs-test.golang.org/~/notfound
+! stderr 'trailing tilde and digits'
+stderr 'unrecognized import path'
diff --git a/src/cmd/go/testdata/script/get_update.txt b/src/cmd/go/testdata/script/get_update.txt
new file mode 100644
index 0000000..a70a80d
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_update.txt
@@ -0,0 +1,25 @@
+# Tests Issue #9224
+# The recursive updating was trying to walk to
+# former dependencies, not current ones.
+
+[!net:github.com] skip
+[!git] skip
+env GO111MODULE=off
+
+# Rewind
+go get github.com/rsc/go-get-issue-9224-cmd
+cd $GOPATH/src/github.com/rsc/go-get-issue-9224-lib
+exec git reset --hard HEAD~
+cd $GOPATH/src
+
+# Run get
+go get -u 'github.com/rsc/go-get-issue-9224-cmd'
+
+# (Again with -d -u) Rewind
+go get github.com/rsc/go-get-issue-9224-cmd
+cd $GOPATH/src/github.com/rsc/go-get-issue-9224-lib
+exec git reset --hard HEAD~
+cd $GOPATH/src
+
+# (Again with -d -u) Run get
+go get -d -u 'github.com/rsc/go-get-issue-9224-cmd'
diff --git a/src/cmd/go/testdata/script/get_update_all.txt b/src/cmd/go/testdata/script/get_update_all.txt
new file mode 100644
index 0000000..22fe3ed
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_update_all.txt
@@ -0,0 +1,7 @@
+# Issue 14444: go get -u .../ duplicate loads errors
+# Check that go get update -u ... does not try to load duplicates
+
+env GO111MODULE=off
+
+go get -u -n .../
+! stderr 'duplicate loads of' # make sure old packages are removed from cache
diff --git a/src/cmd/go/testdata/script/get_update_unknown_protocol.txt b/src/cmd/go/testdata/script/get_update_unknown_protocol.txt
new file mode 100644
index 0000000..714ed6a
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_update_unknown_protocol.txt
@@ -0,0 +1,14 @@
+[!net:github.com] skip
+[!git] skip
+env GO111MODULE=off
+
+# Clone the repo via HTTPS manually.
+exec git clone -q https://github.com/golang/example github.com/golang/example
+
+# Configure the repo to use a protocol unknown to cmd/go
+# that still actually works.
+cd github.com/golang/example
+exec git remote set-url origin xyz://github.com/golang/example
+exec git config --local url.https://github.com/.insteadOf xyz://github.com/
+
+go get -d -u -f github.com/golang/example/hello
diff --git a/src/cmd/go/testdata/script/get_update_wildcard.txt b/src/cmd/go/testdata/script/get_update_wildcard.txt
new file mode 100644
index 0000000..c833783
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_update_wildcard.txt
@@ -0,0 +1,16 @@
+# Issue 14450: go get -u .../ tried to import not downloaded package
+
+[!net:github.com] skip
+[!git] skip
+env GO111MODULE=off
+
+go get github.com/tmwh/go-get-issue-14450/a
+! go get -u .../
+stderr 'cannot find package.*d-dependency/e'
+
+# Even though get -u failed, the source for others should be downloaded.
+exists github.com/tmwh/go-get-issue-14450/b
+exists github.com/tmwh/go-get-issue-14450-b-dependency/c
+exists github.com/tmwh/go-get-issue-14450-b-dependency/d
+
+! exists github.com/tmwh/go-get-issue-14450-c-dependency/e
diff --git a/src/cmd/go/testdata/script/get_vcs_error_message.txt b/src/cmd/go/testdata/script/get_vcs_error_message.txt
new file mode 100644
index 0000000..8dc84fc
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_vcs_error_message.txt
@@ -0,0 +1,9 @@
+# Test that the Version Control error message includes the correct directory
+env GO111MODULE=off
+! go get -u foo
+stderr gopath(\\\\|/)src(\\\\|/)foo
+
+-- foo/foo.go --
+package foo
+-- math/math.go --
+package math
diff --git a/src/cmd/go/testdata/script/get_vendor.txt b/src/cmd/go/testdata/script/get_vendor.txt
new file mode 100644
index 0000000..179456d
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_vendor.txt
@@ -0,0 +1,95 @@
+[short] skip
+env GO111MODULE=off
+
+cd $GOPATH/src/v
+go run m.go
+go test
+go list -f '{{.Imports}}'
+stdout 'v/vendor/vendor.org/p'
+go list -f '{{.TestImports}}'
+stdout 'v/vendor/vendor.org/p'
+go get -d
+go get -t -d
+
+[!net:github.com] stop
+[!git] stop
+
+cd $GOPATH/src
+
+# Update
+go get 'github.com/rsc/go-get-issue-11864'
+go get -u 'github.com/rsc/go-get-issue-11864'
+exists github.com/rsc/go-get-issue-11864/vendor
+
+# get -u
+rm $GOPATH
+mkdir $GOPATH/src
+go get -u 'github.com/rsc/go-get-issue-11864'
+exists github.com/rsc/go-get-issue-11864/vendor
+
+# get -t -u
+rm $GOPATH
+mkdir $GOPATH/src
+go get -t -u 'github.com/rsc/go-get-issue-11864/...'
+exists github.com/rsc/go-get-issue-11864/vendor
+
+# Submodules
+rm $GOPATH
+mkdir $GOPATH/src
+go get -d 'github.com/rsc/go-get-issue-12612'
+go get -u -d 'github.com/rsc/go-get-issue-12612'
+exists github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git
+
+# Bad vendor (bad/imp)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+# Bad vendor (bad/imp2)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp2'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+# Bad vendor (bad/imp3)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp3'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+# Bad vendor (bad/...)
+rm $GOPATH
+mkdir $GOPATH/src
+! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/...'
+stderr 'must be imported as'
+! exists github.com/rsc/go-get-issue-11864/vendor
+
+-- v/m.go --
+package main
+
+import (
+ "fmt"
+ "vendor.org/p"
+)
+
+func main() {
+ fmt.Println(p.C)
+}
+-- v/m_test.go --
+package main
+import (
+ "fmt"
+ "testing"
+ "vendor.org/p"
+)
+
+func TestNothing(t *testing.T) {
+ fmt.Println(p.C)
+}
+-- v/vendor/vendor.org/p/p.go --
+package p
+const C = 1
diff --git a/src/cmd/go/testdata/script/get_with_git_trace.txt b/src/cmd/go/testdata/script/get_with_git_trace.txt
new file mode 100644
index 0000000..6f1305a
--- /dev/null
+++ b/src/cmd/go/testdata/script/get_with_git_trace.txt
@@ -0,0 +1,9 @@
+env GO111MODULE=off
+
+env GIT_TRACE=1
+
+[!net:golang.org] skip
+[!git] skip
+
+# go get should be success when GIT_TRACE set
+go get golang.org/x/text
diff --git a/src/cmd/go/testdata/script/gopath_moved_repo.txt b/src/cmd/go/testdata/script/gopath_moved_repo.txt
new file mode 100644
index 0000000..8108d9b
--- /dev/null
+++ b/src/cmd/go/testdata/script/gopath_moved_repo.txt
@@ -0,0 +1,67 @@
+env GO111MODULE=off
+
+# Test that 'go get -u' reports packages whose VCS configurations do not
+# match their import paths.
+
+[!net:rsc.io] skip
+[short] skip
+
+# We need to execute a custom Go program to break the config files.
+#
+# git will ask for a username and password when we run 'go get -d -f -u',
+# so we also need to set GIT_ASKPASS. Conveniently, a single binary can
+# perform both tasks!
+
+go build -o replace.exe replace
+env GIT_ASKPASS=$PWD/replace.exe
+
+
+# Test that 'go get -u' reports moved git packages.
+
+[git] go get -d rsc.io/pdf
+[git] go get -d -u rsc.io/pdf
+[git] exec ./replace.exe pdf rsc.io/pdf/.git/config
+
+[git] ! go get -d -u rsc.io/pdf
+[git] stderr 'is a custom import path for'
+[git] ! go get -d -f -u rsc.io/pdf
+[git] stderr 'validating server certificate|[nN]ot [fF]ound'
+
+
+# Test that 'go get -u' reports moved Mercurial packages.
+
+[exec:hg] go get -d vcs-test.golang.org/go/custom-hg-hello
+[exec:hg] go get -d -u vcs-test.golang.org/go/custom-hg-hello
+[exec:hg] exec ./replace.exe custom-hg-hello vcs-test.golang.org/go/custom-hg-hello/.hg/hgrc
+
+[exec:hg] ! go get -d -u vcs-test.golang.org/go/custom-hg-hello
+[exec:hg] stderr 'is a custom import path for'
+[exec:hg] ! go get -d -f -u vcs-test.golang.org/go/custom-hg-hello
+[exec:hg] stderr 'validating server certificate|[nN]ot [fF]ound'
+
+
+-- replace/replace.go --
+package main
+
+import (
+ "bytes"
+ "log"
+ "os"
+)
+
+func main() {
+ if len(os.Args) < 3 {
+ return
+ }
+
+ base := []byte(os.Args[1])
+ path := os.Args[2]
+ data, err := os.ReadFile(path)
+ if err != nil {
+ log.Fatal(err)
+ }
+ err = os.WriteFile(path, bytes.ReplaceAll(data, base, append(base, "XXX"...)), 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/src/cmd/go/testdata/script/govcs.txt b/src/cmd/go/testdata/script/govcs.txt
index 876f606..dd128cc 100644
--- a/src/cmd/go/testdata/script/govcs.txt
+++ b/src/cmd/go/testdata/script/govcs.txt
@@ -84,6 +84,89 @@ env GOVCS=public:git
! go get rsc.io/nonexist.hg/hello
stderr '^go: rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$'
+# Repeat in GOPATH mode. Error texts slightly different.
+
+env GO111MODULE=off
+
+# GOVCS stops go get
+env GOVCS='*:none'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOPRIVATE='github.com/google'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# public pattern works
+env GOPRIVATE='github.com/google'
+env GOVCS='public:all,private:none'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$'
+
+# private pattern works
+env GOPRIVATE='hubgit.com/google'
+env GOVCS='private:all,public:none'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# other patterns work (for more patterns, see TestGOVCS)
+env GOPRIVATE=
+env GOVCS='github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$'
+
+# bad patterns are reported (for more bad patterns, see TestGOVCSErrors)
+env GOVCS='git'
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$'
+
+env GOVCS=github.com:hg,github.com:git
+! go get github.com/google/go-cmp
+stderr '^package github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$'
+
+# bad GOVCS patterns do not stop commands that do not need to check VCS
+go list
+
+# svn is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.svn/hello
+stderr '^package rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$'
+
+# fossil is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.fossil/hello
+stderr '^package rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$'
+
+# bzr is disallowed by default
+env GOPRIVATE=
+env GOVCS=
+! go get rsc.io/nonexist.bzr/hello
+stderr '^package rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$'
+
+# git is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[net:rsc.io] [git] [!short] go get rsc.io/sampler
+
+# hg is OK by default
+env GOVCS=
+env GONOSUMDB='*'
+[exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello
+
+# git can be disallowed
+env GOVCS=public:hg
+! go get rsc.io/nonexist.git/hello
+stderr '^package rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$'
+
+# hg can be disallowed
+env GOVCS=public:git
+! go get rsc.io/nonexist.hg/hello
+stderr '^package rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$'
+
-- go.mod --
module m
diff --git a/src/cmd/go/testdata/script/help.txt b/src/cmd/go/testdata/script/help.txt
index fb15e93..26a0194 100644
--- a/src/cmd/go/testdata/script/help.txt
+++ b/src/cmd/go/testdata/script/help.txt
@@ -48,4 +48,4 @@ stderr 'Run ''go help test'' and ''go help testflag'' for details.'
# go help get shows usage for get
go help get
stdout 'usage: go get'
-stdout 'specific module versions'
+stdout 'get when using GOPATH'
diff --git a/src/cmd/go/testdata/script/mod_versions.txt b/src/cmd/go/testdata/script/mod_versions.txt
index aaa4216..9e6322b 100644
--- a/src/cmd/go/testdata/script/mod_versions.txt
+++ b/src/cmd/go/testdata/script/mod_versions.txt
@@ -1,7 +1,7 @@
# Test rejection of pkg@version in GOPATH mode.
env GO111MODULE=off
! go get rsc.io/quote@v1.5.1
-stderr '^go: modules disabled by GO111MODULE=off'
+stderr '^go: can only use path@version syntax with ''go get'' and ''go install'' in module-aware mode$'
! go build rsc.io/quote@v1.5.1
stderr '^package rsc.io/quote@v1.5.1: can only use path@version syntax with ''go get'' and ''go install'' in module-aware mode$'
diff --git a/src/cmd/go/testdata/script/vendor_list_issue11977.txt b/src/cmd/go/testdata/script/vendor_list_issue11977.txt
index f1ed613..f519175 100644
--- a/src/cmd/go/testdata/script/vendor_list_issue11977.txt
+++ b/src/cmd/go/testdata/script/vendor_list_issue11977.txt
@@ -1,5 +1,9 @@
+[!net:github.com] skip
+[!git] skip
env GO111MODULE=off
+go get github.com/rsc/go-get-issue-11864
+
go list -f '{{join .TestImports "\n"}}' github.com/rsc/go-get-issue-11864/t
stdout 'go-get-issue-11864/vendor/vendor.org/p'
@@ -11,77 +15,3 @@ stdout 'go-get-issue-11864/vendor/vendor.org/tx2'
go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3
stdout 'go-get-issue-11864/vendor/vendor.org/tx3'
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/m.go --
-package g
-
-import _ "vendor.org/p"
-import _ "vendor.org/p1"
-
-func main() {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t_test.go --
-package t
-
-import _ "vendor.org/p"
-import _ "vendor.org/p1"
-import "testing"
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t.go --
-package t
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx_test.go --
-package tx_test
-
-import _ "vendor.org/p"
-import _ "vendor.org/p1"
-import "testing"
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx.go --
-package tx
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p1/p1.go --
-package p1 // import "vendor.org/p1"
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3_test.go --
-package tx3_test
-
-import "vendor.org/tx3"
-import "testing"
-
-var Found = tx3.Exported
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/export_test.go --
-package tx3
-
-var Exported = true
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3.go --
-package tx3
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2_test.go --
-package tx2_test
-
-import . "vendor.org/tx2"
-import "testing"
-
-var Found = Exported
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/export_test.go --
-package tx2
-
-var Exported = true
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2.go --
-package tx2
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p/p.go --
-package p
diff --git a/src/cmd/go/testdata/script/vendor_test_issue11864.txt b/src/cmd/go/testdata/script/vendor_test_issue11864.txt
index 90c9c59..9e34811 100644
--- a/src/cmd/go/testdata/script/vendor_test_issue11864.txt
+++ b/src/cmd/go/testdata/script/vendor_test_issue11864.txt
@@ -1,83 +1,12 @@
-[short] skip
+[!net:github.com] skip
+[!git] skip
env GO111MODULE=off
+go get github.com/rsc/go-get-issue-11864
+
# test should work too
go test github.com/rsc/go-get-issue-11864
go test github.com/rsc/go-get-issue-11864/t
# external tests should observe internal test exports (golang.org/issue/11977)
go test github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/m.go --
-package g
-
-import _ "vendor.org/p"
-import _ "vendor.org/p1"
-
-func main() {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t_test.go --
-package t
-
-import _ "vendor.org/p"
-import _ "vendor.org/p1"
-import "testing"
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/t/t.go --
-package t
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx_test.go --
-package tx_test
-
-import _ "vendor.org/p"
-import _ "vendor.org/p1"
-import "testing"
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/tx/tx.go --
-package tx
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p1/p1.go --
-package p1 // import "vendor.org/p1"
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3_test.go --
-package tx3_test
-
-import "vendor.org/tx3"
-import "testing"
-
-var Found = tx3.Exported
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/export_test.go --
-package tx3
-
-var Exported = true
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3/tx3.go --
-package tx3
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2_test.go --
-package tx2_test
-
-import . "vendor.org/tx2"
-import "testing"
-
-var Found = Exported
-
-func TestNop(t *testing.T) {}
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/export_test.go --
-package tx2
-
-var Exported = true
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2/tx2.go --
-package tx2
-
--- $GOPATH/src/github.com/rsc/go-get-issue-11864/vendor/vendor.org/p/p.go --
-package p
diff --git a/src/cmd/go/testdata/script/vendor_test_issue14613.txt b/src/cmd/go/testdata/script/vendor_test_issue14613.txt
index d2f05c9..9535fc1 100644
--- a/src/cmd/go/testdata/script/vendor_test_issue14613.txt
+++ b/src/cmd/go/testdata/script/vendor_test_issue14613.txt
@@ -1,6 +1,11 @@
-[short] skip
+[!net:github.com] skip
+[!git] skip
env GO111MODULE=off
+cd $GOPATH
+
+go get github.com/clsung/go-vendor-issue-14613
+
# test folder should work
go test github.com/clsung/go-vendor-issue-14613
@@ -11,42 +16,3 @@ go test github.com/clsung/go-vendor-issue-14613/vendor_test.go
# test with imported and not used
! go test github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go
stderr 'imported and not used'
-
--- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor_test.go --
-package main
-
-import (
- "testing"
-
- "github.com/clsung/fake"
-)
-
-func TestVendor(t *testing.T) {
- ret := fake.DoNothing()
- expected := "Ok"
- if expected != ret {
- t.Errorf("fake returned %q, expected %q", ret, expected)
- }
-}
-
--- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor/mylibtesttest/myapp/myapp_test.go --
-package myapp
-import (
- "mylibtesttest/rds"
-)
-
--- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor/mylibtesttest/rds/rds.go --
-package rds
-
--- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./vendor/github.com/clsung/fake/fake.go --
-package fake
-
-func DoNothing() string {
- return "Ok"
-}
-
--- $GOPATH/src/github.com/clsung/go-vendor-issue-14613/./m.go --
-package main
-
-func main() {}
-
diff --git a/src/cmd/internal/par/work.go b/src/cmd/internal/par/work.go
index 881b51b..3f1e69a 100644
--- a/src/cmd/internal/par/work.go
+++ b/src/cmd/internal/par/work.go
@@ -180,3 +180,41 @@ func (c *Cache[K, V]) Get(key K) (V, bool) {
}
return e.result, true
}
+
+// Clear removes all entries in the cache.
+//
+// Concurrent calls to Get may return old values. Concurrent calls to Do
+// may return old values or store results in entries that have been deleted.
+//
+// TODO(jayconrod): Delete this after the package cache clearing functions
+// in internal/load have been removed.
+func (c *Cache[K, V]) Clear() {
+ c.m.Clear()
+}
+
+// Delete removes an entry from the map. It is safe to call Delete for an
+// entry that does not exist. Delete will return quickly, even if the result
+// for a key is still being computed; the computation will finish, but the
+// result won't be accessible through the cache.
+//
+// TODO(jayconrod): Delete this after the package cache clearing functions
+// in internal/load have been removed.
+func (c *Cache[K, V]) Delete(key K) {
+ c.m.Delete(key)
+}
+
+// DeleteIf calls pred for each key in the map. If pred returns true for a key,
+// DeleteIf removes the corresponding entry. If the result for a key is
+// still being computed, DeleteIf will remove the entry without waiting for
+// the computation to finish. The result won't be accessible through the cache.
+//
+// TODO(jayconrod): Delete this after the package cache clearing functions
+// in internal/load have been removed.
+func (c *Cache[K, V]) DeleteIf(pred func(key K) bool) {
+ c.m.Range(func(key, _ any) bool {
+ if key := key.(K); pred(key) {
+ c.Delete(key)
+ }
+ return true
+ })
+}
--
2.39.5