Files
mesh-delivery/modules/mesh-delivery-builder/internal/versions/entrynames.go
T
jschoubben 71a35a6376 MV1: move contracts and sdk under modules/, importers follow
The delivery repository's contracts and SDK live under modules/ as
mesh-delivery-contracts and mesh-delivery-sdk, their Go module paths
renamed to match the folders (the TypeScript names already did), and
every importer in mesh-delivery, mesh-catalog, mesh-host, mesh-tools
and mesh-sdk follows in the same group: a design as it should be, one
path per module, checked by the group's check building every importer.

Builds: design 47 G §427, §88

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:09:56 +01:00

155 lines
5.1 KiB
Go

package versions
import (
"context"
"encoding/json"
"slices"
"sort"
"strings"
"sync"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/clients/meshcatalogclient"
"git.novox.be/novox/mesh-delivery/modules/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
}
}