103 lines
3.2 KiB
Go
103 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
sdk "git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// Whether a merge is on the machines (novox/hq ADR 0556 clause 4). The gate records only the merge (ADR 0539 §17, ADR 0429
|
|
// §1): it reads the delivery view's reach of each repository, which names the repository's reached head (the newest merge every
|
|
// node runs a build containing), and derives when asked, for a merged delivery, whether its merge is at or before that head.
|
|
// The order of two merges into one trunk is the gate's own: the moment each was merged, the trunk being a line of merges. A
|
|
// reached head the gate holds no merge of is said, never asked of the forge.
|
|
|
|
// reachState is the delivery view's state the gate reads.
|
|
const reachState = sdk.ViewModule + ".reach"
|
|
|
|
// ReachChanged takes one change of the view's reach.
|
|
func (h *Holder) ReachChanged(key string, value []byte, deleted bool) {
|
|
h.mu.Lock()
|
|
defer h.mu.Unlock()
|
|
if deleted {
|
|
delete(h.reach, key)
|
|
return
|
|
}
|
|
r, err := sdk.DecodeReach(value)
|
|
if err != nil {
|
|
h.Logf("[mesh-delivery] the view's reach %s is not readable, so its merges read as not known: %v", key, err)
|
|
delete(h.reach, key)
|
|
return
|
|
}
|
|
h.reach[key] = r
|
|
}
|
|
|
|
// The words a merged delivery's machines are said in.
|
|
const (
|
|
onMachines = "on the machines"
|
|
notYetOn = "not yet on the machines: "
|
|
notKnownWhere = "not known: "
|
|
)
|
|
|
|
// machines says whether a merged delivery's merge is on the machines, derived from the view's reach; empty for a delivery
|
|
// that is not merged. Under the lock.
|
|
func (h *Holder) machines(d *Delivery) string {
|
|
if d.State != Merged || d.MergedAs == "" {
|
|
return ""
|
|
}
|
|
key, err := sdk.RepositoryKey(d.Repository)
|
|
if err != nil {
|
|
return notKnownWhere + err.Error()
|
|
}
|
|
r, ok := h.reach[key]
|
|
switch {
|
|
case !ok:
|
|
return notKnownWhere + "the delivery view says no reach of " + d.Repository
|
|
}
|
|
// A merge that changed a module a node wants and runs nothing countable of is not yet there, whatever the reached head
|
|
// (the module holds no head back, ADR 0556 clause 2).
|
|
for _, mr := range r.Modules {
|
|
if mr.Nodes == 0 || mr.Floor != "" {
|
|
continue
|
|
}
|
|
for _, c := range mr.Changes {
|
|
if sameCommit(d.MergedAs, c.Commit) {
|
|
return notYetOn + mr.Waiting
|
|
}
|
|
}
|
|
}
|
|
switch {
|
|
case r.Reached == "":
|
|
return notYetOn + holdsSaid(r)
|
|
case sameCommit(d.MergedAs, r.Reached):
|
|
return onMachines
|
|
}
|
|
head := h.mergeOf(d.Repository, r.Reached)
|
|
switch {
|
|
case head == nil:
|
|
return notKnownWhere + fmt.Sprintf("the reached head %s of %s is no merge this gate holds", shortOf(r.Reached, 12), d.Repository)
|
|
case !d.MergedAt.After(head.MergedAt):
|
|
return onMachines
|
|
}
|
|
return notYetOn + holdsSaid(r)
|
|
}
|
|
|
|
// holdsSaid is what holds a repository's next head, in words.
|
|
func holdsSaid(r sdk.Reach) string {
|
|
if len(r.Holds) == 0 {
|
|
return "the delivery view names nothing that holds it yet"
|
|
}
|
|
return strings.Join(r.Holds, "; ")
|
|
}
|
|
|
|
// mergeOf is the delivery of a repository that merged as the commit; nil when none does. Under the lock.
|
|
func (h *Holder) mergeOf(repository, commit string) *Delivery {
|
|
for _, d := range h.deliveries {
|
|
if d.MergedAs != "" && strings.EqualFold(d.Repository, repository) && sameCommit(d.MergedAs, commit) {
|
|
return d
|
|
}
|
|
}
|
|
return nil
|
|
}
|