summaryrefslogtreecommitdiff
path: root/libgo/go/cmd/go/internal/modload/build.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/cmd/go/internal/modload/build.go')
-rw-r--r--libgo/go/cmd/go/internal/modload/build.go243
1 files changed, 243 insertions, 0 deletions
diff --git a/libgo/go/cmd/go/internal/modload/build.go b/libgo/go/cmd/go/internal/modload/build.go
new file mode 100644
index 00000000000..558401d01f6
--- /dev/null
+++ b/libgo/go/cmd/go/internal/modload/build.go
@@ -0,0 +1,243 @@
+// 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 modload
+
+import (
+ "bytes"
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/modinfo"
+ "cmd/go/internal/module"
+ "cmd/go/internal/search"
+ "encoding/hex"
+ "fmt"
+ "internal/goroot"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+var (
+ infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+ infoEnd, _ = hex.DecodeString("f932433186182072008242104116d8f2")
+)
+
+func isStandardImportPath(path string) bool {
+ return findStandardImportPath(path) != ""
+}
+
+func findStandardImportPath(path string) string {
+ if search.IsStandardImportPath(path) {
+ if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
+ return filepath.Join(cfg.GOROOT, "src", path)
+ }
+ if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, "vendor/"+path) {
+ return filepath.Join(cfg.GOROOT, "src/vendor", path)
+ }
+ }
+ return ""
+}
+
+func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
+ if isStandardImportPath(pkgpath) || !Enabled() {
+ return nil
+ }
+ return moduleInfo(findModule(pkgpath, pkgpath), true)
+}
+
+func ModuleInfo(path string) *modinfo.ModulePublic {
+ if !Enabled() {
+ return nil
+ }
+
+ if i := strings.Index(path, "@"); i >= 0 {
+ return moduleInfo(module.Version{Path: path[:i], Version: path[i+1:]}, false)
+ }
+
+ for _, m := range BuildList() {
+ if m.Path == path {
+ return moduleInfo(m, true)
+ }
+ }
+
+ return &modinfo.ModulePublic{
+ Path: path,
+ Error: &modinfo.ModuleError{
+ Err: "module not in current build",
+ },
+ }
+}
+
+// addUpdate fills in m.Update if an updated version is available.
+func addUpdate(m *modinfo.ModulePublic) {
+ if m.Version != "" {
+ if info, err := Query(m.Path, "latest", Allowed); err == nil && info.Version != m.Version {
+ m.Update = &modinfo.ModulePublic{
+ Path: m.Path,
+ Version: info.Version,
+ Time: &info.Time,
+ }
+ }
+ }
+}
+
+// addVersions fills in m.Versions with the list of known versions.
+func addVersions(m *modinfo.ModulePublic) {
+ m.Versions, _ = versions(m.Path)
+}
+
+func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
+ if m == Target {
+ info := &modinfo.ModulePublic{
+ Path: m.Path,
+ Version: m.Version,
+ Main: true,
+ Dir: ModRoot,
+ GoMod: filepath.Join(ModRoot, "go.mod"),
+ }
+ if modFile.Go != nil {
+ info.GoVersion = modFile.Go.Version
+ }
+ return info
+ }
+
+ info := &modinfo.ModulePublic{
+ Path: m.Path,
+ Version: m.Version,
+ Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path],
+ }
+ if loaded != nil {
+ info.GoVersion = loaded.goVersion[m.Path]
+ }
+
+ if cfg.BuildMod == "vendor" {
+ info.Dir = filepath.Join(ModRoot, "vendor", m.Path)
+ return info
+ }
+
+ // complete fills in the extra fields in m.
+ complete := func(m *modinfo.ModulePublic) {
+ if m.Version != "" {
+ if q, err := Query(m.Path, m.Version, nil); err != nil {
+ m.Error = &modinfo.ModuleError{Err: err.Error()}
+ } else {
+ m.Version = q.Version
+ m.Time = &q.Time
+ }
+
+ mod := module.Version{Path: m.Path, Version: m.Version}
+ gomod, err := modfetch.CachePath(mod, "mod")
+ if err == nil {
+ if info, err := os.Stat(gomod); err == nil && info.Mode().IsRegular() {
+ m.GoMod = gomod
+ }
+ }
+ dir, err := modfetch.DownloadDir(mod)
+ if err == nil {
+ if info, err := os.Stat(dir); err == nil && info.IsDir() {
+ m.Dir = dir
+ }
+ }
+ }
+ if cfg.BuildMod == "vendor" {
+ m.Dir = filepath.Join(ModRoot, "vendor", m.Path)
+ }
+ }
+
+ complete(info)
+
+ if fromBuildList {
+ if r := Replacement(m); r.Path != "" {
+ info.Replace = &modinfo.ModulePublic{
+ Path: r.Path,
+ Version: r.Version,
+ GoVersion: info.GoVersion,
+ }
+ if r.Version == "" {
+ if filepath.IsAbs(r.Path) {
+ info.Replace.Dir = r.Path
+ } else {
+ info.Replace.Dir = filepath.Join(ModRoot, r.Path)
+ }
+ }
+ complete(info.Replace)
+ info.Dir = info.Replace.Dir
+ info.GoMod = filepath.Join(info.Dir, "go.mod")
+ info.Error = nil // ignore error loading original module version (it has been replaced)
+ }
+ }
+
+ return info
+}
+
+func PackageBuildInfo(path string, deps []string) string {
+ if isStandardImportPath(path) || !Enabled() {
+ return ""
+ }
+ target := findModule(path, path)
+ mdeps := make(map[module.Version]bool)
+ for _, dep := range deps {
+ if !isStandardImportPath(dep) {
+ mdeps[findModule(path, dep)] = true
+ }
+ }
+ var mods []module.Version
+ delete(mdeps, target)
+ for mod := range mdeps {
+ mods = append(mods, mod)
+ }
+ module.Sort(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, modfetch.Sum(target))
+ for _, mod := range mods {
+ mv := mod.Version
+ if mv == "" {
+ mv = "(devel)"
+ }
+ r := Replacement(mod)
+ h := ""
+ if r.Path == "" {
+ h = "\t" + modfetch.Sum(mod)
+ }
+ fmt.Fprintf(&buf, "dep\t%s\t%s%s\n", mod.Path, mod.Version, h)
+ if r.Path != "" {
+ fmt.Fprintf(&buf, "=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r))
+ }
+ }
+ return buf.String()
+}
+
+func findModule(target, path string) module.Version {
+ // TODO: This should use loaded.
+ if path == "." {
+ return buildList[0]
+ }
+ for _, mod := range buildList {
+ if maybeInModule(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)))
+}