B7-1: recovery-merged names the branch the merge moved and the module of the record's catalog half
Builds: design 47 G §81, §522, A-161, A-172 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -715,6 +715,33 @@ func TestTheRecordsToolsReadThemAndEndOneByHand(t *testing.T) {
|
||||
t.Fatal("a recovery with no why was taken")
|
||||
}
|
||||
})
|
||||
t.Run("recovery-merged names the branch the merge moved and the module its record's catalog half names (design 47 G A-161, A-172)", func(t *testing.T) {
|
||||
var body meshdelivery.RecoveryMergedEvent
|
||||
rs := &Records{Ledger: newLedgerFake(t), Now: func() time.Time { return at },
|
||||
Say: func(subject string, b any, id string) error {
|
||||
if subject == meshdelivery.SubjectRecoveryMerged {
|
||||
body = b.(meshdelivery.RecoveryMergedEvent)
|
||||
}
|
||||
return nil
|
||||
}}
|
||||
commit := strings.Repeat("2", 40)
|
||||
r, _, err := rs.Open(recordMilestone("feat/x", 4), map[string]string{"novox/app@222222222222": commit}, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := rs.AddEntry(r, RecordEntry{Module: "mesh-y", Fingerprint: "src2:f2"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := rs.AddEntry(r, RecordEntry{Module: "mesh-x", Fingerprint: "src2:f1", Node: "ace"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := rs.Recovery("novox/app", commit, "why", "jochen"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if body.Branch != "feat/x" || body.Module != "mesh-y" {
|
||||
t.Fatalf("said %+v", body)
|
||||
}
|
||||
})
|
||||
t.Run("a removal asks the runtime's ledger removal of the instance, and one said twice changes nothing", func(t *testing.T) {
|
||||
was := ledgerCall
|
||||
t.Cleanup(func() { ledgerCall = was })
|
||||
|
||||
@@ -3,9 +3,11 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshdelivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/keys"
|
||||
)
|
||||
|
||||
// Recovery names a merge a recovery (design 47 G §81, A-23): the delivery record that holds the commit is marked through its
|
||||
@@ -36,7 +38,8 @@ func (rs *Records) Recovery(repository, commit, why, by string) (meshdelivery.Re
|
||||
r.Recovery, r.Sequence = &want, seq
|
||||
now := rs.now()
|
||||
if err := rs.say(meshdelivery.SubjectRecoveryMerged, meshdelivery.RecoveryMergedEvent{At: &now, By: by, Commit: head,
|
||||
Repository: repository, V: 1, Why: why}, "recovery-merged."+r.Instance+"."+head); err != nil {
|
||||
Repository: repository, V: 1, Why: why,
|
||||
Branch: branchOf(r), Module: moduleOf(r)}, "recovery-merged."+r.Instance+"."+head); err != nil {
|
||||
return meshdelivery.RecoveryAnswer{}, fmt.Errorf("the record %s is marked but recovery-merged is not said: %w", r.Instance, err)
|
||||
}
|
||||
return meshdelivery.RecoveryAnswer{By: by, Commit: head, Recovery: true, Repository: repository}, nil
|
||||
@@ -44,3 +47,32 @@ func (rs *Records) Recovery(repository, commit, why, by string) (meshdelivery.Re
|
||||
}
|
||||
return meshdelivery.RecoveryAnswer{}, fmt.Errorf("no delivery record holds %s at %s: the merge is taken in first", repository, commit)
|
||||
}
|
||||
|
||||
// branchOf is the watched branch a record's merge moved: the record of a taken source revision is keyed `<branch>.<source>`
|
||||
// (recordMilestone); a milestone of another form names no branch.
|
||||
func branchOf(r *Record) string {
|
||||
part, _, ok := strings.Cut(r.Milestone, ".")
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
branch, err := keys.UnescapeName(part)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return branch
|
||||
}
|
||||
|
||||
// moduleOf is the module the merge changed, from the entries of the record's catalog half (those that name no node), the
|
||||
// modules in order and comma-separated when the merge changed several.
|
||||
func moduleOf(r *Record) string {
|
||||
seen := map[string]bool{}
|
||||
var modules []string
|
||||
for _, e := range r.Entries {
|
||||
if e.Node == "" && e.Module != "" && !seen[e.Module] {
|
||||
seen[e.Module] = true
|
||||
modules = append(modules, e.Module)
|
||||
}
|
||||
}
|
||||
sort.Strings(modules)
|
||||
return strings.Join(modules, ", ")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user