The seat whose definition delivers a requirement, among those the entry's
catalog graph revision names, is resolved first: its holder from the
placements' holds, as seat-holders keeps them; a delivering seat no
placement holds holds the entry, naming the seat. A hold now names the
requirement, the seat and each candidate {node, module}; an optional
requirement nothing provides is left absent. The catalog entry gains
contributes, filled by the indexer, and requires names every requirement
as Wants lists them, optional ones included (the module graph and the
assigner's halves leave the optional ones out by the entry's manifest).
A contributed requirement gives a contribution edge to the same provider.
Builds: design 47 G §708, §709, §357; lead answers A-167, A-229
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
43 lines
1.6 KiB
Go
43 lines
1.6 KiB
Go
package graph
|
|
|
|
import (
|
|
"encoding/json"
|
|
"maps"
|
|
"slices"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog"
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// NodeOf is the node of the module graph a catalog graph entry carries, as the indexer took it in (design 47, *Two
|
|
// graphs*): the catalog half's holder reads its graph back from its newest trunk revision, and every part that reads the
|
|
// catalog half reads the module graph from its entries, never from the holder's state.
|
|
func NodeOf(e meshcatalog.CatalogEntry) Node {
|
|
n := Node{V: Version, FP: e.Fp, None: e.None, Repository: e.Repository, Path: e.Path, Bases: e.Bases,
|
|
Provides: e.Provides, Requires: required(e), Awaits: e.Awaits, Invokes: e.Invokes, Serves: e.Serves, LeftOut: e.LeftOut}
|
|
if len(e.Packages) > 0 {
|
|
n.Packages = slices.Sorted(maps.Keys(e.Packages))
|
|
}
|
|
for language, t := range e.Toolchains {
|
|
if n.Toolchains == nil {
|
|
n.Toolchains = map[string]Toolchain{}
|
|
}
|
|
n.Toolchains[language] = Toolchain{Module: t.Module, Version: t.Version, Recipe: t.Recipe}
|
|
}
|
|
return n
|
|
}
|
|
|
|
// required are the entry's requires a node means, those it requires not optionally: an entry's requires name the optional
|
|
// ones too, told apart by the entry's manifest (design 47 G §709, A-229).
|
|
func required(e meshcatalog.CatalogEntry) []string {
|
|
if len(e.Manifest) == 0 || len(e.Requires) == 0 {
|
|
return e.Requires
|
|
}
|
|
var m catalogue.Manifest
|
|
raw, err := json.Marshal(e.Manifest)
|
|
if err != nil || json.Unmarshal(raw, &m) != nil {
|
|
return e.Requires
|
|
}
|
|
return slices.DeleteFunc(slices.Clone(e.Requires), m.IsOptional)
|
|
}
|