services/magefiles/download_forgejo.go

125 lines
2.2 KiB
Go

//go:build mage
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"github.com/magefile/mage/sh"
)
type forgejoDownload map[string]map[string]string
const (
forgejoDownloadFileFormat string = "forgejo-%s-linux-amd64"
forgejoBinariesJson string = "./magefiles/data/forgejo.json"
)
func downloadForgejo(version string) error {
downloadFolder := filepath.Join(rootBuildDir, "forgejo")
if err := os.MkdirAll(downloadFolder, 0o750); err != nil {
return fmt.Errorf("unable to make %s; %w", downloadFolder, err)
}
binaryPath := filepath.Join(
downloadFolder,
fmt.Sprintf(forgejoDownloadFileFormat, version),
)
_, err := os.Stat(binaryPath)
if err == nil {
fmt.Printf("Forgejo %s is already downloaded.\n", version)
return nil
}
m, err := newForgejoDownloadMap()
if err != nil {
return err
}
binary, err := os.Create(binaryPath)
if err != nil {
return err
}
defer binary.Close()
client := http.Client{
CheckRedirect: func(r *http.Request, _ []*http.Request) error {
r.URL.Opaque = r.URL.Path
return nil
},
}
binaryURL := m[version]["binary"]
resp, err := client.Get(binaryURL)
if err != nil {
return err
}
defer resp.Body.Close()
size, err := io.Copy(binary, resp.Body)
if err != nil {
return err
}
fmt.Printf("Downloaded %s with size %d.\n", binaryPath, size)
signaturePath := binaryPath + ".asc"
signature, err := os.Create(signaturePath)
if err != nil {
return err
}
defer signature.Close()
signatureURL := m[version]["signature"]
sigResp, err := client.Get(signatureURL)
if err != nil {
return err
}
defer sigResp.Body.Close()
size, err = io.Copy(signature, sigResp.Body)
if err != nil {
return nil
}
fmt.Printf("Downloaded %s with size %d.\n", signaturePath, size)
if err = sh.Run(
"gpg",
"--verify",
signaturePath,
binaryPath,
); err != nil {
return fmt.Errorf("GPG verification failed; %w", err)
}
return nil
}
func newForgejoDownloadMap() (forgejoDownload, error) {
m := make(forgejoDownload)
f, err := os.Open(forgejoBinariesJson)
if err != nil {
return nil, err
}
defer f.Close()
decoder := json.NewDecoder(f)
if err = decoder.Decode(&m); err != nil {
return nil, err
}
return m, nil
}