//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) shasumPath := binaryPath + ".sha256" shasum, err := os.Create(shasumPath) if err != nil { return fmt.Errorf("unable to create %s; %w", shasumPath, err) } defer shasum.Close() shasumURL := m[version]["shasum"] shasumResp, err := client.Get(shasumURL) if err != nil { return err } defer shasumResp.Body.Close() size, err = io.Copy(shasum, shasumResp.Body) if err != nil { return nil } fmt.Printf("Downloaded %s with size %d.\n", shasumPath, 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 }