CT10: a branch with no revision yet is a ready, empty catalog view
Builds: design 47 G §479, §495 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -3,9 +3,11 @@ package meshcatalogclient
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -174,6 +176,10 @@ func (c *Catalog) ask(_ context.Context, after string) (views.Answer, error) {
|
||||
}
|
||||
c.mu.Unlock()
|
||||
a, err := askRevision(c.call, in)
|
||||
if errors.Is(err, errNoneYet) {
|
||||
// A branch with no revision yet is ready and empty, and nothing waits for it (§479, §495).
|
||||
return views.Answer{V: 1, Owner: seat.Seat, State: c.Follower.State, Created: catalogCreated, Values: map[string]json.RawMessage{}, At: time.Now()}, nil
|
||||
}
|
||||
if err != nil {
|
||||
return views.Answer{}, err
|
||||
}
|
||||
@@ -210,13 +216,22 @@ func (c *Catalog) ask(_ context.Context, after string) (views.Answer, error) {
|
||||
return views.Answer{V: 1, Owner: seat.Seat, State: c.Follower.State, Revision: uint64(rev), Created: catalogCreated, Values: values, Next: a.Next, At: time.Now()}, nil
|
||||
}
|
||||
|
||||
// errNoneYet is the seat's answer `none yet`: the branch has no revision yet.
|
||||
var errNoneYet = errors.New("none yet")
|
||||
|
||||
func askRevision(call Call, in seat.RevisionInput) (seat.RevisionAnswer, error) {
|
||||
raw, err := call(RevisionVerb, in)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), views.NoneYet) {
|
||||
return seat.RevisionAnswer{}, errNoneYet
|
||||
}
|
||||
return seat.RevisionAnswer{}, err
|
||||
}
|
||||
answer, said, ok := buscalls.Unwrap(raw)
|
||||
if !ok {
|
||||
if strings.Contains(said, views.NoneYet) {
|
||||
return seat.RevisionAnswer{}, errNoneYet
|
||||
}
|
||||
return seat.RevisionAnswer{}, fmt.Errorf("%s answered: %s", RevisionVerb, said)
|
||||
}
|
||||
var a seat.RevisionAnswer
|
||||
|
||||
@@ -27,6 +27,9 @@ func (f *fakeRevisions) call(key string, body any) (json.RawMessage, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
rev, ok := f.newest[in.Branch]
|
||||
if ok && rev == 0 {
|
||||
return nil, fmt.Errorf("revision of %s: none yet", in.Branch)
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("asked for the branch %q", in.Branch)
|
||||
}
|
||||
@@ -136,6 +139,20 @@ func TestCatalogIsAViewPerWatchedBranch(t *testing.T) {
|
||||
t.Errorf("the gap was not said in the log: %q", logged)
|
||||
}
|
||||
|
||||
// A branch with no revision yet is ready and empty, and nothing waits for it.
|
||||
f.set("new", 0)
|
||||
none, err := NewCatalog(f.call, "new")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := none.Start(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
<-none.Ready()
|
||||
if _, ok := none.View(); ok || none.Follower.Status().WaitsFor != "" {
|
||||
t.Errorf("a branch with no revision yet holds a view or waits: %+v", none.Follower.Status())
|
||||
}
|
||||
|
||||
for _, data := range []string{`{}`, `not json`} {
|
||||
if err := main.Hear(ctx, []byte(data)); err == nil {
|
||||
t.Errorf("Hear(%s) took it", data)
|
||||
|
||||
Reference in New Issue
Block a user