// Copyright Earl Warren // Copyright Loïc Dachary // SPDX-License-Identifier: MIT package objects import ( "crypto/sha256" "encoding/hex" "fmt" "hash" "io" "net/http" options_http "code.forgejo.org/f3/gof3/v3/options/http" ) type SHASetter interface { SetSHA(sha string) } func FuncReadURLAndSetSHA(newHTTPClient options_http.NewMigrationHTTPClientFun, url string, sha SHASetter) func() io.ReadCloser { return func() io.ReadCloser { req, err := http.NewRequest("GET", url, nil) if err != nil { panic(err) } httpClient := newHTTPClient() resp, err := httpClient.Do(req) if err != nil { panic(fmt.Errorf("while downloading %s %w", url, err)) } return FuncReadAndSetSHA(resp.Body, sha)() } } type readAndSetSHA struct { reader io.Reader closer io.Closer sha SHASetter hasher hash.Hash } func (o *readAndSetSHA) Read(b []byte) (n int, err error) { return o.reader.Read(b) } func (o *readAndSetSHA) Close() error { o.sha.SetSHA(hex.EncodeToString(o.hasher.Sum(nil))) return o.closer.Close() } func newReadAndSetSHA(reader io.ReadCloser, sha SHASetter) *readAndSetSHA { hasher := sha256.New() return &readAndSetSHA{ reader: io.TeeReader(reader, hasher), closer: reader, sha: sha, hasher: hasher, } } func FuncReadAndSetSHA(reader io.ReadCloser, sha SHASetter) func() io.ReadCloser { return func() io.ReadCloser { return newReadAndSetSHA(reader, sha) } }