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.
11 "cmd/go/internal/modfetch"
12 "cmd/go/internal/modinfo"
13 "cmd/go/internal/module"
14 "cmd/go/internal/search"
24 infoStart
, _
= hex
.DecodeString("3077af0c9274080241e1c107e6d618e6")
25 infoEnd
, _
= hex
.DecodeString("f932433186182072008242104116d8f2")
28 func isStandardImportPath(path
string) bool {
29 return findStandardImportPath(path
) != ""
32 func findStandardImportPath(path
string) string {
33 if search
.IsStandardImportPath(path
) {
34 if goroot
.IsStandardPackage(cfg
.GOROOT
, cfg
.BuildContext
.Compiler
, path
) {
35 return filepath
.Join(cfg
.GOROOT
, "src", path
)
37 if goroot
.IsStandardPackage(cfg
.GOROOT
, cfg
.BuildContext
.Compiler
, "vendor/"+path
) {
38 return filepath
.Join(cfg
.GOROOT
, "src/vendor", path
)
44 func PackageModuleInfo(pkgpath
string) *modinfo
.ModulePublic
{
45 if isStandardImportPath(pkgpath
) ||
!Enabled() {
48 return moduleInfo(findModule(pkgpath
, pkgpath
), true)
51 func ModuleInfo(path
string) *modinfo
.ModulePublic
{
56 if i
:= strings
.Index(path
, "@"); i
>= 0 {
57 return moduleInfo(module
.Version
{Path
: path
[:i
], Version
: path
[i
+1:]}, false)
60 for _
, m
:= range BuildList() {
62 return moduleInfo(m
, true)
66 return &modinfo
.ModulePublic
{
68 Error
: &modinfo
.ModuleError
{
69 Err
: "module not in current build",
74 // addUpdate fills in m.Update if an updated version is available.
75 func addUpdate(m
*modinfo
.ModulePublic
) {
77 if info
, err
:= Query(m
.Path
, "latest", Allowed
); err
== nil && info
.Version
!= m
.Version
{
78 m
.Update
= &modinfo
.ModulePublic
{
80 Version
: info
.Version
,
87 // addVersions fills in m.Versions with the list of known versions.
88 func addVersions(m
*modinfo
.ModulePublic
) {
89 m
.Versions
, _
= versions(m
.Path
)
92 func moduleInfo(m module
.Version
, fromBuildList
bool) *modinfo
.ModulePublic
{
94 info
:= &modinfo
.ModulePublic
{
99 GoMod
: filepath
.Join(ModRoot
, "go.mod"),
101 if modFile
.Go
!= nil {
102 info
.GoVersion
= modFile
.Go
.Version
107 info
:= &modinfo
.ModulePublic
{
110 Indirect
: fromBuildList
&& loaded
!= nil && !loaded
.direct
[m
.Path
],
113 info
.GoVersion
= loaded
.goVersion
[m
.Path
]
116 if cfg
.BuildMod
== "vendor" {
117 info
.Dir
= filepath
.Join(ModRoot
, "vendor", m
.Path
)
121 // complete fills in the extra fields in m.
122 complete
:= func(m
*modinfo
.ModulePublic
) {
124 if q
, err
:= Query(m
.Path
, m
.Version
, nil); err
!= nil {
125 m
.Error
= &modinfo
.ModuleError
{Err
: err
.Error()}
127 m
.Version
= q
.Version
131 mod
:= module
.Version
{Path
: m
.Path
, Version
: m
.Version
}
132 gomod
, err
:= modfetch
.CachePath(mod
, "mod")
134 if info
, err
:= os
.Stat(gomod
); err
== nil && info
.Mode().IsRegular() {
138 dir
, err
:= modfetch
.DownloadDir(mod
)
140 if info
, err
:= os
.Stat(dir
); err
== nil && info
.IsDir() {
145 if cfg
.BuildMod
== "vendor" {
146 m
.Dir
= filepath
.Join(ModRoot
, "vendor", m
.Path
)
153 if r
:= Replacement(m
); r
.Path
!= "" {
154 info
.Replace
= &modinfo
.ModulePublic
{
157 GoVersion
: info
.GoVersion
,
160 if filepath
.IsAbs(r
.Path
) {
161 info
.Replace
.Dir
= r
.Path
163 info
.Replace
.Dir
= filepath
.Join(ModRoot
, r
.Path
)
166 complete(info
.Replace
)
167 info
.Dir
= info
.Replace
.Dir
168 info
.GoMod
= filepath
.Join(info
.Dir
, "go.mod")
169 info
.Error
= nil // ignore error loading original module version (it has been replaced)
176 func PackageBuildInfo(path
string, deps
[]string) string {
177 if isStandardImportPath(path
) ||
!Enabled() {
180 target
:= findModule(path
, path
)
181 mdeps
:= make(map[module
.Version
]bool)
182 for _
, dep
:= range deps
{
183 if !isStandardImportPath(dep
) {
184 mdeps
[findModule(path
, dep
)] = true
187 var mods
[]module
.Version
188 delete(mdeps
, target
)
189 for mod
:= range mdeps
{
190 mods
= append(mods
, mod
)
195 fmt
.Fprintf(&buf
, "path\t%s\n", path
)
200 fmt
.Fprintf(&buf
, "mod\t%s\t%s\t%s\n", target
.Path
, tv
, modfetch
.Sum(target
))
201 for _
, mod
:= range mods
{
206 r
:= Replacement(mod
)
209 h
= "\t" + modfetch
.Sum(mod
)
211 fmt
.Fprintf(&buf
, "dep\t%s\t%s%s\n", mod
.Path
, mod
.Version
, h
)
213 fmt
.Fprintf(&buf
, "=>\t%s\t%s\t%s\n", r
.Path
, r
.Version
, modfetch
.Sum(r
))
219 func findModule(target
, path
string) module
.Version
{
220 // TODO: This should use loaded.
224 for _
, mod
:= range buildList
{
225 if maybeInModule(path
, mod
.Path
) {
229 base
.Fatalf("build %v: cannot find module for path %v", target
, path
)
233 func ModInfoProg(info
string) []byte {
234 return []byte(fmt
.Sprintf(`
237 //go:linkname __debug_modinfo__ runtime/debug.modinfo
238 var __debug_modinfo__ string
240 __debug_modinfo__ = %q
242 `, string(infoStart
)+info
+string(infoEnd
)))