detached f2c8f76

refactor(ports): define snapshot repository generations

commit
f2c8f763bef877352e0221dc315347573d582953
author
brice · · 2026-07-21 19:13 UTC
parent
a7d13d1
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +344 -0
M internal/ports/mocks/store_mock.go +266 -0
@@ -523,3 +523,269 @@ func (_c *MockSnapshotStore_Write_Call) RunAndReturn(run func(name string, data
523523 _c.Call.Return(run)
524524 return _c
525525 }
526+
527+// NewMockSnapshotRepository creates a new instance of MockSnapshotRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
528+// The first argument is typically a *testing.T value.
529+func NewMockSnapshotRepository(t interface {
530+ mock.TestingT
531+ Cleanup(func())
532+}) *MockSnapshotRepository {
533+ mock := &MockSnapshotRepository{}
534+ mock.Mock.Test(t)
535+
536+ t.Cleanup(func() { mock.AssertExpectations(t) })
537+
538+ return mock
539+}
540+
541+// MockSnapshotRepository is an autogenerated mock type for the SnapshotRepository type
542+type MockSnapshotRepository struct {
543+ mock.Mock
544+}
545+
546+type MockSnapshotRepository_Expecter struct {
547+ mock *mock.Mock
548+}
549+
550+func (_m *MockSnapshotRepository) EXPECT() *MockSnapshotRepository_Expecter {
551+ return &MockSnapshotRepository_Expecter{mock: &_m.Mock}
552+}
553+
554+// Delete provides a mock function for the type MockSnapshotRepository
555+func (_mock *MockSnapshotRepository) Delete(name string) error {
556+ ret := _mock.Called(name)
557+
558+ if len(ret) == 0 {
559+ panic("no return value specified for Delete")
560+ }
561+
562+ var r0 error
563+ if returnFunc, ok := ret.Get(0).(func(string) error); ok {
564+ r0 = returnFunc(name)
565+ } else {
566+ r0 = ret.Error(0)
567+ }
568+ return r0
569+}
570+
571+// MockSnapshotRepository_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete'
572+type MockSnapshotRepository_Delete_Call struct {
573+ *mock.Call
574+}
575+
576+// Delete is a helper method to define mock.On call
577+// - name string
578+func (_e *MockSnapshotRepository_Expecter) Delete(name any) *MockSnapshotRepository_Delete_Call {
579+ return &MockSnapshotRepository_Delete_Call{Call: _e.mock.On("Delete", name)}
580+}
581+
582+func (_c *MockSnapshotRepository_Delete_Call) Run(run func(name string)) *MockSnapshotRepository_Delete_Call {
583+ _c.Call.Run(func(args mock.Arguments) {
584+ var arg0 string
585+ if args[0] != nil {
586+ arg0 = args[0].(string)
587+ }
588+ run(
589+ arg0,
590+ )
591+ })
592+ return _c
593+}
594+
595+func (_c *MockSnapshotRepository_Delete_Call) Return(err error) *MockSnapshotRepository_Delete_Call {
596+ _c.Call.Return(err)
597+ return _c
598+}
599+
600+func (_c *MockSnapshotRepository_Delete_Call) RunAndReturn(run func(name string) error) *MockSnapshotRepository_Delete_Call {
601+ _c.Call.Return(run)
602+ return _c
603+}
604+
605+// Load provides a mock function for the type MockSnapshotRepository
606+func (_mock *MockSnapshotRepository) Load() ([]ports.SnapshotGeneration, error) {
607+ ret := _mock.Called()
608+
609+ if len(ret) == 0 {
610+ panic("no return value specified for Load")
611+ }
612+
613+ var r0 []ports.SnapshotGeneration
614+ var r1 error
615+ if returnFunc, ok := ret.Get(0).(func() ([]ports.SnapshotGeneration, error)); ok {
616+ return returnFunc()
617+ }
618+ if returnFunc, ok := ret.Get(0).(func() []ports.SnapshotGeneration); ok {
619+ r0 = returnFunc()
620+ } else {
621+ if ret.Get(0) != nil {
622+ r0 = ret.Get(0).([]ports.SnapshotGeneration)
623+ }
624+ }
625+ if returnFunc, ok := ret.Get(1).(func() error); ok {
626+ r1 = returnFunc()
627+ } else {
628+ r1 = ret.Error(1)
629+ }
630+ return r0, r1
631+}
632+
633+// MockSnapshotRepository_Load_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Load'
634+type MockSnapshotRepository_Load_Call struct {
635+ *mock.Call
636+}
637+
638+// Load is a helper method to define mock.On call
639+func (_e *MockSnapshotRepository_Expecter) Load() *MockSnapshotRepository_Load_Call {
640+ return &MockSnapshotRepository_Load_Call{Call: _e.mock.On("Load")}
641+}
642+
643+func (_c *MockSnapshotRepository_Load_Call) Run(run func()) *MockSnapshotRepository_Load_Call {
644+ _c.Call.Run(func(args mock.Arguments) {
645+ run()
646+ })
647+ return _c
648+}
649+
650+func (_c *MockSnapshotRepository_Load_Call) Return(snapshotGenerations []ports.SnapshotGeneration, err error) *MockSnapshotRepository_Load_Call {
651+ _c.Call.Return(snapshotGenerations, err)
652+ return _c
653+}
654+
655+func (_c *MockSnapshotRepository_Load_Call) RunAndReturn(run func() ([]ports.SnapshotGeneration, error)) *MockSnapshotRepository_Load_Call {
656+ _c.Call.Return(run)
657+ return _c
658+}
659+
660+// Publish provides a mock function for the type MockSnapshotRepository
661+func (_mock *MockSnapshotRepository) Publish(snapshotPublication ports.SnapshotPublication) error {
662+ ret := _mock.Called(snapshotPublication)
663+
664+ if len(ret) == 0 {
665+ panic("no return value specified for Publish")
666+ }
667+
668+ var r0 error
669+ if returnFunc, ok := ret.Get(0).(func(ports.SnapshotPublication) error); ok {
670+ r0 = returnFunc(snapshotPublication)
671+ } else {
672+ r0 = ret.Error(0)
673+ }
674+ return r0
675+}
676+
677+// MockSnapshotRepository_Publish_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Publish'
678+type MockSnapshotRepository_Publish_Call struct {
679+ *mock.Call
680+}
681+
682+// Publish is a helper method to define mock.On call
683+// - snapshotPublication ports.SnapshotPublication
684+func (_e *MockSnapshotRepository_Expecter) Publish(snapshotPublication any) *MockSnapshotRepository_Publish_Call {
685+ return &MockSnapshotRepository_Publish_Call{Call: _e.mock.On("Publish", snapshotPublication)}
686+}
687+
688+func (_c *MockSnapshotRepository_Publish_Call) Run(run func(snapshotPublication ports.SnapshotPublication)) *MockSnapshotRepository_Publish_Call {
689+ _c.Call.Run(func(args mock.Arguments) {
690+ var arg0 ports.SnapshotPublication
691+ if args[0] != nil {
692+ arg0 = args[0].(ports.SnapshotPublication)
693+ }
694+ run(
695+ arg0,
696+ )
697+ })
698+ return _c
699+}
700+
701+func (_c *MockSnapshotRepository_Publish_Call) Return(err error) *MockSnapshotRepository_Publish_Call {
702+ _c.Call.Return(err)
703+ return _c
704+}
705+
706+func (_c *MockSnapshotRepository_Publish_Call) RunAndReturn(run func(snapshotPublication ports.SnapshotPublication) error) *MockSnapshotRepository_Publish_Call {
707+ _c.Call.Return(run)
708+ return _c
709+}
710+
711+// NewMockLegacySnapshotSource creates a new instance of MockLegacySnapshotSource. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
712+// The first argument is typically a *testing.T value.
713+func NewMockLegacySnapshotSource(t interface {
714+ mock.TestingT
715+ Cleanup(func())
716+}) *MockLegacySnapshotSource {
717+ mock := &MockLegacySnapshotSource{}
718+ mock.Mock.Test(t)
719+
720+ t.Cleanup(func() { mock.AssertExpectations(t) })
721+
722+ return mock
723+}
724+
725+// MockLegacySnapshotSource is an autogenerated mock type for the LegacySnapshotSource type
726+type MockLegacySnapshotSource struct {
727+ mock.Mock
728+}
729+
730+type MockLegacySnapshotSource_Expecter struct {
731+ mock *mock.Mock
732+}
733+
734+func (_m *MockLegacySnapshotSource) EXPECT() *MockLegacySnapshotSource_Expecter {
735+ return &MockLegacySnapshotSource_Expecter{mock: &_m.Mock}
736+}
737+
738+// LoadLegacySnapshots provides a mock function for the type MockLegacySnapshotSource
739+func (_mock *MockLegacySnapshotSource) LoadLegacySnapshots() ([]ports.LegacySnapshot, error) {
740+ ret := _mock.Called()
741+
742+ if len(ret) == 0 {
743+ panic("no return value specified for LoadLegacySnapshots")
744+ }
745+
746+ var r0 []ports.LegacySnapshot
747+ var r1 error
748+ if returnFunc, ok := ret.Get(0).(func() ([]ports.LegacySnapshot, error)); ok {
749+ return returnFunc()
750+ }
751+ if returnFunc, ok := ret.Get(0).(func() []ports.LegacySnapshot); ok {
752+ r0 = returnFunc()
753+ } else {
754+ if ret.Get(0) != nil {
755+ r0 = ret.Get(0).([]ports.LegacySnapshot)
756+ }
757+ }
758+ if returnFunc, ok := ret.Get(1).(func() error); ok {
759+ r1 = returnFunc()
760+ } else {
761+ r1 = ret.Error(1)
762+ }
763+ return r0, r1
764+}
765+
766+// MockLegacySnapshotSource_LoadLegacySnapshots_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LoadLegacySnapshots'
767+type MockLegacySnapshotSource_LoadLegacySnapshots_Call struct {
768+ *mock.Call
769+}
770+
771+// LoadLegacySnapshots is a helper method to define mock.On call
772+func (_e *MockLegacySnapshotSource_Expecter) LoadLegacySnapshots() *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
773+ return &MockLegacySnapshotSource_LoadLegacySnapshots_Call{Call: _e.mock.On("LoadLegacySnapshots")}
774+}
775+
776+func (_c *MockLegacySnapshotSource_LoadLegacySnapshots_Call) Run(run func()) *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
777+ _c.Call.Run(func(args mock.Arguments) {
778+ run()
779+ })
780+ return _c
781+}
782+
783+func (_c *MockLegacySnapshotSource_LoadLegacySnapshots_Call) Return(legacySnapshots []ports.LegacySnapshot, err error) *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
784+ _c.Call.Return(legacySnapshots, err)
785+ return _c
786+}
787+
788+func (_c *MockLegacySnapshotSource_LoadLegacySnapshots_Call) RunAndReturn(run func() ([]ports.LegacySnapshot, error)) *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
789+ _c.Call.Return(run)
790+ return _c
791+}
@@ -523,3 +523,269 @@ func (_c *MockSnapshotStore_Write_Call) RunAndReturn(run func(name string, data
523 _c.Call.Return(run)523 _c.Call.Return(run)
524 return _c524 return _c
525 }525 }
526+
527+// NewMockSnapshotRepository creates a new instance of MockSnapshotRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
528+// The first argument is typically a *testing.T value.
529+func NewMockSnapshotRepository(t interface {
530+ mock.TestingT
531+ Cleanup(func())
532+}) *MockSnapshotRepository {
533+ mock := &MockSnapshotRepository{}
534+ mock.Mock.Test(t)
535+
536+ t.Cleanup(func() { mock.AssertExpectations(t) })
537+
538+ return mock
539+}
540+
541+// MockSnapshotRepository is an autogenerated mock type for the SnapshotRepository type
542+type MockSnapshotRepository struct {
543+ mock.Mock
544+}
545+
546+type MockSnapshotRepository_Expecter struct {
547+ mock *mock.Mock
548+}
549+
550+func (_m *MockSnapshotRepository) EXPECT() *MockSnapshotRepository_Expecter {
551+ return &MockSnapshotRepository_Expecter{mock: &_m.Mock}
552+}
553+
554+// Delete provides a mock function for the type MockSnapshotRepository
555+func (_mock *MockSnapshotRepository) Delete(name string) error {
556+ ret := _mock.Called(name)
557+
558+ if len(ret) == 0 {
559+ panic("no return value specified for Delete")
560+ }
561+
562+ var r0 error
563+ if returnFunc, ok := ret.Get(0).(func(string) error); ok {
564+ r0 = returnFunc(name)
565+ } else {
566+ r0 = ret.Error(0)
567+ }
568+ return r0
569+}
570+
571+// MockSnapshotRepository_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete'
572+type MockSnapshotRepository_Delete_Call struct {
573+ *mock.Call
574+}
575+
576+// Delete is a helper method to define mock.On call
577+// - name string
578+func (_e *MockSnapshotRepository_Expecter) Delete(name any) *MockSnapshotRepository_Delete_Call {
579+ return &MockSnapshotRepository_Delete_Call{Call: _e.mock.On("Delete", name)}
580+}
581+
582+func (_c *MockSnapshotRepository_Delete_Call) Run(run func(name string)) *MockSnapshotRepository_Delete_Call {
583+ _c.Call.Run(func(args mock.Arguments) {
584+ var arg0 string
585+ if args[0] != nil {
586+ arg0 = args[0].(string)
587+ }
588+ run(
589+ arg0,
590+ )
591+ })
592+ return _c
593+}
594+
595+func (_c *MockSnapshotRepository_Delete_Call) Return(err error) *MockSnapshotRepository_Delete_Call {
596+ _c.Call.Return(err)
597+ return _c
598+}
599+
600+func (_c *MockSnapshotRepository_Delete_Call) RunAndReturn(run func(name string) error) *MockSnapshotRepository_Delete_Call {
601+ _c.Call.Return(run)
602+ return _c
603+}
604+
605+// Load provides a mock function for the type MockSnapshotRepository
606+func (_mock *MockSnapshotRepository) Load() ([]ports.SnapshotGeneration, error) {
607+ ret := _mock.Called()
608+
609+ if len(ret) == 0 {
610+ panic("no return value specified for Load")
611+ }
612+
613+ var r0 []ports.SnapshotGeneration
614+ var r1 error
615+ if returnFunc, ok := ret.Get(0).(func() ([]ports.SnapshotGeneration, error)); ok {
616+ return returnFunc()
617+ }
618+ if returnFunc, ok := ret.Get(0).(func() []ports.SnapshotGeneration); ok {
619+ r0 = returnFunc()
620+ } else {
621+ if ret.Get(0) != nil {
622+ r0 = ret.Get(0).([]ports.SnapshotGeneration)
623+ }
624+ }
625+ if returnFunc, ok := ret.Get(1).(func() error); ok {
626+ r1 = returnFunc()
627+ } else {
628+ r1 = ret.Error(1)
629+ }
630+ return r0, r1
631+}
632+
633+// MockSnapshotRepository_Load_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Load'
634+type MockSnapshotRepository_Load_Call struct {
635+ *mock.Call
636+}
637+
638+// Load is a helper method to define mock.On call
639+func (_e *MockSnapshotRepository_Expecter) Load() *MockSnapshotRepository_Load_Call {
640+ return &MockSnapshotRepository_Load_Call{Call: _e.mock.On("Load")}
641+}
642+
643+func (_c *MockSnapshotRepository_Load_Call) Run(run func()) *MockSnapshotRepository_Load_Call {
644+ _c.Call.Run(func(args mock.Arguments) {
645+ run()
646+ })
647+ return _c
648+}
649+
650+func (_c *MockSnapshotRepository_Load_Call) Return(snapshotGenerations []ports.SnapshotGeneration, err error) *MockSnapshotRepository_Load_Call {
651+ _c.Call.Return(snapshotGenerations, err)
652+ return _c
653+}
654+
655+func (_c *MockSnapshotRepository_Load_Call) RunAndReturn(run func() ([]ports.SnapshotGeneration, error)) *MockSnapshotRepository_Load_Call {
656+ _c.Call.Return(run)
657+ return _c
658+}
659+
660+// Publish provides a mock function for the type MockSnapshotRepository
661+func (_mock *MockSnapshotRepository) Publish(snapshotPublication ports.SnapshotPublication) error {
662+ ret := _mock.Called(snapshotPublication)
663+
664+ if len(ret) == 0 {
665+ panic("no return value specified for Publish")
666+ }
667+
668+ var r0 error
669+ if returnFunc, ok := ret.Get(0).(func(ports.SnapshotPublication) error); ok {
670+ r0 = returnFunc(snapshotPublication)
671+ } else {
672+ r0 = ret.Error(0)
673+ }
674+ return r0
675+}
676+
677+// MockSnapshotRepository_Publish_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Publish'
678+type MockSnapshotRepository_Publish_Call struct {
679+ *mock.Call
680+}
681+
682+// Publish is a helper method to define mock.On call
683+// - snapshotPublication ports.SnapshotPublication
684+func (_e *MockSnapshotRepository_Expecter) Publish(snapshotPublication any) *MockSnapshotRepository_Publish_Call {
685+ return &MockSnapshotRepository_Publish_Call{Call: _e.mock.On("Publish", snapshotPublication)}
686+}
687+
688+func (_c *MockSnapshotRepository_Publish_Call) Run(run func(snapshotPublication ports.SnapshotPublication)) *MockSnapshotRepository_Publish_Call {
689+ _c.Call.Run(func(args mock.Arguments) {
690+ var arg0 ports.SnapshotPublication
691+ if args[0] != nil {
692+ arg0 = args[0].(ports.SnapshotPublication)
693+ }
694+ run(
695+ arg0,
696+ )
697+ })
698+ return _c
699+}
700+
701+func (_c *MockSnapshotRepository_Publish_Call) Return(err error) *MockSnapshotRepository_Publish_Call {
702+ _c.Call.Return(err)
703+ return _c
704+}
705+
706+func (_c *MockSnapshotRepository_Publish_Call) RunAndReturn(run func(snapshotPublication ports.SnapshotPublication) error) *MockSnapshotRepository_Publish_Call {
707+ _c.Call.Return(run)
708+ return _c
709+}
710+
711+// NewMockLegacySnapshotSource creates a new instance of MockLegacySnapshotSource. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
712+// The first argument is typically a *testing.T value.
713+func NewMockLegacySnapshotSource(t interface {
714+ mock.TestingT
715+ Cleanup(func())
716+}) *MockLegacySnapshotSource {
717+ mock := &MockLegacySnapshotSource{}
718+ mock.Mock.Test(t)
719+
720+ t.Cleanup(func() { mock.AssertExpectations(t) })
721+
722+ return mock
723+}
724+
725+// MockLegacySnapshotSource is an autogenerated mock type for the LegacySnapshotSource type
726+type MockLegacySnapshotSource struct {
727+ mock.Mock
728+}
729+
730+type MockLegacySnapshotSource_Expecter struct {
731+ mock *mock.Mock
732+}
733+
734+func (_m *MockLegacySnapshotSource) EXPECT() *MockLegacySnapshotSource_Expecter {
735+ return &MockLegacySnapshotSource_Expecter{mock: &_m.Mock}
736+}
737+
738+// LoadLegacySnapshots provides a mock function for the type MockLegacySnapshotSource
739+func (_mock *MockLegacySnapshotSource) LoadLegacySnapshots() ([]ports.LegacySnapshot, error) {
740+ ret := _mock.Called()
741+
742+ if len(ret) == 0 {
743+ panic("no return value specified for LoadLegacySnapshots")
744+ }
745+
746+ var r0 []ports.LegacySnapshot
747+ var r1 error
748+ if returnFunc, ok := ret.Get(0).(func() ([]ports.LegacySnapshot, error)); ok {
749+ return returnFunc()
750+ }
751+ if returnFunc, ok := ret.Get(0).(func() []ports.LegacySnapshot); ok {
752+ r0 = returnFunc()
753+ } else {
754+ if ret.Get(0) != nil {
755+ r0 = ret.Get(0).([]ports.LegacySnapshot)
756+ }
757+ }
758+ if returnFunc, ok := ret.Get(1).(func() error); ok {
759+ r1 = returnFunc()
760+ } else {
761+ r1 = ret.Error(1)
762+ }
763+ return r0, r1
764+}
765+
766+// MockLegacySnapshotSource_LoadLegacySnapshots_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LoadLegacySnapshots'
767+type MockLegacySnapshotSource_LoadLegacySnapshots_Call struct {
768+ *mock.Call
769+}
770+
771+// LoadLegacySnapshots is a helper method to define mock.On call
772+func (_e *MockLegacySnapshotSource_Expecter) LoadLegacySnapshots() *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
773+ return &MockLegacySnapshotSource_LoadLegacySnapshots_Call{Call: _e.mock.On("LoadLegacySnapshots")}
774+}
775+
776+func (_c *MockLegacySnapshotSource_LoadLegacySnapshots_Call) Run(run func()) *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
777+ _c.Call.Run(func(args mock.Arguments) {
778+ run()
779+ })
780+ return _c
781+}
782+
783+func (_c *MockLegacySnapshotSource_LoadLegacySnapshots_Call) Return(legacySnapshots []ports.LegacySnapshot, err error) *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
784+ _c.Call.Return(legacySnapshots, err)
785+ return _c
786+}
787+
788+func (_c *MockLegacySnapshotSource_LoadLegacySnapshots_Call) RunAndReturn(run func() ([]ports.LegacySnapshot, error)) *MockLegacySnapshotSource_LoadLegacySnapshots_Call {
789+ _c.Call.Return(run)
790+ return _c
791+}
M internal/ports/snapshot_test.go +29 -0
@@ -2,6 +2,35 @@ package ports
22
33 import "testing"
44
5+type snapshotRepositoryContract struct{}
6+
7+func (snapshotRepositoryContract) Publish(SnapshotPublication) error { return nil }
8+func (snapshotRepositoryContract) Load() ([]SnapshotGeneration, error) { return nil, nil }
9+func (snapshotRepositoryContract) Delete(string) error { return nil }
10+
11+type legacySnapshotSourceContract struct{}
12+
13+func (legacySnapshotSourceContract) LoadLegacySnapshots() ([]LegacySnapshot, error) { return nil, nil }
14+
15+func TestSnapshotRepositoryContracts(t *testing.T) {
16+ var _ SnapshotRepository = snapshotRepositoryContract{}
17+ var _ LegacySnapshotSource = legacySnapshotSourceContract{}
18+
19+ publication := SnapshotPublication{
20+ Name: "named-session",
21+ Head: []byte("head-envelope"),
22+ Objects: []SnapshotObject{{Digest: SnapshotDigest{1}, Data: []byte("object-envelope")}},
23+ }
24+ generation := SnapshotGeneration{Publication: publication, Manifest: []byte("manifest-envelope")}
25+ if publication.Name != "named-session" || string(generation.Manifest) != "manifest-envelope" {
26+ t.Fatalf("snapshot publication/generation = %#v", generation)
27+ }
28+ legacy := LegacySnapshot{Name: "old", Data: []byte("v3")}
29+ if legacy.Name != "old" || string(legacy.Data) != "v3" {
30+ t.Fatalf("legacy snapshot = %#v", legacy)
31+ }
32+}
33+
534 type snapshotStoreContract struct{}
635
736 func (snapshotStoreContract) Write(name string, data []byte) error { return nil }
@@ -2,6 +2,35 @@ package ports
2 2
3 import "testing"3 import "testing"
4 4
5+type snapshotRepositoryContract struct{}
6+
7+func (snapshotRepositoryContract) Publish(SnapshotPublication) error { return nil }
8+func (snapshotRepositoryContract) Load() ([]SnapshotGeneration, error) { return nil, nil }
9+func (snapshotRepositoryContract) Delete(string) error { return nil }
10+
11+type legacySnapshotSourceContract struct{}
12+
13+func (legacySnapshotSourceContract) LoadLegacySnapshots() ([]LegacySnapshot, error) { return nil, nil }
14+
15+func TestSnapshotRepositoryContracts(t *testing.T) {
16+ var _ SnapshotRepository = snapshotRepositoryContract{}
17+ var _ LegacySnapshotSource = legacySnapshotSourceContract{}
18+
19+ publication := SnapshotPublication{
20+ Name: "named-session",
21+ Head: []byte("head-envelope"),
22+ Objects: []SnapshotObject{{Digest: SnapshotDigest{1}, Data: []byte("object-envelope")}},
23+ }
24+ generation := SnapshotGeneration{Publication: publication, Manifest: []byte("manifest-envelope")}
25+ if publication.Name != "named-session" || string(generation.Manifest) != "manifest-envelope" {
26+ t.Fatalf("snapshot publication/generation = %#v", generation)
27+ }
28+ legacy := LegacySnapshot{Name: "old", Data: []byte("v3")}
29+ if legacy.Name != "old" || string(legacy.Data) != "v3" {
30+ t.Fatalf("legacy snapshot = %#v", legacy)
31+ }
32+}
33+
5 type snapshotStoreContract struct{}34 type snapshotStoreContract struct{}
6 35
7 func (snapshotStoreContract) Write(name string, data []byte) error { return nil }36 func (snapshotStoreContract) Write(name string, data []byte) error { return nil }
M internal/ports/store.go +49 -0
@@ -29,3 +29,52 @@ type SnapshotStore interface {
2929 Load() ([]SnapshotBlob, error)
3030 Delete(name string) error
3131 }
32+
33+// SnapshotDigest is the SHA-256 content address of a complete snapshot object
34+// or manifest envelope. The fixed-width value cannot be mutated by a caller.
35+type SnapshotDigest [32]byte
36+
37+// SnapshotObject is one complete, typed VEVO envelope and its content address.
38+// Data is caller-owned: repository implementations must not retain it after
39+// Publish returns, and Load returns a fresh copy that callers may mutate.
40+type SnapshotObject struct {
41+ Digest SnapshotDigest
42+ Data []byte
43+}
44+
45+// SnapshotPublication is the atomic data submitted for a named generation.
46+// Head and every object Data slice are caller-owned.
47+type SnapshotPublication struct {
48+ Name string
49+ Head []byte
50+ Objects []SnapshotObject
51+}
52+
53+// SnapshotGeneration is a published head together with its manifest and all
54+// reachable objects. Every byte slice is caller-owned by the recipient.
55+type SnapshotGeneration struct {
56+ Publication SnapshotPublication
57+ Manifest []byte
58+}
59+
60+// SnapshotRepository persists content-addressed incremental snapshot
61+// generations. Load returns caller-owned copies, so callers may retain or
62+// mutate all returned bytes without affecting the repository.
63+type SnapshotRepository interface {
64+ Publish(SnapshotPublication) error
65+ Load() ([]SnapshotGeneration, error)
66+ Delete(name string) error
67+}
68+
69+// LegacySnapshot is the pre-incremental named-session blob retained only for
70+// one-way migration. Data is caller-owned.
71+type LegacySnapshot struct {
72+ Name string
73+ Data []byte
74+}
75+
76+// LegacySnapshotSource exposes v3 snapshot blobs without coupling the new
77+// repository to the legacy SnapshotStore lifecycle.
78+type LegacySnapshotSource interface {
79+ LoadLegacySnapshots() ([]LegacySnapshot, error)
80+}
@@ -29,3 +29,52 @@ type SnapshotStore interface {
29 Load() ([]SnapshotBlob, error)29 Load() ([]SnapshotBlob, error)
30 Delete(name string) error30 Delete(name string) error
31 }31 }
32+
33+// SnapshotDigest is the SHA-256 content address of a complete snapshot object
34+// or manifest envelope. The fixed-width value cannot be mutated by a caller.
35+type SnapshotDigest [32]byte
36+
37+// SnapshotObject is one complete, typed VEVO envelope and its content address.
38+// Data is caller-owned: repository implementations must not retain it after
39+// Publish returns, and Load returns a fresh copy that callers may mutate.
40+type SnapshotObject struct {
41+ Digest SnapshotDigest
42+ Data []byte
43+}
44+
45+// SnapshotPublication is the atomic data submitted for a named generation.
46+// Head and every object Data slice are caller-owned.
47+type SnapshotPublication struct {
48+ Name string
49+ Head []byte
50+ Objects []SnapshotObject
51+}
52+
53+// SnapshotGeneration is a published head together with its manifest and all
54+// reachable objects. Every byte slice is caller-owned by the recipient.
55+type SnapshotGeneration struct {
56+ Publication SnapshotPublication
57+ Manifest []byte
58+}
59+
60+// SnapshotRepository persists content-addressed incremental snapshot
61+// generations. Load returns caller-owned copies, so callers may retain or
62+// mutate all returned bytes without affecting the repository.
63+type SnapshotRepository interface {
64+ Publish(SnapshotPublication) error
65+ Load() ([]SnapshotGeneration, error)
66+ Delete(name string) error
67+}
68+
69+// LegacySnapshot is the pre-incremental named-session blob retained only for
70+// one-way migration. Data is caller-owned.
71+type LegacySnapshot struct {
72+ Name string
73+ Data []byte
74+}
75+
76+// LegacySnapshotSource exposes v3 snapshot blobs without coupling the new
77+// repository to the legacy SnapshotStore lifecycle.
78+type LegacySnapshotSource interface {
79+ LoadLegacySnapshots() ([]LegacySnapshot, error)
80+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close