This repository has been archived on 2023-11-08. You can view files and clone it, but cannot push or open issues/pull-requests.
eget/forge/forge.go

111 lines
2.3 KiB
Go

package forge
import (
"errors"
"fmt"
"net/url"
"os"
"regexp"
"runtime"
"strings"
)
var (
amd64Re = regexp.MustCompile(`amd64|x86_64|64-bit|[^mhv]64`)
linuxRe = regexp.MustCompile(`(?i)linux`)
windowsRe = regexp.MustCompile(`(?i)windows|\Awin`)
installerRe = regexp.MustCompile(`\.deb|\.msi`)
)
type Release struct {
Name string
Assets []Asset
}
type Asset struct {
Name string
DownloadURL string
Version string // Release.Name
}
type Forger interface {
Name() string
latestRelease() (Release, error)
tagRelease(tag string) (Release, error)
}
func splitURI(uri string) (string, []string, error) {
if !strings.HasPrefix(uri, "http") {
uri = "https://" + uri
}
u, err := url.ParseRequestURI(uri)
if err != nil {
return "", nil, fmt.Errorf("could not parse URI: %w", err)
}
u.Scheme = "https"
paths := strings.FieldsFunc(u.Path, func(r rune) bool { return r == '/' })
u.Path = ""
return u.String(), paths, nil
}
func TagRelease(f Forger, tag, override string) (Asset, error) {
var asset Asset
var re *regexp.Regexp
switch runtime.GOOS {
case "linux":
re = linuxRe
case "windows":
re = windowsRe
default:
return asset, fmt.Errorf("%q is not a supported OS", runtime.GOOS)
}
release, err := f.tagRelease(tag)
if err != nil {
return asset, fmt.Errorf("could not get %q release: %w", tag, err)
}
overrideName := os.Expand(override, func(s string) string {
switch strings.ToLower(s) {
case "os", "goos":
return runtime.GOOS
case "arch", "goarch":
return runtime.GOARCH
case "version":
return release.Name
default:
return ""
}
})
for _, a := range release.Assets {
match := strings.EqualFold(a.Name, overrideName)
if overrideName == "" {
match = amd64Re.MatchString(a.Name) && re.MatchString(a.Name) && !installerRe.MatchString(a.Name)
}
if match {
fmt.Printf("found %q\n", a.Name)
asset = a
break
}
}
if asset.Name == "" {
return asset, errors.New("no release found for this OS")
}
asset.Version = release.Name
return asset, nil
}
func LatestRelease(f Forger, override string) (Asset, error) {
var asset Asset
release, err := f.latestRelease()
if err != nil {
return asset, fmt.Errorf("could not get latest release: %w", err)
}
return TagRelease(f, release.Name, override)
}