151 lines
5.5 KiB
Go
151 lines
5.5 KiB
Go
package meshdeliverycheckerclient
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
checker "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdeliverychecker"
|
|
"git.novox.be/novox/mesh-sdk/go/keys"
|
|
)
|
|
|
|
// The codecs of the three states the checker writes and others read (the view and the gate read verdicts, the indexer reads
|
|
// previews, the checker and the tools read kept verdicts): a value is written at the version of the kept values after its rules
|
|
// (CheckVerdict, CheckKept, CheckPreview) and read back through the same rules. The checker's owed state is read by no other
|
|
// part and keeps its own codec.
|
|
|
|
// EncodeVerdict is v as JSON at the kept values' version, refused by CheckVerdict's rules.
|
|
func EncodeVerdict(v checker.VerdictsByGroupHeadsValue) ([]byte, error) {
|
|
if err := CheckVerdict(v); err != nil {
|
|
return nil, err
|
|
}
|
|
v.V = keys.Version
|
|
return json.Marshal(v)
|
|
}
|
|
|
|
// DecodeVerdict reads a `verdicts` value; it refuses an unknown version (keys.ErrUnknownVersion) and what EncodeVerdict refuses.
|
|
func DecodeVerdict(data []byte) (checker.VerdictsByGroupHeadsValue, error) {
|
|
var v checker.VerdictsByGroupHeadsValue
|
|
if err := decode(data, &v); err != nil {
|
|
return v, err
|
|
}
|
|
if err := CheckVerdict(v); err != nil {
|
|
return checker.VerdictsByGroupHeadsValue{}, err
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
// EncodeKept is k as JSON at the kept values' version, refused by CheckKept's rules.
|
|
func EncodeKept(k checker.KeptByLevelDigestValue) ([]byte, error) {
|
|
if err := CheckKept(k); err != nil {
|
|
return nil, err
|
|
}
|
|
k.V = keys.Version
|
|
return json.Marshal(k)
|
|
}
|
|
|
|
// DecodeKept reads a `kept` value; it refuses an unknown version and what EncodeKept refuses.
|
|
func DecodeKept(data []byte) (checker.KeptByLevelDigestValue, error) {
|
|
var k checker.KeptByLevelDigestValue
|
|
if err := decode(data, &k); err != nil {
|
|
return k, err
|
|
}
|
|
if err := CheckKept(k); err != nil {
|
|
return checker.KeptByLevelDigestValue{}, err
|
|
}
|
|
return k, nil
|
|
}
|
|
|
|
// EncodePreview is p as JSON at the kept values' version, refused by CheckPreview's rules.
|
|
func EncodePreview(p checker.PreviewsByRepositoryHeadTrunkValue) ([]byte, error) {
|
|
if err := CheckPreview(p); err != nil {
|
|
return nil, err
|
|
}
|
|
p.V = keys.Version
|
|
return json.Marshal(p)
|
|
}
|
|
|
|
// DecodePreview reads a `previews` value; it refuses an unknown version and what EncodePreview refuses.
|
|
func DecodePreview(data []byte) (checker.PreviewsByRepositoryHeadTrunkValue, error) {
|
|
var p checker.PreviewsByRepositoryHeadTrunkValue
|
|
if err := decode(data, &p); err != nil {
|
|
return p, err
|
|
}
|
|
if err := CheckPreview(p); err != nil {
|
|
return checker.PreviewsByRepositoryHeadTrunkValue{}, err
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
func decode(data []byte, into any) error {
|
|
if err := keys.CheckVersion(data); err != nil {
|
|
return err
|
|
}
|
|
if err := json.Unmarshal(data, into); err != nil {
|
|
return fmt.Errorf("meshdeliverycheckerclient: value does not fit its shape: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// KeptKey is the key, in the state kept, of a kept verdict: `<level>.<digest>`, the level unit or integration and the digest,
|
|
// lowercase hex, of everything that package's tests read at that level as the language's build module names it.
|
|
func KeptKey(level, digest string) (string, error) {
|
|
if err := checkLevel(level); err != nil {
|
|
return "", err
|
|
}
|
|
if digest == "" || strings.Trim(digest, "0123456789abcdef") != "" {
|
|
return "", fmt.Errorf("meshdeliverycheckerclient: %q is not a digest, lowercase hex", digest)
|
|
}
|
|
return checker.KeptByLevelDigestKey(level, digest), nil
|
|
}
|
|
|
|
// ParseKeptKey is the inverse of KeptKey.
|
|
func ParseKeptKey(key string) (level, digest string, err error) {
|
|
level, digest, ok := checker.ParseKeptByLevelDigestKey(key)
|
|
if !ok {
|
|
return "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a kept key, <level>.<digest>", key)
|
|
}
|
|
if _, err = KeptKey(level, digest); err != nil {
|
|
return "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a kept key: %w", key, err)
|
|
}
|
|
return level, digest, nil
|
|
}
|
|
|
|
// PreviewKey is the key, in the state previews, of a head merged onto a trunk commit: `<repository>.<head>.<trunk>`, the
|
|
// repository's owner and name each escaped (keys.EscapeName).
|
|
func PreviewKey(repository, head, trunk string) (string, error) {
|
|
if err := CheckRepository(repository); err != nil {
|
|
return "", err
|
|
}
|
|
if err := keys.CheckName("head", head); err != nil {
|
|
return "", err
|
|
}
|
|
if err := keys.CheckName("trunk commit", trunk); err != nil {
|
|
return "", err
|
|
}
|
|
owner, name, _ := strings.Cut(repository, "/")
|
|
return checker.PreviewsByRepositoryHeadTrunkKey(keys.EscapeName(owner)+"/"+keys.EscapeName(name), head, trunk), nil
|
|
}
|
|
|
|
// ParsePreviewKey is the inverse of PreviewKey.
|
|
func ParsePreviewKey(key string) (repository, head, trunk string, err error) {
|
|
repo, head, trunk, ok := checker.ParsePreviewsByRepositoryHeadTrunkKey(key)
|
|
if !ok || strings.Contains(trunk, ".") {
|
|
return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key, <repository>.<head>.<trunk>", key)
|
|
}
|
|
owner, name, found := strings.Cut(repo, "/")
|
|
if !found {
|
|
return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key: the repository has no slash", key)
|
|
}
|
|
owner, err1 := keys.UnescapeName(owner)
|
|
name, err2 := keys.UnescapeName(name)
|
|
if err1 != nil || err2 != nil {
|
|
return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key: the repository does not unescape", key)
|
|
}
|
|
repository = owner + "/" + name
|
|
if _, err := PreviewKey(repository, head, trunk); err != nil {
|
|
return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key: %w", key, err)
|
|
}
|
|
return repository, head, trunk, nil
|
|
}
|