/
gomod.go
116 lines (96 loc) · 2.37 KB
/
gomod.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package mod
import (
"bytes"
"context"
"encoding/json"
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"strings"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
type goModule struct {
Path string
Dir string
Version string
}
func goGetByFilepath(filename, ver string) (err error) {
if names := strings.Split(filename, "/"); len(names) > 0 {
for i := range names[1:] {
gogetPath := path.Join(names[:1+i]...)
if ver != "" {
gogetPath = gogetPath + "@" + ver
}
err = goGet(gogetPath)
if err == nil {
return nil
}
logrus.Debugf("go get %s error: %s\n", gogetPath, err.Error())
}
}
return errors.New("no such module")
}
func goGet(args ...string) error {
if err := runGo(context.Background(), logrus.StandardLogger().Out, append([]string{"get", "-u"}, args...)...); err != nil { // nolint:lll
return errors.Wrapf(err, "failed to get %q", args)
}
return nil
}
func (m *Modules) Load() error {
out := ioutil.Discard
err := runGo(context.Background(), out, "mod", "download")
if err != nil {
return errors.Wrap(err, "failed to download modules")
}
b := &bytes.Buffer{}
err = runGo(context.Background(), b, "list", "-m", "-json", "all")
if err != nil {
return errors.Wrap(err, "failed to list modules")
}
dec := json.NewDecoder(b)
for {
goMod := &goModule{}
if err := dec.Decode(goMod); err != nil {
if err == io.EOF {
break
}
return errors.Wrap(err, "failed to decode modules list")
}
m.Add(&Module{
Name: goMod.Path,
Dir: goMod.Dir,
Version: goMod.Version,
})
}
return nil
}
func runGo(ctx context.Context, out io.Writer, args ...string) error {
cmd := exec.CommandContext(ctx, "go", args...)
wd, err := os.Getwd()
if err != nil {
return errors.Errorf("get current working directory error: %s\n", err.Error())
}
cmd.Dir = wd
errbuf := new(bytes.Buffer)
cmd.Stderr = errbuf
cmd.Stdout = out
logrus.Debugf("running command `go %v`\n", strings.Join(args, " "))
if err := cmd.Run(); err != nil {
if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
return nil
}
_, ok := err.(*exec.ExitError)
if !ok {
return errors.Errorf("failed to execute 'go %v': %s %T", args, err, err)
}
// Too old Go version
if strings.Contains(errbuf.String(), "flag provided but not defined") {
return nil
}
return errors.Errorf("go command failed: %s", errbuf)
}
return nil
}