Source file src/pkg/cmd/go/internal/modload/build.go
1
2
3
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 "cmd/go/internal/semver"
16 "encoding/hex"
17 "fmt"
18 "internal/goroot"
19 "os"
20 "path/filepath"
21 "runtime/debug"
22 "strings"
23 )
24
25 var (
26 infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
27 infoEnd, _ = hex.DecodeString("f932433186182072008242104116d8f2")
28 )
29
30 func isStandardImportPath(path string) bool {
31 return findStandardImportPath(path) != ""
32 }
33
34 func findStandardImportPath(path string) string {
35 if path == "" {
36 panic("findStandardImportPath called with empty path")
37 }
38 if search.IsStandardImportPath(path) {
39 if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
40 return filepath.Join(cfg.GOROOT, "src", path)
41 }
42 }
43 return ""
44 }
45
46 func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
47 if isStandardImportPath(pkgpath) || !Enabled() {
48 return nil
49 }
50 return moduleInfo(findModule(pkgpath, pkgpath), true)
51 }
52
53 func ModuleInfo(path string) *modinfo.ModulePublic {
54 if !Enabled() {
55 return nil
56 }
57
58 if i := strings.Index(path, "@"); i >= 0 {
59 return moduleInfo(module.Version{Path: path[:i], Version: path[i+1:]}, false)
60 }
61
62 for _, m := range BuildList() {
63 if m.Path == path {
64 return moduleInfo(m, true)
65 }
66 }
67
68 return &modinfo.ModulePublic{
69 Path: path,
70 Error: &modinfo.ModuleError{
71 Err: "module not in current build",
72 },
73 }
74 }
75
76
77 func addUpdate(m *modinfo.ModulePublic) {
78 if m.Version == "" {
79 return
80 }
81
82 if info, err := Query(m.Path, "upgrade", m.Version, Allowed); err == nil && semver.Compare(info.Version, m.Version) > 0 {
83 m.Update = &modinfo.ModulePublic{
84 Path: m.Path,
85 Version: info.Version,
86 Time: &info.Time,
87 }
88 }
89 }
90
91
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
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
165
166
167
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, mv, 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
231
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
254
255
256
257
258
259 return []byte(fmt.Sprintf(`package main
260 import _ "unsafe"
261 //go:linkname __debug_modinfo__ runtime.modinfo
262 var __debug_modinfo__ = %q
263 `, string(infoStart)+info+string(infoEnd)))
264 }
265
View as plain text