diff --git a/go/delivery/delivery.go b/go/delivery/delivery.go index 769420c..8fccfaa 100644 --- a/go/delivery/delivery.go +++ b/go/delivery/delivery.go @@ -491,7 +491,19 @@ func DecodePulse(data []byte) (Pulse, error) { } // SameHave says whether two haves are the same value, so a writer writes only when they differ. -func SameHave(a, b Have) bool { return a == b } +func SameHave(a, b Have) bool { + ua, ub := a.UserList, b.UserList + a.UserList, b.UserList = nil, nil + if a != b || (ua == nil) != (ub == nil) { + return false + } + if ua == nil { + return true + } + x, y := *ua, *ub + x.At, y.At = time.Time{}, time.Time{} + return x == y && ua.At.Equal(ub.At) +} // SameHaveNode says whether two node facts are the same value, comparing each carried JSON without its spacing. func SameHaveNode(a, b HaveNode) bool { diff --git a/go/delivery/delivery_test.go b/go/delivery/delivery_test.go index 3b1ac09..a0aba8d 100644 --- a/go/delivery/delivery_test.go +++ b/go/delivery/delivery_test.go @@ -294,6 +294,18 @@ func TestSame(t *testing.T) { if SameHave(a, b) { t.Error("different haves same") } + // The user list is compared by what it says, never by where it is held (ADR 0547 ยง8). + at := time.Date(2026, 10, 25, 21, 0, 0, 0, time.UTC) + ua, ub := a, a + ua.UserList = &UserListWritten{Source: "k", Revision: 1, Wanted: "sha256:a", Digest: "sha256:a", Users: 2, At: at} + ub.UserList = &UserListWritten{Source: "k", Revision: 1, Wanted: "sha256:a", Digest: "sha256:a", Users: 2, At: at.In(time.Local)} + if !SameHave(ua, ub) || SameHave(ua, a) { + t.Error("equal user lists differ, or one said and one not are the same") + } + ub.UserList.Revision = 2 + if SameHave(ua, ub) { + t.Error("different user lists same") + } n := HaveNode{V: 1, Busy: json.RawMessage(`true`)} if !SameHaveNode(n, HaveNode{V: 1, Busy: json.RawMessage(`true`)}) || SameHaveNode(n, HaveNode{V: 1}) { t.Error("have node")