package main // The seats' contracts (mesh-contracts, generated from the seat definitions; ADR 0620): every verb's input and answer, // and every event's body, as the two seats distribution holds define them. The verbs common to both seats have one // shape in every registry seat, so containerimageregistry's types serve oci-artifact-registry's too. The holder's own // types stay inside; what crosses the bus is the contract's. import ( "encoding/base64" "fmt" "time" reg "git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry" "distribution/internal/holder" ) func publishOf(in reg.PublishInput) holder.PublishRequest { r := holder.PublishRequest{Transfer: in.Transfer, Name: in.Name, Version: in.Version, Tag: in.Tag, Kind: in.Kind, Fingerprint: in.Fingerprint, Commit: in.Commit, Digest: in.Digest} for _, p := range in.Parts { r.Parts = append(r.Parts, holder.Part{Digest: p.Digest, Size: p.Size}) } return r } func publishAnswer(a holder.PublishAnswer) reg.PublishAnswer { return reg.PublishAnswer{Transfer: a.Transfer, Lacks: a.Missing, Held: a.Ended && len(a.Missing) == 0} } func partOf(in reg.PublishPartInput) (holder.PartRequest, error) { data, err := base64.StdEncoding.DecodeString(in.Data) if err != nil { return holder.PartRequest{}, fmt.Errorf("publish-part: data is not base64: %w", err) } return holder.PartRequest{Transfer: in.Transfer, Digest: in.Part, Sequence: int(in.Sequence), Last: in.Last, Data: data}, nil } func partAnswer(in reg.PublishPartInput, a holder.PublishAnswer) reg.PublishPartAnswer { return reg.PublishPartAnswer{Transfer: in.Transfer, Part: in.Part, Received: in.Sequence + 1, Complete: a.Ended} } // versionsAnswer is `versions`: each version with the digest the store holds under it. func versionsAnswer(v *holder.Verbs, kind string, a holder.VersionsAnswer) reg.VersionsAnswer { out := reg.VersionsAnswer{Name: a.Name, Versions: []reg.Artifact{}} for _, ver := range a.Versions { d, _ := v.Catalog.Digest(a.Name, ver) out.Versions = append(out.Versions, reg.Artifact{Name: a.Name, Version: ver, Digest: d, Kind: kind}) } return out } func tagsAnswer(v *holder.Verbs, a holder.VersionsAnswer) reg.TagsAnswer { out := reg.TagsAnswer{Name: a.Name, Tags: []reg.TagsAnswerTagsItem{}} for _, t := range a.Versions { d, _ := v.Catalog.Digest(a.Name, t) out.Tags = append(out.Tags, reg.TagsAnswerTagsItem{Tag: t, Digest: d}) } return out } // eventBody is an event's body as the seat's contract defines it: an Outcome for published, refused, removed and kept, a // Hold for held and released. func eventBody(event string, e holder.Event) any { switch event { case holder.EventHeld, holder.EventReleased: return reg.Hold{Name: e.Name, Digest: e.Digest, Holder: e.Holder, By: e.By, Reason: e.Reason, At: time.Now().UTC().Format(time.RFC3339)} } return reg.Outcome{Name: e.Name, Version: e.Version, Kind: e.Kind, Tag: e.Tag, Digest: e.Digest, Fingerprint: e.Fingerprint, Commit: e.Commit, Holder: e.Holder, Transfer: e.Transfer, Reference: e.Reference, Reason: e.Reason, Tags: e.Tags} }