//go:build mage package main import ( "encoding/json" "fmt" "io" "net/http" "os" "path/filepath" "github.com/magefile/mage/sh" ) type forgejoDownload struct { Downloads map[string]forgejoFiles `json:"downloads"` } type forgejoFiles struct { Binary string `json:"binary"` Signature string `json:"signature"` Digest string `json:"digest"` } const ( forgejoBinaryFileFormat string = "forgejo-%s-linux-amd64" forgejoDigestExtension string = ".sha256" forgejoSignatureExtension string = ".asc" forgejoDownloadJson string = "./magefiles/forgejo/download.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(forgejoBinaryFileFormat, version), ) signaturePath := binaryPath + forgejoSignatureExtension digestPath := binaryPath + forgejoDigestExtension _, err := os.Stat(binaryPath) if err == nil { fmt.Printf("Forgejo %s is already downloaded.\n", version) return nil } data, err := newForgejoDownloadData() if err != nil { return err } downloads := []struct { url string path string }{ { url: data.Downloads[version].Binary, path: binaryPath, }, { url: data.Downloads[version].Signature, path: signaturePath, }, { url: data.Downloads[version].Digest, path: digestPath, }, } for _, v := range downloads { if err := func() error { download, err := os.Create(v.path) if err != nil { return fmt.Errorf("unable to create %s; %w", v.path, err) } defer download.Close() client := http.Client{ CheckRedirect: func(r *http.Request, _ []*http.Request) error { r.URL.Opaque = r.URL.Path return nil }, } resp, err := client.Get(v.url) if err != nil { return err } defer resp.Body.Close() size, err := io.Copy(download, resp.Body) if err != nil { return err } fmt.Printf("Downloaded %s with size %d.\n", v.path, size) return nil }(); err != nil { return err } } if err = sh.Run("gpg", "--verify", signaturePath, binaryPath); err != nil { return fmt.Errorf("GPG verification failed; %w", err) } if err := os.Chdir(downloadFolder); err != nil { return err } if err := sh.Run("sha256sum", "--check", fmt.Sprintf(forgejoBinaryFileFormat+forgejoDigestExtension, version)); err != nil { return err } return nil } func newForgejoDownloadData() (forgejoDownload, error) { var data forgejoDownload f, err := os.Open(forgejoDownloadJson) if err != nil { return data, err } defer f.Close() decoder := json.NewDecoder(f) if err = decoder.Decode(&data); err != nil { return data, err } return data, nil }