-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.go
129 lines (107 loc) · 2.95 KB
/
app.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
128
129
package vin
import (
"context"
"fmt"
"path/filepath"
"regexp"
"runtime"
"strings"
"github.com/google/go-github/v33/github"
)
// App represents an application.
type App struct {
// Repo is the GitHub repository name in "owner/repo" format.
Repo string `toml:"repo,omitempty"`
// Tag is the tag on GitHub.
Tag string `toml:"tag,omitempty"`
// Keywords is a list of keywords for selecting suitable assets from multiple assets.
Keywords []string `toml:"keywords,omitempty"`
// Name is the name of the executable file.
Name string `toml:"name,omitempty"`
// Hosts is a list of host names.
Hosts []string `toml:"hosts,omitempty"`
// Priority is the priority of the application.
Priority int `toml:"priority,omitempty"`
// Command is the command to run after installation.
Command string `toml:"command,omitempty"`
release *github.RepositoryRelease
}
func (a *App) defaultKeywords() []string {
goos := runtime.GOOS
goarch := runtime.GOARCH
return []string{goos, goarch}
}
func (a *App) parseOwnerAndRepo(s string) (string, string, error) {
x := strings.Split(s, "/")
if len(x) != 2 { //nolint:gomnd
return "", "", fmt.Errorf("invalid format: %s", s)
}
return x[0], x[1], nil
}
func (a *App) getRepositoryRelease(gh *github.Client, owner, repo, tag string) (*github.RepositoryRelease, error) {
ctx := context.Background()
if tag == "" {
release, _, err := gh.Repositories.GetLatestRelease(ctx, owner, repo)
if err != nil {
return nil, err
}
return release, err
}
release, _, err := gh.Repositories.GetReleaseByTag(ctx, owner, repo, tag)
if err != nil {
return nil, err
}
return release, err
}
func (a *App) init(gh *github.Client) error {
if len(a.Keywords) == 0 {
a.Keywords = a.defaultKeywords()
}
owner, repo, err := a.parseOwnerAndRepo(a.Repo)
if err != nil {
return err
}
release, err := a.getRepositoryRelease(gh, owner, repo, a.Tag)
if err != nil {
return err
}
a.release = release
return nil
}
// contains returns whether all substrs are within s (ignore case).
func contains(s string, substrs []string) bool {
s = strings.ToLower(s)
for _, substr := range substrs {
if !strings.Contains(s, strings.ToLower(substr)) {
return false
}
}
return true
}
var (
anyExtRegexp = regexp.MustCompile(`\.[a-zA-Z0-9]+$`)
archiveRegexp = regexp.MustCompile(`\.(tar\.gz|tgz|zip)$`)
)
func (a *App) suitableURLs(urls []string) []string {
r := make([]string, 0)
for _, url := range urls {
name := filepath.Base(url)
if contains(name, a.Keywords) && (!anyExtRegexp.MatchString(name) || archiveRegexp.MatchString(name)) {
r = append(r, url)
}
}
return r
}
func (a *App) SuitableAssetURLs() []string {
urls := make([]string, 0)
for _, asset := range a.release.Assets {
urls = append(urls, *asset.BrowserDownloadURL)
}
return a.suitableURLs(urls)
}
func (a *App) TagName() (string, error) {
if a.release == nil {
return "", fmt.Errorf("failed to reference tag name; invalid release")
}
return *a.release.TagName, nil
}