Files
mesh-delivery/modules/mesh-delivery-builder/internal/versions/entrynames.go
T
jschoubben 1eb481ccc8 Builder: the manifest names no other module, the floor reads the seat git and the catalog half
The floor's tags are the seat git's verb tags and its requirements what the catalog half's entries
name for the package (indexer_requirements and the forge bridge's bridge_tags go from code and
manifest); a catalog revision the builder hears wakes a silent floor (the forge stream's consume
and its wake go). The guard test says A-107 relaxes ADR 0437 section 8 for a seat's verbs and
accepted kinds. The integration bed creates the state bounds the step bounds are kept in.
The assignments view's seat form (A-119 (3)) is not built here.

Builds: design 47 G §7, A-82, A-107, A-119
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 01:18:40 +01:00

155 lines
5.1 KiB
Go

package versions
import (
"context"
"encoding/json"
"slices"
"sort"
"strings"
"sync"
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// Entries are the catalog graph entries of the halves the builder follows, one per module and watched branch (design 47 G §348,
// §614): where a package's name in its ecosystem is read from, each artifact's `package` (§676), never the indexer's state.
type Entries func() []meshcatalog.CatalogEntry
// artifactOf is the artifact name of an artifact reference `<module>:<artifact>` of module.
func artifactOf(module, ref string) (string, bool) {
m, a, ok := strings.Cut(ref, ":")
return a, ok && m == module && a != ""
}
// NamesFrom answers a package's name in its ecosystem from the entries (design 47 G §348): the name the entry of module gives the
// artifact; known is false when no entry names one for it.
func NamesFrom(all Entries) PackageNames {
return func(_ context.Context, module, artifact string) (string, bool, error) {
for _, e := range all() {
if e.Module != module {
continue
}
for _, a := range e.Artifacts {
if name, ok := artifactOf(module, a.Ref); ok && name == artifact && a.Package != nil && a.Package.Name != "" {
return a.Package.Name, true, nil
}
}
}
return "", false, nil
}
}
// CarriersFrom are the module artifacts a package's name in its ecosystem is the name of, as the entries hold them (design 47 G
// §572, §478), each distinct module and artifact once, sorted; a name no entry carries answers none.
func CarriersFrom(all Entries) func(ctx context.Context, name string) ([]Built, error) {
return func(_ context.Context, name string) ([]Built, error) {
seen := map[Built]bool{}
var out []Built
for _, e := range all() {
for _, a := range e.Artifacts {
artifact, ok := artifactOf(e.Module, a.Ref)
if !ok || a.Package == nil || a.Package.Name != name || seen[Built{e.Module, artifact}] {
continue
}
seen[Built{e.Module, artifact}] = true
out = append(out, Built{e.Module, artifact})
}
}
sort.Slice(out, func(i, j int) bool { return out[i].Module+"/"+out[i].Artifact < out[j].Module+"/"+out[j].Artifact })
return out, nil
}
}
// ModuleFrom is the module and artifact a package's name is built from, from the entries (CarriersFrom); more than one entry
// carrying it is an error naming them.
func ModuleFrom(all Entries) func(ctx context.Context, name string) (module, artifact string, found bool, err error) {
return moduleOfCarriers(CarriersFrom(all))
}
// EntriesOf are the entries of every half the branch follower holds, the followed branches in the order they came.
func EntriesOf(branches *meshcatalogclient.Branches) Entries {
return func() []meshcatalog.CatalogEntry {
var out []meshcatalog.CatalogEntry
for _, br := range branches.Followed() {
if cat, ok := branches.Catalog(br); ok {
if half, ok := cat.View(); ok {
for _, e := range half.Entries {
out = append(out, e)
}
}
}
}
return out
}
}
// HolderOf finds the module that holds a seat: the one whose entry in the first followed branch's half (the trunk's) has a
// manifest that claims it (design 47 G A-82; the seat list answers seat definitions alone, §527). More than one claimant, or
// none, is no holder.
func HolderOf(branches *meshcatalogclient.Branches) func(seat string) (string, bool) {
var mu sync.Mutex
claims := map[string][]string{} // manifest digest -> the seats it claims
claimed := func(e meshcatalog.CatalogEntry) []string {
mu.Lock()
defer mu.Unlock()
if seats, ok := claims[e.ManifestDigest]; ok && e.ManifestDigest != "" {
return seats
}
var seats []string
if raw, err := json.Marshal(e.Manifest); err == nil {
if mf, err := catalogue.Decode(raw); err == nil {
for _, c := range mf.Claims {
seats = append(seats, c.Name)
}
}
}
if e.ManifestDigest != "" {
claims[e.ManifestDigest] = seats
}
return seats
}
return func(seat string) (string, bool) {
followed := branches.Followed()
if len(followed) == 0 {
return "", false
}
cat, ok := branches.Catalog(followed[0])
if !ok {
return "", false
}
half, ok := cat.View()
if !ok {
return "", false
}
var holders []string
for _, e := range half.Entries {
if slices.Contains(claimed(e), seat) {
holders = append(holders, e.Module)
}
}
if len(holders) != 1 {
return "", false
}
return holders[0], true
}
}
// RequirementsFrom answers the versions of a package the entries of every followed half require, each once, in order: what a
// consumer's entry names for it in its packages (design 47 G A-119), the floor's third source.
func RequirementsFrom(all Entries) func(ctx context.Context, name string) ([]string, error) {
return func(_ context.Context, name string) ([]string, error) {
seen := map[string]bool{}
var out []string
for _, e := range all() {
if v := e.Packages[name]; v != "" && !seen[v] {
seen[v] = true
out = append(out, v)
}
}
sort.Strings(out)
return out, nil
}
}