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) }