diff --git a/data/acltreebuilder.go b/data/acltreebuilder.go index 0fe3e347..f97aa805 100644 --- a/data/acltreebuilder.go +++ b/data/acltreebuilder.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/anytypeio/go-anytype-infrastructure-experiments/data/pb" "github.com/anytypeio/go-anytype-infrastructure-experiments/data/threadmodels" + "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/gogo/protobuf/proto" "github.com/textileio/go-threads/core/thread" "time" @@ -80,8 +81,12 @@ func (tb *ACLTreeBuilder) verify(identity string, payload, signature []byte) (is func (tb *ACLTreeBuilder) Build() (*Tree, error) { heads := tb.thread.Heads() + aclHeads, err := tb.getACLHeads(heads) + if err != nil { + return nil, err + } - if err := tb.buildTreeFromStart(heads); err != nil { + if err = tb.buildTreeFromStart(aclHeads); err != nil { return nil, fmt.Errorf("buildTree error: %v", err) } tb.cache = nil @@ -157,3 +162,40 @@ func (tb *ACLTreeBuilder) getRoot(possibleRoots []*Change) (*Change, error) { } return nil, fmt.Errorf("could not find any root") } + +func (tb *ACLTreeBuilder) getACLHeads(heads []string) (aclTreeHeads []string, err error) { + for _, head := range heads { + if slice.FindPos(aclTreeHeads, head) != -1 { // do not scan known heads + continue + } + precedingHeads, err := tb.getPrecedingACLHeads(head) + if err != nil { + return nil, err + } + + for _, aclHead := range precedingHeads { + if slice.FindPos(aclTreeHeads, aclHead) != -1 { + continue + } + aclTreeHeads = append(aclTreeHeads, aclHead) + } + } + + if len(aclTreeHeads) == 0 { + return nil, fmt.Errorf("no usable ACL heads in thread") + } + return aclTreeHeads, nil +} + +func (tb *ACLTreeBuilder) getPrecedingACLHeads(head string) ([]string, error) { + headChange, err := tb.loadChange(head) + if err != nil { + return nil, err + } + + if headChange.Content.GetAclData() != nil { + return []string{head}, nil + } else { + return headChange.PreviousIds, nil + } +} diff --git a/data/treebuilder.go b/data/treebuilder.go index 4e76f27c..1d04804b 100644 --- a/data/treebuilder.go +++ b/data/treebuilder.go @@ -11,7 +11,6 @@ import ( "github.com/gogo/protobuf/proto" "github.com/prometheus/common/log" "github.com/textileio/go-threads/core/thread" - "sort" "time" ) @@ -89,13 +88,10 @@ func (tb *TreeBuilder) verify(identity string, payload, signature []byte) (isVer } func (tb *TreeBuilder) Build(fromStart bool) (*Tree, error) { - heads, err := tb.getActualHeads() - if err != nil { - return nil, fmt.Errorf("get acl heads error: %v", err) - } + heads := tb.thread.Heads() if fromStart { - if err = tb.buildTreeFromStart(heads); err != nil { + if err := tb.buildTreeFromStart(heads); err != nil { return nil, fmt.Errorf("buildTree error: %v", err) } } else { @@ -195,59 +191,6 @@ func (tb *TreeBuilder) dfs(stack []string, breakpoint string) (buf []*Change, er return buf, nil } -func (tb *TreeBuilder) getActualHeads(logs []threadmodels.ThreadLog) (heads []string, err error) { - sort.Slice(logs, func(i, j int) bool { - return logs[i].ID < logs[j].ID - }) - var knownHeads []string - var validLogs = logs[:0] - for _, l := range logs { - if slice.FindPos(knownHeads, l.Head) != -1 { // do not scan known heads - continue - } - sh, err := tb.getNearSnapshot(l.Head) - if err != nil { - log.Warnf("can't get near snapshot: %v; ignore", err) - continue - } - if sh.LogHeads != nil { - for _, headId := range sh.LogHeads { - knownHeads = append(knownHeads, headId) - } - } - validLogs = append(validLogs, l) - } - for _, l := range validLogs { - if slice.FindPos(knownHeads, l.Head) != -1 { // do not scan known heads - continue - } else { - heads = append(heads, l.Head) - } - } - if len(heads) == 0 { - return nil, fmt.Errorf("no usable logs in head") - } - return -} - -func (tb *TreeBuilder) getNearSnapshot(id string) (sh *Change, err error) { - ch, err := tb.loadChange(id) - if err != nil { - return - } - - if ch.IsSnapshot { - sh = ch - } else { - sh, err = tb.loadChange(ch.SnapshotId) - if err != nil { - return nil, err - } - } - - return sh, nil -} - func (tb *TreeBuilder) findBreakpoint(heads []string) (breakpoint string, err error) { var ( ch *Change diff --git a/data/treegraph_nix.go b/data/treegraph_nix.go index b06f7435..0adbb58f 100644 --- a/data/treegraph_nix.go +++ b/data/treegraph_nix.go @@ -10,11 +10,12 @@ package data import ( "bytes" "fmt" - "github.com/goccy/go-graphviz" - "github.com/goccy/go-graphviz/cgraph" "strings" "time" "unicode" + + "github.com/goccy/go-graphviz" + "github.com/goccy/go-graphviz/cgraph" ) func (t *Tree) Graph() (data string, err error) { @@ -70,17 +71,18 @@ func (t *Tree) Graph() (data string, err error) { } } if c.DecryptedDocumentChange != nil { - for _, chc := range c.DecryptedDocumentChange.Content { - tp := fmt.Sprintf("%T", chc.Value) - tp = strings.Replace(tp, "ChangeContentValueOf", "", 1) - res := "" - for _, ts := range tp { - if unicode.IsUpper(ts) { - res += string(ts) - } - } - chSymbs = append(chSymbs, res) - } + // TODO: add some parser to provide custom unmarshalling for the document change + //for _, chc := range c.DecryptedDocumentChange.Content { + // tp := fmt.Sprintf("%T", chc.Value) + // tp = strings.Replace(tp, "ChangeContentValueOf", "", 1) + // res := "" + // for _, ts := range tp { + // if unicode.IsUpper(ts) { + // res += string(ts) + // } + // } + // chSymbs = append(chSymbs, res) + //} } shortId := c.Id diff --git a/go.mod b/go.mod index 45eaba98..bcbed4af 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/textileio/go-threads v1.0.2-0.20210304072541-d0f91da84404 gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c + github.com/goccy/go-graphviz v0.0.9 ) replace github.com/textileio/go-threads => github.com/anytypeio/go-threads v1.1.0-rc1.0.20220223104843-a67245cee80e