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
5package modinfo
6
7import (
8	"cmd/go/internal/modfetch/codehost"
9	"encoding/json"
10	"time"
11)
12
13// Note that these structs are publicly visible (part of go list's API)
14// and the fields are documented in the help text in ../list/list.go
15
16type ModulePublic struct {
17	Path       string           `json:",omitempty"` // module path
18	Version    string           `json:",omitempty"` // module version
19	Query      string           `json:",omitempty"` // version query corresponding to this version
20	Versions   []string         `json:",omitempty"` // available module versions
21	Replace    *ModulePublic    `json:",omitempty"` // replaced by this module
22	Time       *time.Time       `json:",omitempty"` // time version was created
23	Update     *ModulePublic    `json:",omitempty"` // available update (with -u)
24	Main       bool             `json:",omitempty"` // is this the main module?
25	Indirect   bool             `json:",omitempty"` // module is only indirectly needed by main module
26	Dir        string           `json:",omitempty"` // directory holding local copy of files, if any
27	GoMod      string           `json:",omitempty"` // path to go.mod file describing module, if any
28	GoVersion  string           `json:",omitempty"` // go version used in module
29	Retracted  []string         `json:",omitempty"` // retraction information, if any (with -retracted or -u)
30	Deprecated string           `json:",omitempty"` // deprecation message, if any (with -u)
31	Error      *ModuleError     `json:",omitempty"` // error loading module
32	Sum        string           `json:",omitempty"` // checksum for path, version (as in go.sum)
33	GoModSum   string           `json:",omitempty"` // checksum for go.mod (as in go.sum)
34	Origin     *codehost.Origin `json:",omitempty"` // provenance of module
35	Reuse      bool             `json:",omitempty"` // reuse of old module info is safe
36}
37
38type ModuleError struct {
39	Err string // error text
40}
41
42type moduleErrorNoMethods ModuleError
43
44// UnmarshalJSON accepts both {"Err":"text"} and "text",
45// so that the output of go mod download -json can still
46// be unmarshaled into a ModulePublic during -reuse processing.
47func (e *ModuleError) UnmarshalJSON(data []byte) error {
48	if len(data) > 0 && data[0] == '"' {
49		return json.Unmarshal(data, &e.Err)
50	}
51	return json.Unmarshal(data, (*moduleErrorNoMethods)(e))
52}
53
54func (m *ModulePublic) String() string {
55	s := m.Path
56	versionString := func(mm *ModulePublic) string {
57		v := mm.Version
58		if len(mm.Retracted) == 0 {
59			return v
60		}
61		return v + " (retracted)"
62	}
63
64	if m.Version != "" {
65		s += " " + versionString(m)
66		if m.Update != nil {
67			s += " [" + versionString(m.Update) + "]"
68		}
69	}
70	if m.Deprecated != "" {
71		s += " (deprecated)"
72	}
73	if m.Replace != nil {
74		s += " => " + m.Replace.Path
75		if m.Replace.Version != "" {
76			s += " " + versionString(m.Replace)
77			if m.Replace.Update != nil {
78				s += " [" + versionString(m.Replace.Update) + "]"
79			}
80		}
81		if m.Replace.Deprecated != "" {
82			s += " (deprecated)"
83		}
84	}
85	return s
86}
87