cmd/go/internal/vgo: main vgo drivers
diff --git a/vendor/cmd/go/internal/vgo/build.go b/vendor/cmd/go/internal/vgo/build.go
new file mode 100644
index 0000000..37d14f3
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/build.go
@@ -0,0 +1,79 @@
+// 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 (
+ "bytes"
+ "cmd/go/internal/base"
+ "cmd/go/internal/module"
+ "cmd/go/internal/search"
+ "encoding/hex"
+ "fmt"
+)
+
+var (
+ infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+ infoEnd, _ = hex.DecodeString("f932433186182072008242104116d8f2")
+)
+
+func PackageModuleInfo(path string, deps []string) string {
+ if search.IsStandardImportPath(path) {
+ return ""
+ }
+ target := findModule(path, path)
+ mdeps := make(map[module.Version]bool)
+ for _, dep := range deps {
+ if !search.IsStandardImportPath(dep) {
+ mdeps[findModule(path, dep)] = true
+ }
+ }
+ var mods []module.Version
+ delete(mdeps, target)
+ for mod := range mdeps {
+ mods = append(mods, mod)
+ }
+ sortModules(mods)
+
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "path\t%s\n", path)
+ tv := target.Version
+ if tv == "" {
+ tv = "(devel)"
+ }
+ fmt.Fprintf(&buf, "mod\t%s\t%s\t%s\n", target.Path, tv, findModHash(target))
+ for _, mod := range mods {
+ mv := mod.Version
+ if mv == "" {
+ mv = "(devel)"
+ }
+ fmt.Fprintf(&buf, "dep\t%s\t%s\t%s\n", mod.Path, mod.Version, findModHash(mod))
+ }
+ return buf.String()
+}
+
+func findModule(target, path string) module.Version {
+ if path == "." {
+ return buildList[0]
+ }
+ for _, mod := range buildList {
+ if importPathInModule(path, mod.Path) {
+ return mod
+ }
+ }
+ base.Fatalf("build %v: cannot find module for path %v", target, path)
+ panic("unreachable")
+}
+
+func ModInfoProg(info string) []byte {
+ return []byte(fmt.Sprintf(`
+ package main
+ import _ "unsafe"
+ //go:linkname __debug_modinfo__ runtime/debug.modinfo
+ var __debug_modinfo__ string
+ func init() {
+ __debug_modinfo__ = %q
+ }
+ `, string(infoStart)+info+string(infoEnd)))
+}
diff --git a/vendor/cmd/go/internal/vgo/fetch.go b/vendor/cmd/go/internal/vgo/fetch.go
new file mode 100644
index 0000000..b76eb3d
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/fetch.go
@@ -0,0 +1,231 @@
+// 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 (
+ "archive/zip"
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/dirhash"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/module"
+ "cmd/go/internal/semver"
+)
+
+// fetch returns the directory in the local download cache
+// holding the root of mod's source tree.
+// It downloads the module if needed.
+func fetch(mod module.Version) (dir string, err error) {
+ if r := replaced(mod); r != nil {
+ if r.New.Version == "" {
+ dir = r.New.Path
+ if !filepath.IsAbs(dir) {
+ dir = filepath.Join(ModRoot, dir)
+ }
+ return dir, nil
+ }
+ mod = r.New
+ }
+
+ modpath := mod.Path + "@" + mod.Version
+ dir = filepath.Join(srcV, modpath)
+ if files, _ := ioutil.ReadDir(dir); len(files) == 0 {
+ zipfile := filepath.Join(srcV, "cache", mod.Path, "@v", mod.Version+".zip")
+ if _, err := os.Stat(zipfile); err == nil {
+ // Use it.
+ // This should only happen if the v/cache directory is preinitialized
+ // or if src/v/modpath was removed but not src/v/cache.
+ fmt.Fprintf(os.Stderr, "vgo: extracting %s %s\n", mod.Path, mod.Version)
+ } else {
+ if err := os.MkdirAll(filepath.Join(srcV, "cache", mod.Path, "@v"), 0777); err != nil {
+ return "", err
+ }
+ fmt.Fprintf(os.Stderr, "vgo: downloading %s %s\n", mod.Path, mod.Version)
+ if err := downloadZip(mod, zipfile); err != nil {
+ return "", err
+ }
+ }
+ if err := modfetch.Unzip(dir, zipfile, modpath, 0); err != nil {
+ fmt.Fprintf(os.Stderr, "-> %s\n", err)
+ return "", err
+ }
+ }
+ checkModHash(mod)
+ return dir, nil
+}
+
+func downloadZip(mod module.Version, target string) error {
+ repo, err := modfetch.Lookup(mod.Path)
+ if err != nil {
+ return err
+ }
+ tmpfile, err := repo.Zip(mod.Version, os.TempDir())
+ if err != nil {
+ return err
+ }
+ defer os.Remove(tmpfile)
+
+ // Double-check zip file looks OK.
+ z, err := zip.OpenReader(tmpfile)
+ if err != nil {
+ z.Close()
+ return err
+ }
+ prefix := mod.Path + "@" + mod.Version
+ for _, f := range z.File {
+ if !strings.HasPrefix(f.Name, prefix) {
+ z.Close()
+ return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], f.Name)
+ }
+ }
+ z.Close()
+
+ hash, err := dirhash.HashZip(tmpfile, dirhash.DefaultHash)
+ if err != nil {
+ return err
+ }
+ r, err := os.Open(tmpfile)
+ if err != nil {
+ return err
+ }
+ defer r.Close()
+ w, err := os.Create(target)
+ if err != nil {
+ return err
+ }
+ if _, err := io.Copy(w, r); err != nil {
+ w.Close()
+ return fmt.Errorf("copying: %v", err)
+ }
+ if err := w.Close(); err != nil {
+ return err
+ }
+ if err := ioutil.WriteFile(target+"hash", []byte(hash), 0666); err != nil {
+ return err
+ }
+ return nil
+}
+
+var useModHash = false
+var modHash map[module.Version][]string
+
+func initModHash() {
+ if modHash != nil {
+ return
+ }
+ modHash = make(map[module.Version][]string)
+ file := filepath.Join(ModRoot, "go.modverify")
+ data, err := ioutil.ReadFile(file)
+ if err != nil && os.IsNotExist(err) {
+ return
+ }
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+ useModHash = true
+ lineno := 0
+ for len(data) > 0 {
+ var line []byte
+ lineno++
+ i := bytes.IndexByte(data, '\n')
+ if i < 0 {
+ line, data = data, nil
+ } else {
+ line, data = data[:i], data[i+1:]
+ }
+ f := strings.Fields(string(line))
+ if len(f) != 3 {
+ base.Fatalf("vgo: malformed go.modverify:\n%s:%d: wrong number of fields", file, lineno)
+ }
+ mod := module.Version{Path: f[0], Version: f[1]}
+ modHash[mod] = append(modHash[mod], f[2])
+ }
+}
+
+func checkModHash(mod module.Version) {
+ initModHash()
+ if !useModHash {
+ return
+ }
+
+ data, err := ioutil.ReadFile(filepath.Join(srcV, "cache", mod.Path, "@v", mod.Version+".ziphash"))
+ if err != nil {
+ base.Fatalf("vgo: verifying %s %s: %v", mod.Path, mod.Version, err)
+ }
+ h := strings.TrimSpace(string(data))
+ if !strings.HasPrefix(h, "h1:") {
+ base.Fatalf("vgo: verifying %s %s: unexpected ziphash: %q", mod.Path, mod.Version, h)
+ }
+
+ for _, vh := range modHash[mod] {
+ if h == vh {
+ return
+ }
+ if strings.HasPrefix(vh, "h1:") {
+ base.Fatalf("vgo: verifying %s %s: module hash mismatch\n\tdownloaded: %v\n\tgo.modverify: %v", mod.Path, mod.Version, h, vh)
+ }
+ }
+ if len(modHash[mod]) > 0 {
+ fmt.Fprintf(os.Stderr, "warning: verifying %s %s: unknown hashes in go.modverify: %v; adding %v", mod.Path, mod.Version, strings.Join(modHash[mod], ", "), h)
+ }
+ modHash[mod] = append(modHash[mod], h)
+}
+
+func findModHash(mod module.Version) string {
+ data, err := ioutil.ReadFile(filepath.Join(srcV, "cache", mod.Path, "@v", mod.Version+".ziphash"))
+ if err != nil {
+ return ""
+ }
+ return strings.TrimSpace(string(data))
+}
+
+func writeModHash() {
+ if !useModHash {
+ return
+ }
+
+ var mods []module.Version
+ for m := range modHash {
+ mods = append(mods, m)
+ }
+ sortModules(mods)
+ var buf bytes.Buffer
+ for _, m := range mods {
+ list := modHash[m]
+ sort.Strings(list)
+ for _, h := range list {
+ fmt.Fprintf(&buf, "%s %s %s\n", m.Path, m.Version, h)
+ }
+ }
+
+ file := filepath.Join(ModRoot, "go.modverify")
+ data, _ := ioutil.ReadFile(filepath.Join(ModRoot, "go.modverify"))
+ if bytes.Equal(data, buf.Bytes()) {
+ return
+ }
+
+ if err := ioutil.WriteFile(file, buf.Bytes(), 0666); err != nil {
+ base.Fatalf("vgo: writing go.modverify: %v", err)
+ }
+}
+
+func sortModules(mods []module.Version) {
+ sort.Slice(mods, func(i, j int) bool {
+ mi := mods[i]
+ mj := mods[j]
+ if mi.Path != mj.Path {
+ return mi.Path < mj.Path
+ }
+ return semver.Compare(mi.Version, mj.Version) < 0
+ })
+}
diff --git a/vendor/cmd/go/internal/vgo/get.go b/vendor/cmd/go/internal/vgo/get.go
new file mode 100644
index 0000000..1ed5d19
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/get.go
@@ -0,0 +1,139 @@
+// 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 (
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/module"
+ "cmd/go/internal/mvs"
+ "cmd/go/internal/semver"
+)
+
+var CmdGet = &base.Command{
+ UsageLine: "get [build flags] [packages]",
+ Short: "TODO",
+ Long: `
+TODO
+ `,
+}
+
+var getU = CmdGet.Flag.Bool("u", false, "")
+
+func init() {
+ CmdGet.Run = runGet // break init loop
+}
+
+func runGet(cmd *base.Command, args []string) {
+ if *getU && len(args) > 0 {
+ base.Fatalf("vgo get: -u not supported with argument list")
+ }
+ if !*getU && len(args) == 0 {
+ base.Fatalf("vgo get: need arguments or -u")
+ }
+
+ if *getU {
+ isGetU = true
+ ImportPaths([]string{"."})
+ return
+ }
+
+ Init()
+ InitMod()
+ var upgrade []module.Version
+ var downgrade []module.Version
+ var newPkgs []string
+ for _, pkg := range args {
+ var path, vers string
+ /* OLD CODE
+ if n := strings.Count(pkg, "(") + strings.Count(pkg, ")"); n > 0 {
+ i := strings.Index(pkg, "(")
+ j := strings.Index(pkg, ")")
+ if n != 2 || i < 0 || j <= i+1 || j != len(pkg)-1 && pkg[j+1] != '/' {
+ base.Errorf("vgo get: invalid module version syntax: %s", pkg)
+ continue
+ }
+ path, vers = pkg[:i], pkg[i+1:j]
+ pkg = pkg[:i] + pkg[j+1:]
+ */
+ if i := strings.Index(pkg, "@"); i >= 0 {
+ path, pkg, vers = pkg[:i], pkg[:i], pkg[i+1:]
+ if strings.Contains(vers, "@") {
+ base.Errorf("vgo get: invalid module version syntax: %s", pkg)
+ continue
+ }
+ } else {
+ path = pkg
+ vers = "latest"
+ }
+ if vers == "none" {
+ downgrade = append(downgrade, module.Version{path, ""})
+ } else {
+ info, err := modfetch.Query(path, vers, allowed)
+ if err != nil {
+ base.Errorf("vgo get %v: %v", pkg, err)
+ continue
+ }
+ upgrade = append(upgrade, module.Version{Path: path, Version: info.Version})
+ newPkgs = append(newPkgs, pkg)
+ }
+ }
+ args = newPkgs
+
+ // Upgrade.
+ var err error
+ buildList, err = mvs.Upgrade(Target, newReqs(), upgrade...)
+ if err != nil {
+ base.Fatalf("vgo get: %v", err)
+ }
+
+ importPaths([]string{"."})
+
+ // Downgrade anything that went too far.
+ version := make(map[string]string)
+ for _, mod := range buildList {
+ version[mod.Path] = mod.Version
+ }
+ for _, mod := range upgrade {
+ if semver.Compare(mod.Version, version[mod.Path]) < 0 {
+ downgrade = append(downgrade, mod)
+ }
+ }
+
+ if len(downgrade) > 0 {
+ buildList, err = mvs.Downgrade(Target, newReqs(buildList[1:]...), downgrade...)
+ if err != nil {
+ base.Fatalf("vgo get: %v", err)
+ }
+
+ // TODO: Check that everything we need to import is still available.
+ /*
+ local := v.matchPackages("all", v.Reqs[:1])
+ for _, path := range local {
+ dir, err := v.importDir(path)
+ if err != nil {
+ return err // TODO
+ }
+ imports, testImports, err := imports.ScanDir(dir, v.Tags)
+ for _, path := range imports {
+ xxx
+ }
+ for _, path := range testImports {
+ xxx
+ }
+ }
+ */
+ }
+ writeGoMod()
+
+ if len(args) > 0 {
+ InstallHook(args)
+ }
+}
+
+// Call into "go install". Set by internal/work, which imports us.
+var InstallHook func([]string)
diff --git a/vendor/cmd/go/internal/vgo/init.go b/vendor/cmd/go/internal/vgo/init.go
new file mode 100644
index 0000000..c4e843d
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/init.go
@@ -0,0 +1,331 @@
+// 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 (
+ "bytes"
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/modconv"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/modfile"
+ "cmd/go/internal/module"
+ "cmd/go/internal/mvs"
+ "cmd/go/internal/search"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+ "path/filepath"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ cwd string
+ enabled = MustBeVgo
+ MustBeVgo = mustBeVgo()
+ initialized bool
+
+ ModRoot string
+ modFile *modfile.File
+ excluded map[module.Version]bool
+ Target module.Version
+
+ gopath string
+ srcV string
+)
+
+func init() {
+ flag.BoolVar(&MustBeVgo, "vgo", MustBeVgo, "require use of modules")
+}
+
+// mustBeVgo reports whether we are invoked as vgo
+// (as opposed to go).
+// If so, we only support builds with go.mod files.
+func mustBeVgo() bool {
+ name := os.Args[0]
+ name = name[strings.LastIndex(name, "/")+1:]
+ name = name[strings.LastIndex(name, `\`)+1:]
+ return strings.HasPrefix(name, "vgo")
+}
+
+func Init() {
+ if initialized {
+ return
+ }
+ initialized = true
+
+ // If this is testgo - the test binary during cmd/go tests - then
+ // do not let it look for a go.mod. Only use vgo support if the
+ // global -vgo flag has been passed on the command line.
+ if base := filepath.Base(os.Args[0]); (base == "testgo" || base == "testgo.exe") && !MustBeVgo {
+ return
+ }
+
+ var err error
+ cwd, err = os.Getwd()
+ if err != nil {
+ base.Fatalf("go: %v", err)
+ }
+
+ root, _ := FindModuleRoot(cwd, "", MustBeVgo)
+ if root == "" {
+ // If invoked as vgo, insist on a mod file.
+ if MustBeVgo {
+ base.Fatalf("cannot determine module root; please create a go.mod file there")
+ }
+ return
+ }
+ enabled = true
+ ModRoot = root
+ search.SetModRoot(root)
+}
+
+func Enabled() bool {
+ if !initialized {
+ panic("vgo: Enabled called before Init")
+ }
+ return enabled
+}
+
+func InitMod() {
+ if Init(); !Enabled() || modFile != nil {
+ return
+ }
+
+ list := filepath.SplitList(cfg.BuildContext.GOPATH)
+ if len(list) == 0 || list[0] == "" {
+ base.Fatalf("missing $GOPATH")
+ }
+ gopath = list[0]
+ srcV = filepath.Join(list[0], "src/v")
+
+ gomod := filepath.Join(ModRoot, "go.mod")
+ data, err := ioutil.ReadFile(gomod)
+ if err != nil {
+ legacyModInit()
+ return
+ }
+
+ f, err := modfile.Parse(gomod, data)
+ if err != nil {
+ // Errors returned by modfile.Parse begin with file:line.
+ base.Fatalf("vgo: errors parsing go.mod:\n%s\n", err)
+ }
+ modFile = f
+
+ if len(f.Syntax.Stmt) == 0 {
+ // Empty mod file. Must add module path.
+ path, err := FindModulePath(ModRoot)
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+ f.AddModuleStmt(path)
+ }
+
+ excluded = make(map[module.Version]bool)
+ for _, x := range f.Exclude {
+ excluded[x.Mod] = true
+ }
+ Target = f.Module.Mod
+ writeGoMod()
+}
+
+func allowed(m module.Version) bool {
+ return !excluded[m]
+}
+
+func legacyModInit() {
+ path, err := FindModulePath(ModRoot)
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+ modFile = new(modfile.File)
+ modFile.AddModuleStmt(path)
+ Target = module.Version{Path: path}
+
+ for _, name := range altConfigs {
+ cfg := filepath.Join(ModRoot, name)
+ data, err := ioutil.ReadFile(cfg)
+ if err == nil {
+ convert := modconv.Converters[name]
+ if convert == nil {
+ return
+ }
+ if err := modfetch.ConvertLegacyConfig(modFile, cfg, data); err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+ return
+ }
+ }
+
+ base.Fatalf("vgo: internal error: cannot find legacy config file (it was here a minute ago!)")
+}
+
+var altConfigs = []string{
+ "Gopkg.lock",
+
+ "GLOCKFILE",
+ "Godeps/Godeps.json",
+ "dependencies.tsv",
+ "glide.lock",
+ "vendor.conf",
+ "vendor.yml",
+ "vendor/manifest",
+ "vendor/vendor.json",
+
+ ".git/config",
+}
+
+// Exported only for testing.
+func FindModuleRoot(dir, limit string, legacyConfigOK bool) (root, file string) {
+ dir = filepath.Clean(dir)
+ dir1 := dir
+ limit = filepath.Clean(limit)
+
+ // Look for enclosing go.mod.
+ for {
+ if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
+ return dir, "go.mod"
+ }
+ if dir == limit {
+ break
+ }
+ d := filepath.Dir(dir)
+ if d == dir {
+ break
+ }
+ dir = d
+ }
+
+ // Failing that, look for enclosing alternate version config.
+ if legacyConfigOK {
+ dir = dir1
+ for {
+ for _, name := range altConfigs {
+ if _, err := os.Stat(filepath.Join(dir, name)); err == nil {
+ return dir, name
+ }
+ }
+ if dir == limit {
+ break
+ }
+ d := filepath.Dir(dir)
+ if d == dir {
+ break
+ }
+ dir = d
+ }
+ }
+
+ return "", ""
+}
+
+// Exported only for testing.
+func FindModulePath(dir string) (string, error) {
+ for _, dir := range filepath.SplitList(cfg.BuildContext.GOPATH) {
+ src := filepath.Join(dir, "src") + string(filepath.Separator)
+ if strings.HasPrefix(dir, src) {
+ return filepath.ToSlash(dir[len(src):]), nil
+ }
+ }
+
+ // Cast about for import comments,
+ // first in top-level directory, then in subdirectories.
+ list, _ := ioutil.ReadDir(dir)
+ for _, info := range list {
+ if info.Mode().IsRegular() && strings.HasSuffix(info.Name(), ".go") {
+ if com := findImportComment(filepath.Join(dir, info.Name())); com != "" {
+ return com, nil
+ }
+ }
+ }
+ for _, info1 := range list {
+ if info1.IsDir() {
+ files, _ := ioutil.ReadDir(filepath.Join(dir, info1.Name()))
+ for _, info2 := range files {
+ if info2.Mode().IsRegular() && strings.HasSuffix(info2.Name(), ".go") {
+ if com := findImportComment(filepath.Join(dir, info1.Name(), info2.Name())); com != "" {
+ return path.Dir(com), nil
+ }
+ }
+ }
+ }
+ }
+
+ // Look for Godeps.json declaring import path.
+ data, _ := ioutil.ReadFile(filepath.Join(dir, "Godeps/Godeps.json"))
+ var cfg struct{ ImportPath string }
+ json.Unmarshal(data, &cfg)
+ if cfg.ImportPath != "" {
+ return cfg.ImportPath, nil
+ }
+
+ // Look for vendor.json declaring import path.
+ data, _ = ioutil.ReadFile(filepath.Join(dir, "vendor/vendor.json"))
+ var cfg2 struct{ RootPath string }
+ json.Unmarshal(data, &cfg2)
+ if cfg2.RootPath != "" {
+ return cfg2.RootPath, nil
+ }
+
+ // Look for .git/config with github origin as last resort.
+ data, _ = ioutil.ReadFile(filepath.Join(dir, ".git/config"))
+ if m := gitOriginRE.FindSubmatch(data); m != nil {
+ return "github.com/" + string(m[1]), nil
+ }
+
+ return "", fmt.Errorf("cannot determine module path for legacy source directory %s (outside GOROOT, no import comments)", dir)
+}
+
+var (
+ gitOriginRE = regexp.MustCompile(`(?m)^\[remote "origin"\]\n\turl = (?:https://github.com/|git@github.com:|gh:)([^/]+/[^/]+?)(\.git)?\n`)
+ importCommentRE = regexp.MustCompile(`(?m)^package[ \t]+[^ \t\n/]+[ \t]+//[ \t]+import[ \t]+(\"[^"]+\")[ \t]*\n`)
+)
+
+func findImportComment(file string) string {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ return ""
+ }
+ m := importCommentRE.FindSubmatch(data)
+ if m == nil {
+ return ""
+ }
+ path, err := strconv.Unquote(string(m[1]))
+ if err != nil {
+ return ""
+ }
+ return path
+}
+
+func writeGoMod() {
+ writeModHash()
+
+ if buildList != nil {
+ min, err := mvs.Req(Target, buildList, newReqs())
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+ modFile.SetRequire(min)
+ }
+
+ file := filepath.Join(ModRoot, "go.mod")
+ old, _ := ioutil.ReadFile(file)
+ new, err := modFile.Format()
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+ if bytes.Equal(old, new) {
+ return
+ }
+ if err := ioutil.WriteFile(file, new, 0666); err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+}
diff --git a/vendor/cmd/go/internal/vgo/list.go b/vendor/cmd/go/internal/vgo/list.go
new file mode 100644
index 0000000..c6656c2
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/list.go
@@ -0,0 +1,153 @@
+// 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 (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "regexp"
+ "unicode/utf8"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/module"
+)
+
+func ListT(pkgs []string) {
+ if Init(); !Enabled() {
+ base.Fatalf("go list: cannot use -t outside module")
+ }
+ InitMod()
+
+ if len(pkgs) == 0 {
+ base.Fatalf("vgo list -t: need list of modules")
+ }
+
+ for _, pkg := range pkgs {
+ repo, err := modfetch.Lookup(pkg)
+ if err != nil {
+ base.Errorf("vgo list -t: %v", err)
+ continue
+ }
+ path := repo.ModulePath()
+ fmt.Printf("%s\n", path)
+ tags, err := repo.Versions("")
+ if err != nil {
+ base.Errorf("vgo list -t: %v", err)
+ continue
+ }
+ for _, t := range tags {
+ if excluded[module.Version{Path: path, Version: t}] {
+ t += " # excluded"
+ }
+ fmt.Printf("\t%s\n", t)
+ }
+ }
+}
+
+func ListM() {
+ if Init(); !Enabled() {
+ base.Fatalf("go list: cannot use -m outside module")
+ }
+ InitMod()
+ iterate(func(*loader) {})
+ printListM(os.Stdout)
+}
+
+func printListM(w io.Writer) {
+ var rows [][]string
+ rows = append(rows, []string{"MODULE", "VERSION"})
+ for _, mod := range buildList {
+ v := mod.Version
+ if v == "" {
+ v = "-"
+ }
+ rows = append(rows, []string{mod.Path, v})
+ if r := replaced(mod); r != nil {
+ rows = append(rows, []string{" => " + r.New.Path, r.New.Version})
+ }
+ }
+ printTable(w, rows)
+}
+
+func ListMU() {
+ if Init(); !Enabled() {
+ base.Fatalf("go list: cannot use -m outside module")
+ }
+ InitMod()
+
+ quietLookup = true // do not chatter in v.Lookup
+ iterate(func(*loader) {})
+
+ var rows [][]string
+ rows = append(rows, []string{"MODULE", "VERSION", "LATEST"})
+ for _, mod := range buildList {
+ var latest string
+ v := mod.Version
+ if v == "" {
+ v = "-"
+ latest = "-"
+ } else {
+ info, err := modfetch.Query(mod.Path, "latest", allowed)
+ if err != nil {
+ latest = "ERR: " + err.Error()
+ } else {
+ latest = info.Version
+ if !isPseudoVersion(latest) && !info.Time.IsZero() {
+ latest += info.Time.Local().Format(" (2006-01-02 15:04)")
+ }
+ }
+ if !isPseudoVersion(mod.Version) {
+ if info, err := modfetch.Query(mod.Path, mod.Version, nil); err == nil && !info.Time.IsZero() {
+ v += info.Time.Local().Format(" (2006-01-02 15:04)")
+ }
+ }
+ }
+ if latest == v {
+ latest = "-"
+ }
+ rows = append(rows, []string{mod.Path, v, latest})
+ }
+ printTable(os.Stdout, rows)
+}
+
+var pseudoVersionRE = regexp.MustCompile(`^v[0-9]+\.0\.0-[0-9]{14}-[A-Za-z0-9]+$`)
+
+func isPseudoVersion(v string) bool {
+ return pseudoVersionRE.MatchString(v)
+}
+
+func printTable(w io.Writer, rows [][]string) {
+ var max []int
+ for _, row := range rows {
+ for i, c := range row {
+ n := utf8.RuneCountInString(c)
+ if i >= len(max) {
+ max = append(max, n)
+ } else if max[i] < n {
+ max[i] = n
+ }
+ }
+ }
+
+ b := bufio.NewWriter(w)
+ for _, row := range rows {
+ for len(row) > 0 && row[len(row)-1] == "" {
+ row = row[:len(row)-1]
+ }
+ for i, c := range row {
+ b.WriteString(c)
+ if i+1 < len(row) {
+ for j := utf8.RuneCountInString(c); j < max[i]+2; j++ {
+ b.WriteRune(' ')
+ }
+ }
+ }
+ b.WriteRune('\n')
+ }
+ b.Flush()
+}
diff --git a/vendor/cmd/go/internal/vgo/load.go b/vendor/cmd/go/internal/vgo/load.go
new file mode 100644
index 0000000..548f0ed
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/load.go
@@ -0,0 +1,559 @@
+// 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 (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/imports"
+ "cmd/go/internal/modconv"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/modfile"
+ "cmd/go/internal/module"
+ "cmd/go/internal/mvs"
+ "cmd/go/internal/search"
+ "cmd/go/internal/semver"
+)
+
+type importLevel int
+
+const (
+ levelNone importLevel = 0
+ levelBuild importLevel = 1
+ levelTest importLevel = 2
+ levelTestRecursive importLevel = 3
+)
+
+var (
+ buildList []module.Version
+ tags map[string]bool
+ importmap map[string]string
+ pkgdir map[string]string
+ isGetU bool
+)
+
+func AddImports(gofiles []string) {
+ if Init(); !Enabled() {
+ return
+ }
+ InitMod()
+
+ imports, testImports, err := imports.ScanFiles(gofiles, tags)
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+
+ iterate(func(ld *loader) {
+ ld.importList(imports, levelBuild)
+ ld.importList(testImports, levelBuild)
+ })
+ writeGoMod()
+}
+
+func ImportPaths(args []string) []string {
+ if Init(); !Enabled() {
+ return search.ImportPaths(args)
+ }
+ InitMod()
+
+ paths := importPaths(args)
+ writeGoMod()
+ return paths
+}
+
+func importPaths(args []string) []string {
+ cleaned := search.CleanImportPaths(args)
+ iterate(func(ld *loader) {
+ args = expandImportPaths(cleaned)
+ for i, pkg := range args {
+ if pkg == "." || pkg == ".." || strings.HasPrefix(pkg, "./") || strings.HasPrefix(pkg, "../") {
+ dir := filepath.Join(cwd, pkg)
+ if dir == ModRoot {
+ pkg = Target.Path
+ } else if strings.HasPrefix(dir, ModRoot+string(filepath.Separator)) {
+ pkg = Target.Path + filepath.ToSlash(dir[len(ModRoot):])
+ } else {
+ base.Errorf("vgo: package %s outside module root", pkg)
+ continue
+ }
+ args[i] = pkg
+ }
+ ld.importPkg(pkg, levelBuild)
+ }
+ })
+ return args
+}
+
+func Lookup(parentPath, path string) (dir, realPath string, err error) {
+ realPath = importmap[path]
+ if realPath == "" {
+ if search.IsStandardImportPath(path) {
+ dir := filepath.Join(cfg.GOROOT, "src", path)
+ if _, err := os.Stat(dir); err == nil {
+ return dir, path, nil
+ }
+ }
+ return "", "", fmt.Errorf("no such package in module")
+ }
+ return pkgdir[realPath], realPath, nil
+}
+
+func iterate(doImports func(*loader)) {
+ var err error
+ mvsOp := mvs.BuildList
+ if isGetU {
+ mvsOp = mvs.UpgradeAll
+ }
+ buildList, err = mvsOp(Target, newReqs())
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+
+ var ld *loader
+ for {
+ ld = newLoader()
+ doImports(ld)
+ if len(ld.missing) == 0 {
+ break
+ }
+ for _, m := range ld.missing {
+ findMissing(m)
+ }
+ base.ExitIfErrors()
+ buildList, err = mvsOp(Target, newReqs())
+ if err != nil {
+ base.Fatalf("vgo: %v", err)
+ }
+ }
+ base.ExitIfErrors()
+
+ importmap = ld.importmap
+ pkgdir = ld.pkgdir
+}
+
+type loader struct {
+ imported map[string]importLevel
+ importmap map[string]string
+ pkgdir map[string]string
+ missing []missing
+ imports []string
+ stack []string
+}
+
+type missing struct {
+ path string
+ stack string
+}
+
+func newLoader() *loader {
+ ld := &loader{
+ imported: make(map[string]importLevel),
+ importmap: make(map[string]string),
+ pkgdir: make(map[string]string),
+ }
+ ld.imported["C"] = 100
+ return ld
+}
+
+func (ld *loader) stackText() string {
+ var buf bytes.Buffer
+ for _, p := range ld.stack[:len(ld.stack)-1] {
+ fmt.Fprintf(&buf, "import %q ->\n\t", p)
+ }
+ fmt.Fprintf(&buf, "import %q", ld.stack[len(ld.stack)-1])
+ return buf.String()
+}
+
+func (ld *loader) importList(pkgs []string, level importLevel) {
+ for _, pkg := range pkgs {
+ ld.importPkg(pkg, level)
+ }
+}
+
+func (ld *loader) importPkg(path string, level importLevel) {
+ if ld.imported[path] >= level {
+ return
+ }
+
+ ld.stack = append(ld.stack, path)
+ defer func() {
+ ld.stack = ld.stack[:len(ld.stack)-1]
+ }()
+
+ // Any rewritings go here.
+ realPath := path
+
+ ld.imported[path] = level
+ ld.importmap[path] = realPath
+ if realPath != path && ld.imported[realPath] >= level {
+ // Already handled.
+ return
+ }
+
+ dir := ld.importDir(realPath)
+ if dir == "" {
+ return
+ }
+
+ ld.pkgdir[realPath] = dir
+
+ imports, testImports, err := imports.ScanDir(dir, imports.Tags)
+ if err != nil {
+ base.Errorf("vgo: %s [%s]: %v", ld.stackText(), dir, err)
+ return
+ }
+ nextLevel := level
+ if level == levelTest {
+ nextLevel = levelBuild
+ }
+ for _, pkg := range imports {
+ ld.importPkg(pkg, nextLevel)
+ }
+ if level >= levelTest {
+ for _, pkg := range testImports {
+ ld.importPkg(pkg, nextLevel)
+ }
+ }
+}
+
+func (ld *loader) importDir(path string) string {
+ if importPathInModule(path, Target.Path) {
+ dir := ModRoot
+ if len(path) > len(Target.Path) {
+ dir = filepath.Join(dir, path[len(Target.Path)+1:])
+ }
+ return dir
+ }
+
+ i := strings.Index(path, "/")
+ if i < 0 || !strings.Contains(path[:i], ".") {
+ if strings.HasPrefix(path, "golang_org/") {
+ return filepath.Join(cfg.GOROOT, "src/vendor", path)
+ }
+ return filepath.Join(cfg.GOROOT, "src", path)
+ }
+
+ var mod1 module.Version
+ var dir1 string
+ for _, mod := range buildList {
+ if !importPathInModule(path, mod.Path) {
+ continue
+ }
+ dir, err := fetch(mod)
+ if err != nil {
+ base.Errorf("vgo: %s: %v", ld.stackText(), err)
+ return ""
+ }
+ if len(path) > len(mod.Path) {
+ dir = filepath.Join(dir, path[len(mod.Path)+1:])
+ }
+ if dir1 != "" {
+ base.Errorf("vgo: %s: found in both %v %v and %v %v", ld.stackText(),
+ mod1.Path, mod1.Version, mod.Path, mod.Version)
+ return ""
+ }
+ dir1 = dir
+ mod1 = mod
+ }
+ if dir1 != "" {
+ return dir1
+ }
+ ld.missing = append(ld.missing, missing{path, ld.stackText()})
+ return ""
+}
+
+func replaced(mod module.Version) *modfile.Replace {
+ var found *modfile.Replace
+ for _, r := range modFile.Replace {
+ if r.Old == mod {
+ found = r // keep going
+ }
+ }
+ return found
+}
+
+func importPathInModule(path, mpath string) bool {
+ return mpath == path ||
+ len(path) > len(mpath) && path[len(mpath)] == '/' && path[:len(mpath)] == mpath
+}
+
+var found = make(map[string]bool)
+
+func findMissing(m missing) {
+ for _, mod := range buildList {
+ if importPathInModule(m.path, mod.Path) {
+ // Leave for ordinary build to complain about the missing import.
+ return
+ }
+ }
+ fmt.Fprintf(os.Stderr, "vgo: resolving import %q\n", m.path)
+ repo, err := modfetch.Lookup(m.path)
+ if err != nil {
+ base.Errorf("vgo: %s: %v", m.stack, err)
+ return
+ }
+ root := repo.ModulePath()
+ fmt.Fprintf(os.Stderr, "vgo: finding %s (latest)\n", root)
+ if found[root] {
+ base.Fatalf("internal error: findmissing loop on %s", root)
+ }
+ found[root] = true
+ info, err := modfetch.Query(root, "latest", allowed)
+ if err != nil {
+ base.Errorf("vgo: %s: %v", m.stack, err)
+ return
+ }
+ fmt.Fprintf(os.Stderr, "vgo: adding %s %s\n", root, info.Version)
+ buildList = append(buildList, module.Version{root, info.Version})
+ modFile.AddRequire(root, info.Version)
+}
+
+type mvsReqs struct {
+ extra []module.Version
+}
+
+func newReqs(extra ...module.Version) *mvsReqs {
+ r := &mvsReqs{
+ extra: extra,
+ }
+ return r
+}
+
+func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
+ list, err := r.required(mod)
+ if err != nil {
+ return nil, err
+ }
+ if *getU {
+ for i := range list {
+ list[i].Version = "none"
+ }
+ return list, nil
+ }
+ for i, mv := range list {
+ for excluded[mv] {
+ mv1, err := r.Next(mv)
+ if err != nil {
+ return nil, err
+ }
+ if mv1.Version == "" {
+ return nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)
+ }
+ mv = mv1
+ }
+ list[i] = mv
+ }
+ return list, nil
+}
+
+var vgoVersion = []byte(modconv.Prefix)
+
+func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
+ if mod == Target {
+ var list []module.Version
+ if buildList != nil {
+ list = append(list, buildList[1:]...)
+ return list, nil
+ }
+ for _, r := range modFile.Require {
+ list = append(list, r.Mod)
+ }
+ list = append(list, r.extra...)
+ return list, nil
+ }
+
+ origPath := mod.Path
+ if repl := replaced(mod); repl != nil {
+ if repl.New.Version == "" {
+ // TODO: need to slip the new version into the tags list etc.
+ dir := repl.New.Path
+ if !filepath.IsAbs(dir) {
+ dir = filepath.Join(ModRoot, dir)
+ }
+ gomod := filepath.Join(dir, "go.mod")
+ data, err := ioutil.ReadFile(gomod)
+ if err != nil {
+ return nil, err
+ }
+ f, err := modfile.Parse(gomod, data)
+ if err != nil {
+ return nil, err
+ }
+ var list []module.Version
+ for _, r := range f.Require {
+ list = append(list, r.Mod)
+ }
+ return list, nil
+ }
+ mod = repl.New
+ }
+
+ if mod.Version == "none" {
+ return nil, nil
+ }
+
+ if !semver.IsValid(mod.Version) {
+ // Disallow the broader queries supported by fetch.Lookup.
+ panic(fmt.Errorf("invalid semantic version %q for %s", mod.Version, mod.Path))
+ return nil, fmt.Errorf("invalid semantic version %q", mod.Version)
+ }
+
+ gomod := filepath.Join(srcV, "cache", mod.Path, "@v", mod.Version+".mod")
+ infofile := filepath.Join(srcV, "cache", mod.Path, "@v", mod.Version+".info")
+ var f *modfile.File
+ if data, err := ioutil.ReadFile(gomod); err == nil {
+ // If go.mod has a //vgo comment at the start,
+ // it was auto-converted from a legacy lock file.
+ // The auto-conversion details may have bugs and
+ // may be fixed in newer versions of vgo.
+ // We ignore cached go.mod files if they do not match
+ // our own vgoVersion.
+ if !bytes.HasPrefix(data, vgoVersion[:len("//vgo")]) || bytes.HasPrefix(data, vgoVersion) {
+ f, err := modfile.Parse(gomod, data)
+ if err != nil {
+ return nil, err
+ }
+ var list []module.Version
+ for _, r := range f.Require {
+ list = append(list, r.Mod)
+ }
+ return list, nil
+ }
+ f, err = modfile.Parse("go.mod", data)
+ if err != nil {
+ return nil, fmt.Errorf("parsing downloaded go.mod: %v", err)
+ }
+ } else {
+ if !quietLookup {
+ fmt.Fprintf(os.Stderr, "vgo: finding %s %s\n", mod.Path, mod.Version)
+ }
+ repo, err := modfetch.Lookup(mod.Path)
+ if err != nil {
+ base.Errorf("vgo: %s: %v\n", mod.Path, err)
+ return nil, err
+ }
+ info, err := repo.Stat(mod.Version)
+ if err != nil {
+ base.Errorf("vgo: %s %s: %v\n", mod.Path, mod.Version, err)
+ return nil, err
+ }
+ data, err := repo.GoMod(info.Version)
+ if err != nil {
+ base.Errorf("vgo: %s %s: %v\n", mod.Path, mod.Version, err)
+ return nil, err
+ }
+
+ f, err = modfile.Parse("go.mod", data)
+ if err != nil {
+ return nil, fmt.Errorf("parsing downloaded go.mod: %v", err)
+ }
+ if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
+ return nil, fmt.Errorf("downloaded %q and got module %q", mod.Path, mpath)
+ }
+
+ dir := filepath.Dir(gomod)
+ if err := os.MkdirAll(dir, 0777); err != nil {
+ return nil, fmt.Errorf("caching go.mod: %v", err)
+ }
+ js, err := json.Marshal(info)
+ if err != nil {
+ return nil, fmt.Errorf("internal error: json failure: %v", err)
+ }
+ if err := ioutil.WriteFile(infofile, js, 0666); err != nil {
+ return nil, fmt.Errorf("caching info: %v", err)
+ }
+ if err := ioutil.WriteFile(gomod, data, 0666); err != nil {
+ return nil, fmt.Errorf("caching go.mod: %v", err)
+ }
+ }
+
+ var list []module.Version
+ for _, req := range f.Require {
+ list = append(list, req.Mod)
+ }
+ if false {
+ fmt.Fprintf(os.Stderr, "REQLIST %v:\n", mod)
+ for _, req := range list {
+ fmt.Fprintf(os.Stderr, "\t%v\n", req)
+ }
+ }
+ return list, nil
+}
+
+var quietLookup bool
+
+func (*mvsReqs) Max(v1, v2 string) string {
+ if semver.Compare(v1, v2) == -1 {
+ return v2
+ }
+ return v1
+}
+
+func (*mvsReqs) Latest(path string) (module.Version, error) {
+ // Note that query "latest" is not the same as
+ // using repo.LatestAt.
+ // The query only falls back to untagged versions
+ // if nothing is tagged. The LatestAt method
+ // only ever returns untagged versions,
+ // which is not what we want.
+ fmt.Fprintf(os.Stderr, "vgo: finding %s latest\n", path)
+ info, err := modfetch.Query(path, "latest", allowed)
+ if err != nil {
+ return module.Version{}, err
+ }
+ return module.Version{Path: path, Version: info.Version}, nil
+}
+
+var versionCache = make(map[string][]string)
+
+func versions(path string) ([]string, error) {
+ list, ok := versionCache[path]
+ if !ok {
+ var err error
+ repo, err := modfetch.Lookup(path)
+ if err != nil {
+ return nil, err
+ }
+ list, err = repo.Versions("")
+ if err != nil {
+ return nil, err
+ }
+ versionCache[path] = list
+ }
+ return list, nil
+}
+
+func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
+ list, err := versions(m.Path)
+ if err != nil {
+ return module.Version{}, err
+ }
+ i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 })
+ if i > 0 {
+ return module.Version{Path: m.Path, Version: list[i-1]}, nil
+ }
+ return module.Version{Path: m.Path, Version: "none"}, nil
+}
+
+func (*mvsReqs) Next(m module.Version) (module.Version, error) {
+ list, err := versions(m.Path)
+ if err != nil {
+ return module.Version{}, err
+ }
+ i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 })
+ if i < len(list) {
+ return module.Version{Path: m.Path, Version: list[i]}, nil
+ }
+ return module.Version{Path: m.Path, Version: "none"}, nil
+}
diff --git a/vendor/cmd/go/internal/vgo/search.go b/vendor/cmd/go/internal/vgo/search.go
new file mode 100644
index 0000000..b32dce2
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/search.go
@@ -0,0 +1,174 @@
+// 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 (
+ "fmt"
+ "go/build"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/imports"
+ "cmd/go/internal/module"
+ "cmd/go/internal/search"
+)
+
+func expandImportPaths(args []string) []string {
+ var out []string
+ for _, a := range args {
+ if search.IsMetaPackage(a) {
+ switch a {
+ default:
+ fmt.Fprintf(os.Stderr, "warning: %q matches no packages when using modules", a)
+ case "all":
+ out = append(out, AllPackages(a)...)
+ }
+ continue
+ }
+ if strings.Contains(a, "...") {
+ if build.IsLocalImport(a) {
+ out = append(out, search.AllPackagesInFS(a)...)
+ } else {
+ out = append(out, AllPackages(a)...)
+ }
+ continue
+ }
+ out = append(out, a)
+ }
+ return out
+}
+
+// AllPackages returns all the packages that can be found
+// under the $GOPATH directories and $GOROOT matching pattern.
+// The pattern is either "all" (all packages), "std" (standard packages),
+// "cmd" (standard commands), or a path including "...".
+func AllPackages(pattern string) []string {
+ pkgs := MatchPackages(pattern)
+ if len(pkgs) == 0 {
+ fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+ }
+ return pkgs
+}
+
+// MatchPackages returns a list of package paths matching pattern
+// (see go help packages for pattern syntax).
+func MatchPackages(pattern string) []string {
+ if pattern == "std" || pattern == "cmd" {
+ return nil
+ }
+ if pattern == "all" {
+ return MatchAll()
+ }
+
+ return matchPackages(pattern, buildList)
+}
+
+func matchPackages(pattern string, buildList []module.Version) []string {
+ match := func(string) bool { return true }
+ treeCanMatch := func(string) bool { return true }
+ if !search.IsMetaPackage(pattern) {
+ match = search.MatchPattern(pattern)
+ treeCanMatch = search.TreeCanMatchPattern(pattern)
+ }
+
+ have := map[string]bool{
+ "builtin": true, // ignore pseudo-package that exists only for documentation
+ }
+ if !cfg.BuildContext.CgoEnabled {
+ have["runtime/cgo"] = true // ignore during walk
+ }
+ var pkgs []string
+
+ for _, mod := range buildList {
+ if !treeCanMatch(mod.Path) {
+ continue
+ }
+ var root string
+ if mod.Version == "" {
+ root = ModRoot
+ } else {
+ var err error
+ root, err = fetch(mod)
+ if err != nil {
+ base.Errorf("vgo: %v", err)
+ continue
+ }
+ }
+ root = filepath.Clean(root)
+
+ filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return nil
+ }
+
+ want := true
+ // Avoid .foo, _foo, and testdata directory trees.
+ _, elem := filepath.Split(path)
+ if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+ want = false
+ }
+
+ name := mod.Path + filepath.ToSlash(path[len(root):])
+ if !treeCanMatch(name) {
+ want = false
+ }
+
+ if !fi.IsDir() {
+ if fi.Mode()&os.ModeSymlink != 0 && want {
+ if target, err := os.Stat(path); err == nil && target.IsDir() {
+ fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
+ }
+ }
+ return nil
+ }
+ if !want {
+ return filepath.SkipDir
+ }
+
+ if have[name] {
+ return nil
+ }
+ have[name] = true
+ if !match(name) {
+ return nil
+ }
+ if _, _, err := imports.ScanDir(path, imports.Tags); err == imports.ErrNoGo {
+ return nil
+ }
+
+ if elem == "vendor" {
+ return filepath.SkipDir // ignore children
+ }
+
+ pkgs = append(pkgs, name)
+ return nil
+ })
+ }
+ return pkgs
+}
+
+// MatchAll returns a list of the packages matching the pattern "all".
+// We redefine "all" to mean start with the packages in the current module
+// and then follow imports into other modules to add packages imported
+// (directly or indirectly) as part of builds in this module.
+// It does not include packages in other modules that are not needed
+// by builds of this module.
+func MatchAll() []string {
+ local := matchPackages("all", buildList[:1])
+ ld := newLoader()
+ ld.importList(local, levelTestRecursive)
+ var all []string
+ for _, pkg := range ld.importmap {
+ if !search.IsStandardImportPath(pkg) {
+ all = append(all, pkg)
+ }
+ }
+ sort.Strings(all)
+ return all
+}
diff --git a/vendor/cmd/go/internal/vgo/vendor.go b/vendor/cmd/go/internal/vgo/vendor.go
new file mode 100644
index 0000000..e3330f6
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/vendor.go
@@ -0,0 +1,124 @@
+// 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 (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "cmd/go/internal/base"
+)
+
+var CmdVendor = &base.Command{
+ UsageLine: "vendor",
+ Run: runVendor,
+ Short: "vendor dependencies of current module",
+ Long: `
+Vendor resets the module's vendor directory to include all
+packages needed to builds and test all packages in the module
+and their dependencies.
+ `,
+}
+
+func runVendor(cmd *base.Command, args []string) {
+ if Init(); !Enabled() {
+ base.Fatalf("vgo vendor: cannot use -m outside module")
+ }
+ if len(args) != 0 {
+ base.Fatalf("vgo vendor: vendor takes no arguments")
+ }
+ InitMod()
+ // TODO(rsc): This should scan directories with more permissive build tags.
+ pkgs := ImportPaths([]string{"all"})
+
+ vdir := filepath.Join(ModRoot, "vendor")
+ if err := os.RemoveAll(vdir); err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+
+ for _, pkg := range pkgs {
+ vendorPkg(vdir, pkg)
+ }
+
+ var buf bytes.Buffer
+ printListM(&buf)
+ if err := ioutil.WriteFile(filepath.Join(vdir, "vgo.list"), buf.Bytes(), 0666); err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+}
+
+func vendorPkg(vdir, pkg string) {
+ if hasPathPrefix(pkg, Target.Path) {
+ return
+ }
+ realPath := importmap[pkg]
+ if realPath != pkg && importmap[realPath] != "" {
+ fmt.Fprintf(os.Stderr, "warning: %s imported as both %s and %s; making two copies.\n", realPath, realPath, pkg)
+ }
+
+ dst := filepath.Join(vdir, pkg)
+ src := pkgdir[realPath]
+ if src == "" {
+ fmt.Fprintf(os.Stderr, "internal error: no pkg for %s -> %s\n", pkg, realPath)
+ }
+ copyDir(dst, src, false)
+}
+
+func copyDir(dst, src string, recursive bool) {
+ files, err := ioutil.ReadDir(src)
+ if err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+ if err := os.MkdirAll(dst, 0777); err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+ for _, file := range files {
+ if file.IsDir() {
+ if recursive || file.Name() == "testdata" {
+ copyDir(filepath.Join(dst, file.Name()), filepath.Join(src, file.Name()), true)
+ }
+ continue
+ }
+ if !file.Mode().IsRegular() {
+ continue
+ }
+ r, err := os.Open(filepath.Join(src, file.Name()))
+ if err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+ w, err := os.Create(filepath.Join(dst, file.Name()))
+ if err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+ if _, err := io.Copy(w, r); err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+ r.Close()
+ if err := w.Close(); err != nil {
+ base.Fatalf("vgo vendor: %v", err)
+ }
+ }
+}
+
+// hasPathPrefix reports whether the path s begins with the
+// elements in prefix.
+func hasPathPrefix(s, prefix string) bool {
+ switch {
+ default:
+ return false
+ case len(s) == len(prefix):
+ return s == prefix
+ case len(s) > len(prefix):
+ if prefix != "" && prefix[len(prefix)-1] == '/' {
+ return strings.HasPrefix(s, prefix)
+ }
+ return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
+ }
+}
diff --git a/vendor/cmd/go/internal/vgo/verify.go b/vendor/cmd/go/internal/vgo/verify.go
new file mode 100644
index 0000000..2c07018
--- /dev/null
+++ b/vendor/cmd/go/internal/vgo/verify.go
@@ -0,0 +1,101 @@
+// 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 (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/dirhash"
+ "cmd/go/internal/module"
+)
+
+var CmdVerify = &base.Command{
+ UsageLine: "verify",
+ Run: runVerify,
+ Short: "verify downloaded modules against expected hashes",
+ Long: `
+Verify checks that the depdendencies of the current module,
+which are stored in a local downloaded source cache,
+have not been modified since being downloaded.
+
+If all the modules are unmodified, verify prints
+
+ all modules verified
+
+and exits successfully (status 0). Otherwise, verify reports
+which modules have been changed and exits with a non-zero status.
+ `,
+}
+
+func runVerify(cmd *base.Command, args []string) {
+ if Init(); !Enabled() {
+ base.Fatalf("vgo verify: cannot use outside module")
+ }
+ if len(args) != 0 {
+ // TODO: take arguments
+ base.Fatalf("vgo verify: verify takes no arguments")
+ }
+ InitMod()
+ ImportPaths([]string{"all"})
+
+ ok := true
+ for _, mod := range buildList[1:] {
+ ok = verifyMod(mod) && ok
+ }
+ if ok {
+ fmt.Printf("all modules verified\n")
+ }
+}
+
+func verifyMod(mod module.Version) bool {
+ ok := true
+ zip := filepath.Join(srcV, "cache", mod.Path+"@"+mod.Version, "zip")
+ _, zipErr := os.Stat(zip)
+ dir := filepath.Join(srcV, mod.Path+"@"+mod.Version)
+ _, dirErr := os.Stat(dir)
+ data, err := ioutil.ReadFile(zip + "hash")
+ if err != nil {
+ if zipErr != nil && os.IsNotExist(zipErr) && dirErr != nil && os.IsNotExist(dirErr) {
+ // Nothing downloaded yet. Nothing to verify.
+ return true
+ }
+ base.Errorf("%s %s: missing ziphash: %v", mod.Path, mod.Version, err)
+ return false
+ }
+ h := string(bytes.TrimSpace(data))
+
+ if zipErr != nil && os.IsNotExist(zipErr) {
+ // ok
+ } else {
+ hZ, err := dirhash.HashZip(zip, dirhash.DefaultHash)
+ if err != nil {
+ base.Errorf("%s %s: %v", mod.Path, mod.Version, err)
+ return false
+ } else if hZ != h {
+ base.Errorf("%s %s: zip has been modified (%v)", mod.Path, mod.Version, zip)
+ ok = false
+ }
+ }
+ if dirErr != nil && os.IsNotExist(dirErr) {
+ // ok
+ } else {
+ hD, err := dirhash.HashDir(dir, mod.Path+"@"+mod.Version, dirhash.DefaultHash)
+ if err != nil {
+
+ base.Errorf("%s %s: %v", mod.Path, mod.Version, err)
+ return false
+ }
+ if hD != h {
+ base.Errorf("%s %s: dir has been modified (%v)", mod.Path, mod.Version, dir)
+ ok = false
+ }
+ }
+ return ok
+}