-
Notifications
You must be signed in to change notification settings - Fork 0
/
locallist.go
127 lines (116 loc) · 2.51 KB
/
locallist.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
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"errors"
"flag"
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"github.com/koron/goup/internal/verutil"
"golang.org/x/mod/semver"
)
// localList lists all Go versions which locally installed.
func localList(fs *flag.FlagSet, args []string) error {
var root string
var linkname string
fs.StringVar(&root, "root", envGoupRoot(), "root dir to install")
fs.StringVar(&linkname, "linkname", envGoupLinkname(), "name of symbolic link to switch")
if err := fs.Parse(args); err != nil {
return err
}
if root == "" {
fs.PrintDefaults()
return errors.New("required -root")
}
curr, err := localCurrent(filepath.Join(root, linkname))
if err != nil {
return err
}
list, err := listInstalledGo(root)
if err != nil {
return err
}
fmt.Println("Local Version:")
for _, g := range list {
if curr != "" && g.name == curr {
fmt.Printf(" %s (%s)\n", g.name, linkname)
continue
}
fmt.Printf(" %s\n", g.name)
}
return nil
}
// localCurrent gets name of Go directory which is selected as "current"
// version.
func localCurrent(name string) (string, error) {
fi, err := os.Lstat(name)
if err != nil {
if os.IsNotExist(err) {
return "", nil
}
return "", err
}
if fi.Mode()&os.ModeSymlink == 0 {
return "", nil
}
rname, err := filepath.EvalSymlinks(name)
if err != nil {
return "", err
}
return filepath.Base(rname), nil
}
type installedGo struct {
version string
os string
arch string
name string
semver string
}
type installedGos []installedGo
func (list installedGos) filter(f func(installedGo) bool) installedGos {
var res installedGos
for _, g := range list {
if f(g) {
res = append(res, g)
}
}
return res
}
var rxGoDir = regexp.MustCompile(`^(go\d+(?:\.\d+)*(?:(?:rc|beta|alpha)\d+)?)\.(\D[^-]*)-(.+)$`)
// listInstalledGo lists installed Go verions.
func listInstalledGo(root string) (installedGos, error) {
filist, err := os.ReadDir(root)
if err != nil {
return nil, err
}
list := make(installedGos, 0, len(filist))
for _, fi := range filist {
if !fi.IsDir() {
continue
}
m := rxGoDir.FindStringSubmatch(fi.Name())
if m == nil {
continue
}
ver := verutil.Regulate(m[1])
if ver == "" {
continue
}
list = append(list, installedGo{
version: m[1],
os: m[2],
arch: m[3],
name: m[0],
semver: ver,
})
}
sort.Slice(list, func(i, j int) bool {
cmp := semver.Compare(list[i].semver, list[j].semver)
if cmp != 0 {
return cmp > 0
}
return list[i].semver > list[j].semver
})
return list, nil
}