From 0d516874e2053f008be8031263cea693aecec1a6 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Wed, 25 Jan 2023 21:20:23 +0100 Subject: [PATCH] Add tree exporter --- .../object/tree/exporter/treeexporter.go | 55 ++++++++++++++++++- .../object/tree/exporter/treeimport.go | 14 ++++- .../mock_objecttree/mock_objecttree.go | 15 +++++ .../object/tree/objecttree/objecttree.go | 6 ++ .../synctree/mock_synctree/mock_synctree.go | 15 +++++ 5 files changed, 101 insertions(+), 4 deletions(-) diff --git a/commonspace/object/tree/exporter/treeexporter.go b/commonspace/object/tree/exporter/treeexporter.go index 3f21ff28..01d41f96 100644 --- a/commonspace/object/tree/exporter/treeexporter.go +++ b/commonspace/object/tree/exporter/treeexporter.go @@ -2,7 +2,9 @@ package exporter import ( "github.com/anytypeio/any-sync/commonspace/object/acl/liststorage" + "github.com/anytypeio/any-sync/commonspace/object/keychain" "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" + "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" ) @@ -21,6 +23,55 @@ type TreeExporter interface { ExportUnencrypted(tree objecttree.ReadableObjectTree) (err error) } -func NewTreeExporter(params TreeExporterParams) TreeExporter { - return nil +type treeExporter struct { + listExporter liststorage.Exporter + treeExporter treestorage.Exporter + converter DataConverter +} + +func NewTreeExporter(params TreeExporterParams) TreeExporter { + return &treeExporter{ + listExporter: params.ListStorageExporter, + treeExporter: params.TreeStorageExporter, + converter: params.DataConverter, + } +} + +func (t *treeExporter) ExportUnencrypted(tree objecttree.ReadableObjectTree) (err error) { + lst := tree.AclList() + // this exports root which should be enough before we implement acls + _, err = t.listExporter.ListStorage(lst.Root()) + if err != nil { + return + } + treeStorage, err := t.treeExporter.TreeStorage(tree.Header()) + if err != nil { + return + } + changeBuilder := objecttree.NewChangeBuilder(keychain.NewKeychain(), tree.Header()) + putStorage := func(change *objecttree.Change) (err error) { + var raw *treechangeproto.RawTreeChangeWithId + raw, err = changeBuilder.Marshall(change) + if err != nil { + return + } + return treeStorage.AddRawChange(raw) + } + err = tree.IterateRoot(t.converter.Unmarshall, func(change *objecttree.Change) bool { + if change.Id == tree.Id() { + err = putStorage(change) + return err == nil + } + var data []byte + data, err = t.converter.Marshall(change.Model) + if err != nil { + return false + } + // that means that change is unencrypted + change.ReadKeyHash = 0 + change.Data = data + err = putStorage(change) + return err == nil + }) + return err } diff --git a/commonspace/object/tree/exporter/treeimport.go b/commonspace/object/tree/exporter/treeimport.go index 69384b6a..f0ac9a82 100644 --- a/commonspace/object/tree/exporter/treeimport.go +++ b/commonspace/object/tree/exporter/treeimport.go @@ -1,6 +1,7 @@ package exporter import ( + "github.com/anytypeio/any-sync/commonspace/object/acl/list" "github.com/anytypeio/any-sync/commonspace/object/acl/liststorage" "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" @@ -13,6 +14,15 @@ type TreeImportParams struct { IncludeBeforeId bool } -func ImportHistoryTree(params TreeImportParams) (objecttree.ReadableObjectTree, error) { - return nil, nil +func ImportHistoryTree(params TreeImportParams) (tree objecttree.ReadableObjectTree, err error) { + aclList, err := list.BuildAclList(params.ListStorage) + if err != nil { + return + } + return objecttree.BuildNonVerifiableHistoryTree(objecttree.HistoryTreeParams{ + TreeStorage: params.TreeStorage, + AclList: aclList, + BeforeId: params.BeforeId, + IncludeBeforeId: params.IncludeBeforeId, + }) } diff --git a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go index c8dc3841..6915f927 100644 --- a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go +++ b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go @@ -8,6 +8,7 @@ import ( context "context" reflect "reflect" + list "github.com/anytypeio/any-sync/commonspace/object/acl/list" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" treestorage "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" @@ -37,6 +38,20 @@ func (m *MockObjectTree) EXPECT() *MockObjectTreeMockRecorder { return m.recorder } +// AclList mocks base method. +func (m *MockObjectTree) AclList() list.AclList { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AclList") + ret0, _ := ret[0].(list.AclList) + return ret0 +} + +// AclList indicates an expected call of AclList. +func (mr *MockObjectTreeMockRecorder) AclList() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AclList", reflect.TypeOf((*MockObjectTree)(nil).AclList)) +} + // AddContent mocks base method. func (m *MockObjectTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) { m.ctrl.T.Helper() diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index bc806522..58c254da 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -52,6 +52,8 @@ type ReadableObjectTree interface { Heads() []string Root() *Change + AclList() list.AclList + HasChanges(...string) bool GetChange(string) (*Change, error) @@ -122,6 +124,10 @@ func (ot *objectTree) Id() string { return ot.id } +func (ot *objectTree) AclList() list.AclList { + return ot.aclList +} + func (ot *objectTree) Header() *treechangeproto.RawTreeChangeWithId { return ot.rawRoot } diff --git a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go index 73335d45..6fad9dd5 100644 --- a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go +++ b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go @@ -8,6 +8,7 @@ import ( context "context" reflect "reflect" + list "github.com/anytypeio/any-sync/commonspace/object/acl/list" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" updatelistener "github.com/anytypeio/any-sync/commonspace/object/tree/synctree/updatelistener" treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" @@ -162,6 +163,20 @@ func (m *MockSyncTree) EXPECT() *MockSyncTreeMockRecorder { return m.recorder } +// AclList mocks base method. +func (m *MockSyncTree) AclList() list.AclList { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AclList") + ret0, _ := ret[0].(list.AclList) + return ret0 +} + +// AclList indicates an expected call of AclList. +func (mr *MockSyncTreeMockRecorder) AclList() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AclList", reflect.TypeOf((*MockSyncTree)(nil).AclList)) +} + // AddContent mocks base method. func (m *MockSyncTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) { m.ctrl.T.Helper()