github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/go/internal/modload/build.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package modload
     6  
     7  import (
     8  	"bytes"
     9  	"cmd/go/internal/base"
    10  	"cmd/go/internal/cfg"
    11  	"cmd/go/internal/modfetch"
    12  	"cmd/go/internal/modinfo"
    13  	"cmd/go/internal/module"
    14  	"cmd/go/internal/search"
    15  	"encoding/hex"
    16  	"fmt"
    17  	"internal/goroot"
    18  	"os"
    19  	"path/filepath"
    20  	"runtime/debug"
    21  	"strings"
    22  )
    23  
    24  var (
    25  	infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
    26  	infoEnd, _   = hex.DecodeString("f932433186182072008242104116d8f2")
    27  )
    28  
    29  func isStandardImportPath(path string) bool {
    30  	return findStandardImportPath(path) != ""
    31  }
    32  
    33  func findStandardImportPath(path string) string {
    34  	if path == "" {
    35  		panic("findStandardImportPath called with empty path")
    36  	}
    37  	if search.IsStandardImportPath(path) {
    38  		if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
    39  			return filepath.Join(cfg.GOROOT, "src", path)
    40  		}
    41  		if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, "vendor/"+path) {
    42  			return filepath.Join(cfg.GOROOT, "src/vendor", path)
    43  		}
    44  	}
    45  	return ""
    46  }
    47  
    48  func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
    49  	if isStandardImportPath(pkgpath) || !Enabled() {
    50  		return nil
    51  	}
    52  	return moduleInfo(findModule(pkgpath, pkgpath), true)
    53  }
    54  
    55  func ModuleInfo(path string) *modinfo.ModulePublic {
    56  	if !Enabled() {
    57  		return nil
    58  	}
    59  
    60  	if i := strings.Index(path, "@"); i >= 0 {
    61  		return moduleInfo(module.Version{Path: path[:i], Version: path[i+1:]}, false)
    62  	}
    63  
    64  	for _, m := range BuildList() {
    65  		if m.Path == path {
    66  			return moduleInfo(m, true)
    67  		}
    68  	}
    69  
    70  	return &modinfo.ModulePublic{
    71  		Path: path,
    72  		Error: &modinfo.ModuleError{
    73  			Err: "module not in current build",
    74  		},
    75  	}
    76  }
    77  
    78  // addUpdate fills in m.Update if an updated version is available.
    79  func addUpdate(m *modinfo.ModulePublic) {
    80  	if m.Version != "" {
    81  		if info, err := Query(m.Path, "latest", Allowed); err == nil && info.Version != m.Version {
    82  			m.Update = &modinfo.ModulePublic{
    83  				Path:    m.Path,
    84  				Version: info.Version,
    85  				Time:    &info.Time,
    86  			}
    87  		}
    88  	}
    89  }
    90  
    91  // addVersions fills in m.Versions with the list of known versions.
    92  func addVersions(m *modinfo.ModulePublic) {
    93  	m.Versions, _ = versions(m.Path)
    94  }
    95  
    96  func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
    97  	if m == Target {
    98  		info := &modinfo.ModulePublic{
    99  			Path:    m.Path,
   100  			Version: m.Version,
   101  			Main:    true,
   102  		}
   103  		if HasModRoot() {
   104  			info.Dir = ModRoot()
   105  			info.GoMod = filepath.Join(info.Dir, "go.mod")
   106  			if modFile.Go != nil {
   107  				info.GoVersion = modFile.Go.Version
   108  			}
   109  		}
   110  		return info
   111  	}
   112  
   113  	info := &modinfo.ModulePublic{
   114  		Path:     m.Path,
   115  		Version:  m.Version,
   116  		Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path],
   117  	}
   118  	if loaded != nil {
   119  		info.GoVersion = loaded.goVersion[m.Path]
   120  	}
   121  
   122  	if cfg.BuildMod == "vendor" {
   123  		info.Dir = filepath.Join(ModRoot(), "vendor", m.Path)
   124  		return info
   125  	}
   126  
   127  	// complete fills in the extra fields in m.
   128  	complete := func(m *modinfo.ModulePublic) {
   129  		if m.Version != "" {
   130  			if q, err := Query(m.Path, m.Version, nil); err != nil {
   131  				m.Error = &modinfo.ModuleError{Err: err.Error()}
   132  			} else {
   133  				m.Version = q.Version
   134  				m.Time = &q.Time
   135  			}
   136  
   137  			mod := module.Version{Path: m.Path, Version: m.Version}
   138  			gomod, err := modfetch.CachePath(mod, "mod")
   139  			if err == nil {
   140  				if info, err := os.Stat(gomod); err == nil && info.Mode().IsRegular() {
   141  					m.GoMod = gomod
   142  				}
   143  			}
   144  			dir, err := modfetch.DownloadDir(mod)
   145  			if err == nil {
   146  				if info, err := os.Stat(dir); err == nil && info.IsDir() {
   147  					m.Dir = dir
   148  				}
   149  			}
   150  		}
   151  	}
   152  
   153  	if !fromBuildList {
   154  		complete(info)
   155  		return info
   156  	}
   157  
   158  	r := Replacement(m)
   159  	if r.Path == "" {
   160  		complete(info)
   161  		return info
   162  	}
   163  
   164  	// Don't hit the network to fill in extra data for replaced modules.
   165  	// The original resolved Version and Time don't matter enough to be
   166  	// worth the cost, and we're going to overwrite the GoMod and Dir from the
   167  	// replacement anyway. See https://golang.org/issue/27859.
   168  	info.Replace = &modinfo.ModulePublic{
   169  		Path:      r.Path,
   170  		Version:   r.Version,
   171  		GoVersion: info.GoVersion,
   172  	}
   173  	if r.Version == "" {
   174  		if filepath.IsAbs(r.Path) {
   175  			info.Replace.Dir = r.Path
   176  		} else {
   177  			info.Replace.Dir = filepath.Join(ModRoot(), r.Path)
   178  		}
   179  	}
   180  	complete(info.Replace)
   181  	info.Dir = info.Replace.Dir
   182  	info.GoMod = filepath.Join(info.Dir, "go.mod")
   183  	return info
   184  }
   185  
   186  func PackageBuildInfo(path string, deps []string) string {
   187  	if isStandardImportPath(path) || !Enabled() {
   188  		return ""
   189  	}
   190  
   191  	target := findModule(path, path)
   192  	mdeps := make(map[module.Version]bool)
   193  	for _, dep := range deps {
   194  		if !isStandardImportPath(dep) {
   195  			mdeps[findModule(path, dep)] = true
   196  		}
   197  	}
   198  	var mods []module.Version
   199  	delete(mdeps, target)
   200  	for mod := range mdeps {
   201  		mods = append(mods, mod)
   202  	}
   203  	module.Sort(mods)
   204  
   205  	var buf bytes.Buffer
   206  	fmt.Fprintf(&buf, "path\t%s\n", path)
   207  	tv := target.Version
   208  	if tv == "" {
   209  		tv = "(devel)"
   210  	}
   211  	fmt.Fprintf(&buf, "mod\t%s\t%s\t%s\n", target.Path, tv, modfetch.Sum(target))
   212  	for _, mod := range mods {
   213  		mv := mod.Version
   214  		if mv == "" {
   215  			mv = "(devel)"
   216  		}
   217  		r := Replacement(mod)
   218  		h := ""
   219  		if r.Path == "" {
   220  			h = "\t" + modfetch.Sum(mod)
   221  		}
   222  		fmt.Fprintf(&buf, "dep\t%s\t%s%s\n", mod.Path, mod.Version, h)
   223  		if r.Path != "" {
   224  			fmt.Fprintf(&buf, "=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r))
   225  		}
   226  	}
   227  	return buf.String()
   228  }
   229  
   230  // findModule returns the module containing the package at path,
   231  // needed to build the package at target.
   232  func findModule(target, path string) module.Version {
   233  	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
   234  	if ok {
   235  		if pkg.err != nil {
   236  			base.Fatalf("build %v: cannot load %v: %v", target, path, pkg.err)
   237  		}
   238  		return pkg.mod
   239  	}
   240  
   241  	if path == "command-line-arguments" {
   242  		return Target
   243  	}
   244  
   245  	if printStackInDie {
   246  		debug.PrintStack()
   247  	}
   248  	base.Fatalf("build %v: cannot find module for path %v", target, path)
   249  	panic("unreachable")
   250  }
   251  
   252  func ModInfoProg(info string) []byte {
   253  	// Inject a variable with the debug information as runtime/debug.modinfo,
   254  	// but compile it in package main so that it is specific to the binary.
   255  	//
   256  	// The variable must be a literal so that it will have the correct value
   257  	// before the initializer for package main runs.
   258  	//
   259  	// We also want the value to be present even if runtime/debug.modinfo is
   260  	// otherwise unused in the rest of the program. Reading it in an init function
   261  	// suffices for now.
   262  
   263  	return []byte(fmt.Sprintf(`package main
   264  import _ "unsafe"
   265  //go:linkname __debug_modinfo__ runtime/debug.modinfo
   266  var __debug_modinfo__ = %q
   267  var keepalive_modinfo = __debug_modinfo__
   268  func init() { keepalive_modinfo = __debug_modinfo__ }
   269  	`, string(infoStart)+info+string(infoEnd)))
   270  }