cmd/go/internal/vgo: add -getmode=local, -getmode=vendor build flag
The new build flag -getmode=mode changes the way that vgo
resolves references to modules outside the target module.
The default (no -getmode flag) is to download and cache as usual.
With -getmode=local, the local cache is still consulted for modules,
but no network lookups are permitted.
With -getmode==vendor, only the vendor directory is used,
bypassing both the network and the local cache.
In this mode most of the interesting vgo behavior is inaccessible:
there is no world beyond the current module and its vendor directory.
I'm not thrilled with the name -getmode but don't have a better
name yet. It will probably change before the release - this CL is
about implementing the behavior.
Fixes golang/go#25073.
Change-Id: Ic5273f9f2d0263b49540401c4f554190702df099
Reviewed-on: https://go-review.googlesource.com/118316
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/vendor/cmd/go/internal/cfg/cfg.go b/vendor/cmd/go/internal/cfg/cfg.go
index 98afaa2..af86b96 100644
--- a/vendor/cmd/go/internal/cfg/cfg.go
+++ b/vendor/cmd/go/internal/cfg/cfg.go
@@ -22,6 +22,7 @@
BuildA bool // -a flag
BuildBuildmode string // -buildmode flag
BuildContext = build.Default
+ BuildGetmode string // -getmode flag
BuildI bool // -i flag
BuildLinkshared bool // -linkshared flag
BuildMSan bool // -msan flag
diff --git a/vendor/cmd/go/internal/modfetch/repo.go b/vendor/cmd/go/internal/modfetch/repo.go
index 6e21a41..b089981 100644
--- a/vendor/cmd/go/internal/modfetch/repo.go
+++ b/vendor/cmd/go/internal/modfetch/repo.go
@@ -6,11 +6,13 @@
import (
"errors"
+ "fmt"
pathpkg "path"
"sort"
"strings"
"time"
+ "cmd/go/internal/cfg"
"cmd/go/internal/modfetch/bitbucket"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfetch/github"
@@ -60,6 +62,9 @@
// Lookup returns the module with the given module path.
func Lookup(path string) (Repo, error) {
+ if cfg.BuildGetmode != "" {
+ return nil, fmt.Errorf("module lookup disabled by -getmode=%s", cfg.BuildGetmode)
+ }
if proxyURL != "" {
return lookupProxy(path)
}
diff --git a/vendor/cmd/go/internal/vgo/help.go b/vendor/cmd/go/internal/vgo/help.go
new file mode 100644
index 0000000..4a373e9
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/help.go
@@ -0,0 +1,17 @@
+// Copyright 2018 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 vgo
+
+import "cmd/go/internal/base"
+
+var HelpModule = &base.Command{
+ UsageLine: "module",
+ Short: "using versioned modules",
+ Long: `
+TODO: write whole thing
+
+TODO: mention -getmode=vendor, -getmode=local
+ `,
+}
diff --git a/vendor/cmd/go/internal/vgo/load.go b/vendor/cmd/go/internal/vgo/load.go
index 7b85cd0..5be03b4 100644
--- a/vendor/cmd/go/internal/vgo/load.go
+++ b/vendor/cmd/go/internal/vgo/load.go
@@ -260,6 +260,13 @@
}
}
+ if cfg.BuildGetmode == "vendor" {
+ // Using -getmode=vendor, everything the module needs
+ // (beyond the current module and standard library)
+ // must be in the module's vendor directory.
+ return filepath.Join(ModRoot, "vendor", path)
+ }
+
var mod1 module.Version
var dir1 string
for _, mod := range buildList {
diff --git a/vendor/cmd/go/internal/work/build.go b/vendor/cmd/go/internal/work/build.go
index c6aca11..c637d76 100644
--- a/vendor/cmd/go/internal/work/build.go
+++ b/vendor/cmd/go/internal/work/build.go
@@ -88,6 +88,8 @@
arguments to pass on each gccgo compiler/linker invocation.
-gcflags '[pattern=]arg list'
arguments to pass on each go tool compile invocation.
+ -getmode mode
+ module download mode to use. See 'go help module' for more.
-installsuffix suffix
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
@@ -220,6 +222,7 @@
cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
cmd.Flag.Var(&load.BuildGcflags, "gcflags", "")
cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "")
+ cmd.Flag.StringVar(&cfg.BuildGetmode, "getmode", "", "")
cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
cmd.Flag.Var(&load.BuildLdflags, "ldflags", "")
cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "")
diff --git a/vendor/cmd/go/internal/work/init.go b/vendor/cmd/go/internal/work/init.go
index 1081e51..41aecad 100644
--- a/vendor/cmd/go/internal/work/init.go
+++ b/vendor/cmd/go/internal/work/init.go
@@ -9,6 +9,7 @@
import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
+ "cmd/go/internal/vgo"
"flag"
"fmt"
"os"
@@ -224,4 +225,16 @@
cfg.BuildContext.InstallSuffix += codegenArg[1:]
}
}
+
+ switch cfg.BuildGetmode {
+ case "":
+ // ok
+ case "local", "vendor":
+ // ok but check for vgo
+ if !vgo.Enabled() {
+ base.Fatalf("build flag -getmode=%s only valid when using modules", cfg.BuildGetmode)
+ }
+ default:
+ base.Fatalf("-getmode=%s not supported (can be '', 'local', or 'vendor')", cfg.BuildGetmode)
+ }
}
diff --git a/vendor/cmd/go/main.go b/vendor/cmd/go/main.go
index c5a6df4..0604990 100644
--- a/vendor/cmd/go/main.go
+++ b/vendor/cmd/go/main.go
@@ -64,6 +64,7 @@
help.HelpFileType,
help.HelpGopath,
help.HelpImportPath,
+ vgo.HelpModule,
help.HelpPackages,
test.HelpTestflag,
test.HelpTestfunc,
@@ -123,8 +124,9 @@
os.Exit(2)
}
+ vgo.Init()
if !vgo.MustBeVgo {
- if vgo.Init(); vgo.Enabled() {
+ if vgo.Enabled() {
// Didn't do this above, so do it now.
*get.CmdGet = *vgo.CmdGet
}
diff --git a/vendor/cmd/go/vgo_test.go b/vendor/cmd/go/vgo_test.go
index b743f40..0f304d9 100644
--- a/vendor/cmd/go/vgo_test.go
+++ b/vendor/cmd/go/vgo_test.go
@@ -227,11 +227,22 @@
wd, _ := os.Getwd()
tg.cd(filepath.Join(wd, "testdata/vendormod"))
+ defer tg.must(os.RemoveAll(filepath.Join(wd, "testdata/vendormod/vendor")))
+
tg.run("-vgo", "list", "-m")
tg.grepStdout(`^x`, "expected to see module x")
tg.grepStdout(`=> ./x`, "expected to see replacement for module x")
tg.grepStdout(`^w`, "expected to see module w")
+ tg.must(os.RemoveAll(filepath.Join(wd, "testdata/vendormod/vendor")))
+ if !testing.Short() {
+ tg.run("-vgo", "build")
+ tg.runFail("-vgo", "build", "-getmode=vendor")
+ }
+
+ tg.run("-vgo", "list", "-f={{.Dir}}", "x")
+ tg.grepStdout(`vendormod[/\\]x$`, "expected x in vendormod/x")
+
tg.run("-vgo", "vendor", "-v")
tg.grepStderr(`^# x v1.0.0 => ./x`, "expected to see module x with replacement")
tg.grepStderr(`^x`, "expected to see package x")
@@ -241,7 +252,27 @@
tg.grepStderr(`^z`, "expected to see package z")
tg.grepStderrNot(`w`, "expected NOT to see unused module w")
- tg.must(os.RemoveAll(filepath.Join(wd, "testdata/vendormod/vendor")))
+ tg.run("-vgo", "list", "-f={{.Dir}}", "x")
+ tg.grepStdout(`vendormod[/\\]x$`, "expected x in vendormod/x")
+
+ tg.run("-vgo", "list", "-getmode=vendor", "-f={{.Dir}}", "x")
+ tg.grepStdout(`vendormod[/\\]vendor[/\\]x$`, "expected x in vendormod/vendor/x in -get=vendor mode")
+
+ tg.run("-vgo", "list", "-f={{.Dir}}", "w")
+ tg.grepStdout(`vendormod[/\\]w$`, "expected w in vendormod/w")
+ tg.runFail("-vgo", "list", "-getmode=vendor", "-f={{.Dir}}", "w")
+ tg.grepStderr(`vendormod[/\\]vendor[/\\]w`, "want error about vendormod/vendor/w not existing")
+
+ tg.run("-vgo", "list", "-getmode=local", "-f={{.Dir}}", "w")
+ tg.grepStdout(`vendormod[/\\]w`, "expected w in vendormod/w")
+
+ tg.runFail("-vgo", "list", "-getmode=local", "-f={{.Dir}}", "newpkg")
+ tg.grepStderr(`module lookup disabled by -getmode=local`, "expected -getmode=local to avoid network")
+
+ if !testing.Short() {
+ tg.run("-vgo", "build")
+ tg.run("-vgo", "build", "-getmode=vendor")
+ }
}
func TestFillGoMod(t *testing.T) {