Add logic update and create logic
This commit is contained in:
parent
e6534e134b
commit
43797b1b84
@ -10,7 +10,6 @@ import (
|
||||
|
||||
type aclStateBuilder struct {
|
||||
tree *Tree
|
||||
aclState *ACLState
|
||||
identity string
|
||||
key keys.EncryptionPrivKey
|
||||
decoder keys.SigningPubKeyDecoder
|
||||
@ -29,15 +28,28 @@ func newACLStateBuilder(decoder keys.SigningPubKeyDecoder, accountData *account.
|
||||
}
|
||||
}
|
||||
|
||||
func (sb *aclStateBuilder) build() (*ACLState, error) {
|
||||
state, _, err := sb.buildBefore("")
|
||||
func (sb *aclStateBuilder) Init(tree *Tree) error {
|
||||
sb.tree = tree
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sb *aclStateBuilder) Build() (*ACLState, error) {
|
||||
state, _, err := sb.BuildBefore("")
|
||||
return state, err
|
||||
}
|
||||
|
||||
func (sb *aclStateBuilder) init(tree *Tree) error {
|
||||
root := tree.Root()
|
||||
// TODO: we can probably have only one state builder, because we can Build both at the same time
|
||||
func (sb *aclStateBuilder) BuildBefore(beforeId string) (*ACLState, bool, error) {
|
||||
var (
|
||||
err error
|
||||
startChange = sb.tree.root
|
||||
foundId bool
|
||||
idSeenMap = make(map[string][]*Change)
|
||||
decreasedPermissions *decreasedPermissionsParameters
|
||||
)
|
||||
root := sb.tree.Root()
|
||||
if !root.IsSnapshot {
|
||||
return fmt.Errorf("root should always be a snapshot")
|
||||
return nil, false, fmt.Errorf("root should always be a snapshot")
|
||||
}
|
||||
|
||||
snapshot := root.Content.GetAclData().GetAclSnapshot()
|
||||
@ -47,27 +59,13 @@ func (sb *aclStateBuilder) init(tree *Tree) error {
|
||||
sb.key,
|
||||
sb.decoder)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not build ACLState from snapshot: %w", err)
|
||||
return nil, false, fmt.Errorf("could not build ACLState from snapshot: %w", err)
|
||||
}
|
||||
sb.tree = tree
|
||||
sb.aclState = state
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: we can probably have only one state builder, because we can build both at the same time
|
||||
func (sb *aclStateBuilder) buildBefore(beforeId string) (*ACLState, bool, error) {
|
||||
var (
|
||||
err error
|
||||
startChange = sb.tree.root
|
||||
foundId bool
|
||||
idSeenMap = make(map[string][]*Change)
|
||||
decreasedPermissions *decreasedPermissionsParameters
|
||||
)
|
||||
idSeenMap[startChange.Content.Identity] = append(idSeenMap[startChange.Content.Identity], startChange)
|
||||
|
||||
if startChange.Content.GetChangesData() != nil {
|
||||
key, exists := sb.aclState.userReadKeys[startChange.Content.CurrentReadKeyHash]
|
||||
key, exists := state.userReadKeys[startChange.Content.CurrentReadKeyHash]
|
||||
if !exists {
|
||||
return nil, false, fmt.Errorf("no first snapshot")
|
||||
}
|
||||
@ -79,7 +77,7 @@ func (sb *aclStateBuilder) buildBefore(beforeId string) (*ACLState, bool, error)
|
||||
}
|
||||
|
||||
if beforeId == startChange.Id {
|
||||
return sb.aclState, true, nil
|
||||
return state, true, nil
|
||||
}
|
||||
|
||||
for {
|
||||
@ -101,13 +99,13 @@ func (sb *aclStateBuilder) buildBefore(beforeId string) (*ACLState, bool, error)
|
||||
|
||||
idSeenMap[c.Content.Identity] = append(idSeenMap[c.Content.Identity], c)
|
||||
if c.Content.GetAclData() != nil {
|
||||
err = sb.aclState.applyChange(c.Id, c.Content)
|
||||
err = state.applyChange(c.Id, c.Content)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// if we have some users who have less permissions now
|
||||
users := sb.aclState.getPermissionDecreasedUsers(c.Content)
|
||||
users := state.getPermissionDecreasedUsers(c.Content)
|
||||
if len(users) > 0 {
|
||||
decreasedPermissions = &decreasedPermissionsParameters{
|
||||
users: users,
|
||||
@ -118,14 +116,14 @@ func (sb *aclStateBuilder) buildBefore(beforeId string) (*ACLState, bool, error)
|
||||
}
|
||||
|
||||
// the user can't make changes
|
||||
if !sb.aclState.hasPermission(c.Content.Identity, pb.ACLChange_Writer) && !sb.aclState.hasPermission(c.Content.Identity, pb.ACLChange_Admin) {
|
||||
if !state.hasPermission(c.Content.Identity, pb.ACLChange_Writer) && !state.hasPermission(c.Content.Identity, pb.ACLChange_Admin) {
|
||||
err = fmt.Errorf("user %s cannot make changes", c.Content.Identity)
|
||||
return false
|
||||
}
|
||||
|
||||
// decrypting contents on the fly
|
||||
if c.Content.GetChangesData() != nil {
|
||||
key, exists := sb.aclState.userReadKeys[c.Content.CurrentReadKeyHash]
|
||||
key, exists := state.userReadKeys[c.Content.CurrentReadKeyHash]
|
||||
if !exists {
|
||||
err = fmt.Errorf("failed to find key with hash: %d", c.Content.CurrentReadKeyHash)
|
||||
return false
|
||||
@ -169,7 +167,7 @@ func (sb *aclStateBuilder) buildBefore(beforeId string) (*ACLState, bool, error)
|
||||
decreasedPermissions = nil
|
||||
if removed {
|
||||
// starting from the beginning but with updated Tree
|
||||
return sb.buildBefore(beforeId)
|
||||
return sb.BuildBefore(beforeId)
|
||||
}
|
||||
} else if err == nil {
|
||||
// we can finish the acl state building process
|
||||
@ -185,5 +183,5 @@ func (sb *aclStateBuilder) buildBefore(beforeId string) (*ACLState, bool, error)
|
||||
err = nil
|
||||
}
|
||||
|
||||
return sb.aclState, foundId, err
|
||||
return state, foundId, err
|
||||
}
|
||||
|
||||
@ -19,8 +19,8 @@ type ACLContext struct {
|
||||
|
||||
func createTreeFromThread(t thread.Thread, fromStart bool) (*Tree, error) {
|
||||
treeBuilder := newTreeBuilder(t, keys.NewEd25519Decoder())
|
||||
treeBuilder.init()
|
||||
return treeBuilder.build(fromStart)
|
||||
treeBuilder.Init()
|
||||
return treeBuilder.Build(fromStart)
|
||||
}
|
||||
|
||||
func createACLStateFromThread(
|
||||
@ -40,16 +40,16 @@ func createACLStateFromThread(
|
||||
}
|
||||
|
||||
aclTreeBuilder := newACLTreeBuilder(t, decoder)
|
||||
aclTreeBuilder.init()
|
||||
aclTree, err := aclTreeBuilder.build()
|
||||
aclTreeBuilder.Init()
|
||||
aclTree, err := aclTreeBuilder.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !fromStart {
|
||||
snapshotValidator := newSnapshotValidator(decoder, accountData)
|
||||
snapshotValidator.init(aclTree)
|
||||
valid, err := snapshotValidator.validateSnapshot(tree.root)
|
||||
snapshotValidator.Init(aclTree)
|
||||
valid, err := snapshotValidator.ValidateSnapshot(tree.root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -60,12 +60,12 @@ func createACLStateFromThread(
|
||||
}
|
||||
|
||||
aclBuilder := newACLStateBuilder(decoder, accountData)
|
||||
err = aclBuilder.init(tree)
|
||||
err = aclBuilder.Init(tree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aclState, err := aclBuilder.build()
|
||||
aclState, err := aclBuilder.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -88,7 +88,7 @@ func TestACLStateBuilder_UserJoinBuild(t *testing.T) {
|
||||
keys.NewEd25519Decoder(),
|
||||
false)
|
||||
if err != nil {
|
||||
t.Fatalf("should build acl ACLState without err: %v", err)
|
||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||
}
|
||||
aclState := ctx.ACLState
|
||||
//fmt.Println(ctx.Tree.Graph())
|
||||
@ -122,7 +122,7 @@ func TestACLStateBuilder_UserRemoveBuild(t *testing.T) {
|
||||
keys.NewEd25519Decoder(),
|
||||
false)
|
||||
if err != nil {
|
||||
t.Fatalf("should build acl ACLState without err: %v", err)
|
||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||
}
|
||||
aclState := ctx.ACLState
|
||||
//fmt.Println(ctx.Tree.Graph())
|
||||
@ -152,7 +152,7 @@ func TestACLStateBuilder_UserRemoveBeforeBuild(t *testing.T) {
|
||||
keys.NewEd25519Decoder(),
|
||||
false)
|
||||
if err != nil {
|
||||
t.Fatalf("should build acl ACLState without err: %v", err)
|
||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||
}
|
||||
aclState := ctx.ACLState
|
||||
//fmt.Println(ctx.Tree.Graph())
|
||||
@ -183,7 +183,7 @@ func TestACLStateBuilder_InvalidSnapshotBuild(t *testing.T) {
|
||||
keys.NewEd25519Decoder(),
|
||||
false)
|
||||
if err != nil {
|
||||
t.Fatalf("should build acl ACLState without err: %v", err)
|
||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||
}
|
||||
aclState := ctx.ACLState
|
||||
//fmt.Println(ctx.Tree.Graph())
|
||||
@ -213,7 +213,7 @@ func TestACLStateBuilder_ValidSnapshotBuild(t *testing.T) {
|
||||
keys.NewEd25519Decoder(),
|
||||
false)
|
||||
if err != nil {
|
||||
t.Fatalf("should build acl ACLState without err: %v", err)
|
||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||
}
|
||||
aclState := ctx.ACLState
|
||||
//fmt.Println(ctx.Tree.Graph())
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type AddResultSummary int
|
||||
@ -18,17 +19,17 @@ const (
|
||||
)
|
||||
|
||||
type AddResult struct {
|
||||
AttachedChanges []*Change
|
||||
InvalidChanges []*Change
|
||||
UnattachedChanges []*Change
|
||||
|
||||
OldHeads []string
|
||||
Heads []string
|
||||
// TODO: add summary for changes
|
||||
Summary AddResultSummary
|
||||
}
|
||||
|
||||
// TODO: Change add change content to include ACLChangeBuilder
|
||||
type ACLTree interface {
|
||||
ACLState() *ACLState
|
||||
AddContent(changeContent *ChangeContent) (*Change, error)
|
||||
AddChanges(changes ...*Change) (AddResult, error) // TODO: Make change as interface
|
||||
AddChanges(changes ...*Change) (AddResult, error)
|
||||
Heads() []string
|
||||
Iterate(func(change *Change) bool)
|
||||
IterateFrom(string, func(change *Change) bool)
|
||||
@ -40,13 +41,15 @@ type aclTree struct {
|
||||
accountData *account.AccountData
|
||||
|
||||
fullTree *Tree
|
||||
aclTree *Tree // this tree is built from start of the document
|
||||
aclTree *Tree // TODO: right now we don't use it, we can probably have only local var for now. This tree is built from start of the document
|
||||
aclState *ACLState
|
||||
|
||||
treeBuilder *treeBuilder
|
||||
aclTreeBuilder *aclTreeBuilder
|
||||
aclStateBuilder *aclStateBuilder
|
||||
snapshotValidator *snapshotValidator
|
||||
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func BuildACLTree(t thread.Thread, acc *account.AccountData) (ACLTree, error) {
|
||||
@ -74,14 +77,15 @@ func BuildACLTree(t thread.Thread, acc *account.AccountData) (ACLTree, error) {
|
||||
return aclTree, nil
|
||||
}
|
||||
|
||||
// TODO: this is not used for now, in future we should think about not making full tree rebuild
|
||||
func (a *aclTree) rebuildFromTree(validateSnapshot bool) (err error) {
|
||||
if validateSnapshot {
|
||||
err = a.snapshotValidator.init(a.aclTree)
|
||||
err = a.snapshotValidator.Init(a.aclTree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valid, err := a.snapshotValidator.validateSnapshot(a.fullTree.root)
|
||||
valid, err := a.snapshotValidator.ValidateSnapshot(a.fullTree.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -90,12 +94,12 @@ func (a *aclTree) rebuildFromTree(validateSnapshot bool) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
err = a.aclStateBuilder.init(a.fullTree)
|
||||
err = a.aclStateBuilder.Init(a.fullTree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.aclState, err = a.aclStateBuilder.build()
|
||||
a.aclState, err = a.aclStateBuilder.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -104,28 +108,28 @@ func (a *aclTree) rebuildFromTree(validateSnapshot bool) (err error) {
|
||||
}
|
||||
|
||||
func (a *aclTree) rebuildFromThread(fromStart bool) error {
|
||||
a.treeBuilder.init()
|
||||
a.aclTreeBuilder.init()
|
||||
a.treeBuilder.Init()
|
||||
a.aclTreeBuilder.Init()
|
||||
|
||||
var err error
|
||||
a.fullTree, err = a.treeBuilder.build(fromStart)
|
||||
a.fullTree, err = a.treeBuilder.Build(fromStart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: remove this from context as this is used only to validate snapshot
|
||||
a.aclTree, err = a.aclTreeBuilder.build()
|
||||
a.aclTree, err = a.aclTreeBuilder.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !fromStart {
|
||||
err = a.snapshotValidator.init(a.aclTree)
|
||||
err = a.snapshotValidator.Init(a.aclTree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valid, err := a.snapshotValidator.validateSnapshot(a.fullTree.root)
|
||||
valid, err := a.snapshotValidator.ValidateSnapshot(a.fullTree.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -133,12 +137,12 @@ func (a *aclTree) rebuildFromThread(fromStart bool) error {
|
||||
return a.rebuildFromThread(true)
|
||||
}
|
||||
}
|
||||
err = a.aclStateBuilder.init(a.fullTree)
|
||||
err = a.aclStateBuilder.Init(a.fullTree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.aclState, err = a.aclStateBuilder.build()
|
||||
a.aclState, err = a.aclStateBuilder.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -181,6 +185,8 @@ func (a *aclTree) ACLState() *ACLState {
|
||||
|
||||
func (a *aclTree) AddContent(changeContent *ChangeContent) (*Change, error) {
|
||||
// TODO: add snapshot creation logic
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
marshalled, err := changeContent.ChangesData.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -239,40 +245,100 @@ func (a *aclTree) AddContent(changeContent *ChangeContent) (*Change, error) {
|
||||
}
|
||||
|
||||
func (a *aclTree) AddChanges(changes ...*Change) (AddResult, error) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
// TODO: make proper error handling, because there are a lot of corner cases where this will break
|
||||
var aclChanges []*Change
|
||||
var err error
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// removing attached or invalid orphans
|
||||
var toRemove []string
|
||||
|
||||
for _, orphan := range a.thread.Orphans() {
|
||||
if _, exists := a.fullTree.attached[orphan]; exists {
|
||||
toRemove = append(toRemove, orphan)
|
||||
}
|
||||
if _, exists := a.fullTree.invalidChanges[orphan]; exists {
|
||||
toRemove = append(toRemove, orphan)
|
||||
}
|
||||
}
|
||||
a.thread.RemoveOrphans(toRemove...)
|
||||
}()
|
||||
|
||||
for _, ch := range changes {
|
||||
if ch.IsACLChange() {
|
||||
aclChanges = append(aclChanges, ch)
|
||||
break
|
||||
}
|
||||
a.thread.A
|
||||
err = a.thread.AddChange(ch)
|
||||
if err != nil {
|
||||
return AddResult{}, err
|
||||
}
|
||||
a.thread.AddOrphans(ch.Id)
|
||||
}
|
||||
|
||||
// TODO: understand the common snapshot problem
|
||||
prevHeads := a.fullTree.Heads()
|
||||
mode := a.fullTree.Add(changes...)
|
||||
switch mode {
|
||||
case Nothing:
|
||||
return AddResult{Summary: AddResultSummaryNothing}, nil
|
||||
return AddResult{
|
||||
OldHeads: prevHeads,
|
||||
Heads: prevHeads,
|
||||
Summary: AddResultSummaryNothing,
|
||||
}, nil
|
||||
|
||||
case Rebuild:
|
||||
res, err := d.Build()
|
||||
return AddResult{Summary: Rebuild}, err
|
||||
err = a.rebuildFromThread(false)
|
||||
if err != nil {
|
||||
return AddResult{}, err
|
||||
}
|
||||
|
||||
return AddResult{
|
||||
OldHeads: prevHeads,
|
||||
Heads: a.fullTree.Heads(),
|
||||
Summary: AddResultSummaryRebuild,
|
||||
}, nil
|
||||
default:
|
||||
break
|
||||
a.aclState, err = a.aclStateBuilder.Build()
|
||||
if err != nil {
|
||||
return AddResult{}, err
|
||||
}
|
||||
|
||||
return AddResult{
|
||||
OldHeads: prevHeads,
|
||||
Heads: a.fullTree.Heads(),
|
||||
Summary: AddResultSummaryAppend,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a *aclTree) Iterate(f func(change *Change) bool) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
a.fullTree.Iterate(a.fullTree.RootId(), f)
|
||||
}
|
||||
|
||||
func (a *aclTree) IterateFrom(s string, f func(change *Change) bool) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
a.fullTree.Iterate(s, f)
|
||||
}
|
||||
|
||||
func (a *aclTree) HasChange(s string) bool {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
_, attachedExists := a.fullTree.attached[s]
|
||||
_, unattachedExists := a.fullTree.unAttached[s]
|
||||
_, invalidExists := a.fullTree.invalidChanges[s]
|
||||
return attachedExists || unattachedExists || invalidExists
|
||||
}
|
||||
|
||||
func (a *aclTree) Heads() []string {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
return a.fullTree.Heads()
|
||||
}
|
||||
|
||||
@ -30,16 +30,19 @@ func newACLTreeBuilder(t thread.Thread, decoder keys.SigningPubKeyDecoder) *aclT
|
||||
}
|
||||
}
|
||||
|
||||
func (tb *aclTreeBuilder) init() {
|
||||
func (tb *aclTreeBuilder) Init() {
|
||||
tb.cache = make(map[string]*Change)
|
||||
tb.identityKeys = make(map[string]keys.SigningPubKey)
|
||||
tb.tree = &Tree{}
|
||||
tb.changeLoader.init(tb.cache, tb.identityKeys)
|
||||
tb.changeLoader.Init(tb.cache, tb.identityKeys)
|
||||
}
|
||||
|
||||
func (tb *aclTreeBuilder) build() (*Tree, error) {
|
||||
heads := tb.thread.PossibleHeads()
|
||||
aclHeads, err := tb.getACLHeads(heads)
|
||||
func (tb *aclTreeBuilder) Build() (*Tree, error) {
|
||||
var headsAndOrphans []string
|
||||
headsAndOrphans = append(headsAndOrphans, tb.thread.Orphans()...)
|
||||
headsAndOrphans = append(headsAndOrphans, tb.thread.Heads()...)
|
||||
aclHeads, err := tb.getACLHeads(headsAndOrphans)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ func newChangeLoader(
|
||||
}
|
||||
}
|
||||
|
||||
func (c *changeLoader) init(cache map[string]*Change,
|
||||
func (c *changeLoader) Init(cache map[string]*Change,
|
||||
identityKeys map[string]keys.SigningPubKey) {
|
||||
c.cache = cache
|
||||
c.identityKeys = identityKeys
|
||||
|
||||
@ -26,13 +26,13 @@ func newSnapshotValidator(
|
||||
}
|
||||
}
|
||||
|
||||
func (s *snapshotValidator) init(aclTree *Tree) error {
|
||||
func (s *snapshotValidator) Init(aclTree *Tree) error {
|
||||
s.aclTree = aclTree
|
||||
return s.stateBuilder.init(aclTree)
|
||||
return s.stateBuilder.Init(aclTree)
|
||||
}
|
||||
|
||||
func (s *snapshotValidator) validateSnapshot(ch *Change) (bool, error) {
|
||||
st, found, err := s.stateBuilder.buildBefore(ch.Id)
|
||||
func (s *snapshotValidator) ValidateSnapshot(ch *Change) (bool, error) {
|
||||
st, found, err := s.stateBuilder.BuildBefore(ch.Id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@ -38,27 +38,29 @@ func newTreeBuilder(t thread.Thread, decoder keys.SigningPubKeyDecoder) *treeBui
|
||||
}
|
||||
}
|
||||
|
||||
func (tb *treeBuilder) init() {
|
||||
func (tb *treeBuilder) Init() {
|
||||
tb.cache = make(map[string]*Change)
|
||||
tb.identityKeys = make(map[string]keys.SigningPubKey)
|
||||
tb.tree = &Tree{}
|
||||
tb.changeLoader.init(tb.cache, tb.identityKeys)
|
||||
tb.changeLoader.Init(tb.cache, tb.identityKeys)
|
||||
}
|
||||
|
||||
func (tb *treeBuilder) build(fromStart bool) (*Tree, error) {
|
||||
heads := tb.thread.PossibleHeads()
|
||||
func (tb *treeBuilder) Build(fromStart bool) (*Tree, error) {
|
||||
var headsAndOrphans []string
|
||||
headsAndOrphans = append(headsAndOrphans, tb.thread.Orphans()...)
|
||||
headsAndOrphans = append(headsAndOrphans, tb.thread.Heads()...)
|
||||
|
||||
if fromStart {
|
||||
if err := tb.buildTreeFromStart(heads); err != nil {
|
||||
if err := tb.buildTreeFromStart(headsAndOrphans); err != nil {
|
||||
return nil, fmt.Errorf("buildTree error: %v", err)
|
||||
}
|
||||
} else {
|
||||
breakpoint, err := tb.findBreakpoint(heads)
|
||||
breakpoint, err := tb.findBreakpoint(headsAndOrphans)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("findBreakpoint error: %v", err)
|
||||
}
|
||||
|
||||
if err = tb.buildTree(heads, breakpoint); err != nil {
|
||||
if err = tb.buildTree(headsAndOrphans, breakpoint); err != nil {
|
||||
return nil, fmt.Errorf("buildTree error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ func (t *ThreadBuilder) AddRawChange(change *thread.RawChange) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) AddPossibleHead(head string) {
|
||||
func (t *ThreadBuilder) AddOrphans(head string) {
|
||||
t.maybeHeads = append(t.maybeHeads, head)
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ func (t *ThreadBuilder) AddChange(change aclchanges.Change) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) PossibleHeads() []string {
|
||||
func (t *ThreadBuilder) Orphans() []string {
|
||||
return t.maybeHeads
|
||||
}
|
||||
|
||||
|
||||
@ -11,13 +11,14 @@ type Thread interface {
|
||||
ID() string
|
||||
|
||||
Heads() []string
|
||||
PossibleHeads() []string
|
||||
Orphans() []string
|
||||
SetHeads(heads []string)
|
||||
SetPossibleHeads(heads []string)
|
||||
AddPossibleHead(head string)
|
||||
RemoveOrphans(orphan ...string)
|
||||
AddOrphans(orphan ...string)
|
||||
|
||||
AddRawChange(change *RawChange) error
|
||||
AddChange(change aclchanges.Change) error
|
||||
// TODO: have methods with raw changes also
|
||||
GetChange(ctx context.Context, recordID string) (*RawChange, error)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user