1
0
out-of-tree/distro/debian/snapshot/mr/mr.go

162 lines
3.5 KiB
Go
Raw Normal View History

2023-05-11 10:21:21 +00:00
package mr
import (
2023-05-11 16:07:15 +00:00
"context"
2023-05-11 10:21:21 +00:00
"encoding/json"
2023-05-11 11:54:35 +00:00
"errors"
2023-05-11 10:21:21 +00:00
"fmt"
"net/http"
"net/url"
2023-05-11 16:07:15 +00:00
"time"
"github.com/rs/zerolog/log"
"golang.org/x/time/rate"
2023-05-11 10:21:21 +00:00
)
const apiURL = "https://snapshot.debian.org/mr"
2023-05-11 16:07:15 +00:00
var Limiter = rate.NewLimiter(rate.Every(time.Second), 10)
// Retries in case of 5xx errors
var Retries = 10
2023-05-11 10:21:21 +00:00
// https://salsa.debian.org/snapshot-team/snapshot/blob/master/API
// /mr/package/<package>/
type Package struct {
Comment string `json:"_comment"`
Package string `json:"package"`
Result []struct {
Version string `json:"version"`
} `json:"result"`
}
// /mr/package/<package>/<version>/binpackages
type Binpackages struct {
Comment string `json:"_comment"`
Package string `json:"package"`
Result []struct {
Name string `json:"name"`
Version string `json:"version"`
} `json:"result"`
Version string `json:"version"`
}
// /mr/binary/<binary>/
type Binary struct {
Comment string `json:"_comment"`
Binary string `json:"binary"`
Result []struct {
BinaryVersion string `json:"binary_version"`
Name string `json:"name"`
Source string `json:"source"`
Version string `json:"version"`
} `json:"result"`
}
// /mr/binary/<binpkg>/<binversion>/binfiles
type Binfiles struct {
Comment string `json:"_comment"`
Binary string `json:"binary"`
BinaryVersion string `json:"binary_version"`
Result []struct {
Architecture string `json:"architecture"`
Hash string `json:"hash"`
} `json:"result"`
}
type Fileinfo struct {
ArchiveName string `json:"archive_name"`
FirstSeen string `json:"first_seen"`
Name string `json:"name"`
Path string `json:"path"`
Size int `json:"size"`
}
// /mr/file/<hash>/info
type Info struct {
Comment string `json:"_comment"`
Hash string `json:"hash"`
Result []Fileinfo `json:"result"`
}
2023-05-11 16:07:15 +00:00
func getJson(query string, target interface{}) (err error) {
flog := log.With().Str("url", query).Logger()
var resp *http.Response
for i := Retries; i > 0; i-- {
flog.Trace().Msg("wait")
Limiter.Wait(context.Background())
flog.Trace().Msg("start")
resp, err = http.Get(query)
if err != nil {
flog.Error().Err(err).Msg("")
return
}
defer resp.Body.Close()
flog.Debug().Msgf("%s", resp.Status)
if resp.StatusCode < 500 {
break
}
flog.Debug().Msgf("retry (%d left)", i)
2023-05-11 10:21:21 +00:00
}
2023-05-11 12:54:54 +00:00
if resp.StatusCode >= 400 {
2023-05-11 16:07:15 +00:00
err = fmt.Errorf("%d (%s)", resp.StatusCode, query)
2023-05-11 12:54:54 +00:00
}
2023-05-11 10:21:21 +00:00
return json.NewDecoder(resp.Body).Decode(target)
}
func GetPackage(name string) (pkg Package, err error) {
query := fmt.Sprintf("%s/package/%s/", apiURL,
url.QueryEscape(name),
)
err = getJson(query, &pkg)
return
}
func GetBinpackages(name, version string) (binpkgs Binpackages, err error) {
query := fmt.Sprintf("%s/package/%s/%s/binpackages", apiURL,
url.QueryEscape(name),
url.QueryEscape(version),
)
err = getJson(query, &binpkgs)
return
}
func GetBinary(pkg string) (binary Binary, err error) {
query := fmt.Sprintf("%s/binary/%s/", apiURL,
url.QueryEscape(pkg),
)
err = getJson(query, &binary)
return
}
func GetBinfiles(binpkg, binversion string) (binfiles Binfiles, err error) {
query := fmt.Sprintf("%s/binary/%s/%s/binfiles", apiURL,
url.QueryEscape(binpkg),
url.QueryEscape(binversion),
)
err = getJson(query, &binfiles)
return
}
func GetInfo(hash string) (info Info, err error) {
query := fmt.Sprintf("%s/file/%s/info", apiURL,
url.QueryEscape(hash),
)
2023-05-11 11:54:35 +00:00
2023-05-11 10:21:21 +00:00
err = getJson(query, &info)
2023-05-11 11:54:35 +00:00
if err != nil {
return
}
if len(info.Result) != 1 {
err = errors.New("API mismatch")
}
2023-05-11 10:21:21 +00:00
return
}