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/web/web.go

116 lines
2.2 KiB
Go

package web
import (
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"regexp"
"runtime"
"github.com/adrg/xdg"
"github.com/mholt/archiver/v3"
"go.jolheiser.com/eget/forge"
)
var (
amd64Re = regexp.MustCompile(`amd64|x86_64|64-bit`)
linuxRe = regexp.MustCompile(`linux`)
windowsRe = regexp.MustCompile(`windows`)
)
func Install(f forge.Forger) error {
var re *regexp.Regexp
switch runtime.GOOS {
case "linux":
re = linuxRe
case "windows":
re = windowsRe
default:
return fmt.Errorf("%q is not a supported OS", runtime.GOOS)
}
latest, err := f.Latest()
if err != nil {
return err
}
var asset forge.Asset
for _, a := range latest.Assets {
if amd64Re.MatchString(a.DownloadURL) && re.MatchString(a.DownloadURL) {
asset = a
}
}
if asset.Name == "" {
return errors.New("no release found for this OS")
}
tmp, err := os.MkdirTemp(os.TempDir(), "eget-*")
if err != nil {
return err
}
defer os.RemoveAll(tmp)
resp, err := http.Get(asset.DownloadURL)
if err != nil {
return err
}
defer resp.Body.Close()
tmpDest := filepath.Join(tmp, asset.Name)
fi, err := os.Create(tmpDest)
if err != nil {
return err
}
if _, err := io.Copy(fi, resp.Body); err != nil {
return err
}
if err := fi.Close(); err != nil {
return err
}
if err := unpack(tmpDest, f.Name()); err != nil {
return fmt.Errorf("could not unpack download: %w", err)
}
return nil
}
func detectRootDir(path string) bool {
infos, err := os.ReadDir(path)
if err != nil {
return false
}
return len(infos) != 1
}
func unpack(src, name string) error {
dest := filepath.Join(xdg.DataHome, name)
uaIface, err := archiver.ByExtension(src)
if err != nil {
return err
}
u, ok := uaIface.(archiver.Unarchiver)
if !ok {
d, ok := uaIface.(archiver.Decompressor)
if !ok {
return fmt.Errorf("format specified by source filename is not an archive or compression format: %s (%T)", src, uaIface)
}
var binExt string
if runtime.GOOS == "windows" {
binExt = ".exe"
}
dest = filepath.Join(dest, name+binExt)
c := archiver.FileCompressor{Decompressor: d}
if err := c.DecompressFile(src, dest); err != nil {
return err
}
return os.Chmod(dest, 0o755)
}
return u.Unarchive(src, dest)
}