messageVia, stepsVia, sourceVia and versionsVia go through CallKeptWhileOpen: open while the commit's take-in is pending, the candidate is held, the branch is watched, the module is in the newest view. A call that ends with its ask closed is index.ErrAskClosed, not an unanswered call. Builds: design 47 G §351, §367, §460, §531; A-190 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
105 lines
3.7 KiB
Go
105 lines
3.7 KiB
Go
package index
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"slices"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog"
|
|
"git.novox.be/novox/mesh-sdk/go/keys"
|
|
)
|
|
|
|
// ErrAskClosed is what a kept call answers when its ask was closed while it was made again (design 47 G §351, §460, A-190):
|
|
// what the ask served no longer stands, so the call stopped and is not said unanswered.
|
|
var ErrAskClosed = errors.New("the ask is closed: what it served no longer stands")
|
|
|
|
// takingIn marks a context as the take-in of one commit's merged message, which is pending while that context lives.
|
|
type takingIn struct{ repository, merge string }
|
|
|
|
type takingInKey struct{}
|
|
|
|
// forTakeIn is ctx marked as the take-in of the merged message of repository's commit merge.
|
|
func forTakeIn(ctx context.Context, repository, merge string) context.Context {
|
|
return context.WithValue(ctx, takingInKey{}, takingIn{repository, merge})
|
|
}
|
|
|
|
// TakeInPending says the take-in of the commit merge of repository is still pending (A-190, for the forge bridge's
|
|
// merged_message): its take-in is the one ctx is made for, or a pending entry names it.
|
|
func (ix *Indexer) TakeInPending(ctx context.Context, repository, merge string) (bool, error) {
|
|
if ctx.Err() != nil {
|
|
return false, nil
|
|
}
|
|
if t, ok := ctx.Value(takingInKey{}).(takingIn); ok && t.repository == repository && t.merge == merge {
|
|
return true, nil
|
|
}
|
|
if ix.Pending == nil {
|
|
return false, nil
|
|
}
|
|
entries, err := ReadPending(ctx, ix.Pending, ix.logf)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return slices.ContainsFunc(entries, func(e PendingEntry) bool {
|
|
return e.Forge.Merge == merge && e.Forge.Repository == repository
|
|
}), nil
|
|
}
|
|
|
|
// SeedEntryHeld says the newest trunk revision still holds the entry of module at the fingerprint fp, the candidate the
|
|
// seed asks steps for (A-190).
|
|
func (ix *Indexer) SeedEntryHeld(ctx context.Context, module, fp string) (bool, error) {
|
|
if ctx.Err() != nil || ix.Revisions == nil {
|
|
return false, ctx.Err()
|
|
}
|
|
rev, found, err := newestTrunk(ctx, ix.Revisions)
|
|
if err != nil || !found {
|
|
return false, err
|
|
}
|
|
_, entries, err := ReadRevision(ctx, ix.Revisions, fmt.Sprintf("trunk.%d", rev.Revision))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return slices.ContainsFunc(entries, func(e meshcatalog.CatalogEntry) bool { return e.Module == module && e.Fp == fp }), nil
|
|
}
|
|
|
|
// ModuleInNewestView says module is among the entries of the newest trunk revision, the view the versions are filled for (A-190).
|
|
func (ix *Indexer) ModuleInNewestView(ctx context.Context, module string) (bool, error) {
|
|
if ctx.Err() != nil || ix.Revisions == nil {
|
|
return false, ctx.Err()
|
|
}
|
|
rev, found, err := newestTrunk(ctx, ix.Revisions)
|
|
if err != nil || !found {
|
|
return false, err
|
|
}
|
|
_, entries, err := ReadRevision(ctx, ix.Revisions, fmt.Sprintf("trunk.%d", rev.Revision))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return slices.ContainsFunc(entries, func(e meshcatalog.CatalogEntry) bool { return e.Module == module }), nil
|
|
}
|
|
|
|
// BranchWatched says branch (as the source's key names it, escaped; empty asks the list of every branch) is watched: the
|
|
// trunk always, another branch while a registration names it (A-190). With no registry, every branch is.
|
|
func (ix *Indexer) BranchWatched(ctx context.Context, branch string) (bool, error) {
|
|
if ctx.Err() != nil {
|
|
return false, nil
|
|
}
|
|
if isTrunkBranch(branch) || ix.Registry == nil || ix.Registry.Registrations == nil {
|
|
return true, nil
|
|
}
|
|
name, err := keys.UnescapeName(branch)
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
regs, err := ix.Registry.RegistrationsAnswer(ctx, meshcatalog.RegistrationsInput{})
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
for _, r := range regs.Registrations {
|
|
if slices.Contains(r.Branches, name) {
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|