Add doc tree

This commit is contained in:
mcrakhman 2022-08-10 18:10:28 +02:00
parent 103c8a4aef
commit 0e3d7cc8ca
No known key found for this signature in database
GPG Key ID: DED12CFEF5B8396B
6 changed files with 272 additions and 133 deletions

View File

@ -30,7 +30,7 @@ type AddResult struct {
Summary AddResultSummary Summary AddResultSummary
} }
type TreeUpdateListener interface { type ACLTreeUpdateListener interface {
Update(tree ACLTree) Update(tree ACLTree)
Rebuild(tree ACLTree) Rebuild(tree ACLTree)
} }
@ -72,7 +72,7 @@ type ACLTree interface {
type aclTree struct { type aclTree struct {
treeStorage treestorage.TreeStorage treeStorage treestorage.TreeStorage
accountData *account.AccountData accountData *account.AccountData
updateListener TreeUpdateListener updateListener ACLTreeUpdateListener
id string id string
header *treepb.TreeHeader header *treepb.TreeHeader
@ -86,7 +86,7 @@ type aclTree struct {
sync.RWMutex sync.RWMutex
} }
func BuildACLTreeWithIdentity(t treestorage.TreeStorage, acc *account.AccountData, listener TreeUpdateListener) (ACLTree, error) { func BuildACLTreeWithIdentity(t treestorage.TreeStorage, acc *account.AccountData, listener ACLTreeUpdateListener) (ACLTree, error) {
treeBuilder := newTreeBuilder(t, acc.Decoder) treeBuilder := newTreeBuilder(t, acc.Decoder)
aclStateBuilder := newACLStateBuilderWithIdentity(acc.Decoder, acc) aclStateBuilder := newACLStateBuilderWithIdentity(acc.Decoder, acc)
changeBuilder := newACLChangeBuilder() changeBuilder := newACLChangeBuilder()
@ -127,7 +127,7 @@ func BuildACLTreeWithIdentity(t treestorage.TreeStorage, acc *account.AccountDat
return aclTree, nil return aclTree, nil
} }
func BuildACLTree(t treestorage.TreeStorage, decoder signingkey.PubKeyDecoder, listener TreeUpdateListener) (ACLTree, error) { func BuildACLTree(t treestorage.TreeStorage, decoder signingkey.PubKeyDecoder, listener ACLTreeUpdateListener) (ACLTree, error) {
treeBuilder := newTreeBuilder(t, decoder) treeBuilder := newTreeBuilder(t, decoder)
aclStateBuilder := newACLStateBuilder() aclStateBuilder := newACLStateBuilder()
changeBuilder := newACLChangeBuilder() changeBuilder := newACLChangeBuilder()

View File

@ -1,18 +1,15 @@
package tree package tree
type ChangeValidator interface { type DocTreeValidator interface {
ValidateChange(change *Change) error ValidateTree(tree *Tree, aclTree ACLTree) error
} }
type defChangeValidator struct { type docTreeValidator struct{}
aclTree ACLTree
}
func NewDefChangeValidator(aclTree ACLTree) ChangeValidator { func newTreeValidator() DocTreeValidator {
return &defChangeValidator{} return &docTreeValidator{}
} }
func (v *docTreeValidator) ValidateTree(tree *Tree, aclTree ACLTree) error {
func (c *defChangeValidator) ValidateChange(change *Change) error {
// TODO: add validation logic where we check that the change refers to correct acl heads // TODO: add validation logic where we check that the change refers to correct acl heads
// that means that more recent changes should refer to more recent acl heads // that means that more recent changes should refer to more recent acl heads
return nil return nil

View File

@ -12,6 +12,14 @@ type DescriptionParser interface {
ParseChange(*Change) ([]string, error) ParseChange(*Change) ([]string, error)
} }
var NoOpDescriptionParser = noopDescriptionParser{}
type noopDescriptionParser struct{}
func (n noopDescriptionParser) ParseChange(change *Change) ([]string, error) {
return []string{"DOC"}, nil
}
var ACLDescriptionParser = aclDescriptionParser{} var ACLDescriptionParser = aclDescriptionParser{}
type aclDescriptionParser struct{} type aclDescriptionParser struct{}

View File

@ -6,17 +6,25 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"go.uber.org/zap" "go.uber.org/zap"
"sync" "sync"
"time"
) )
type TreeUpdateListener interface {
Update(tree DocTree)
Rebuild(tree DocTree)
}
type DocTree interface { type DocTree interface {
RWLocker RWLocker
ID() string ID() string
Header() *treepb.TreeHeader Header() *treepb.TreeHeader
AddContent(ctx context.Context, content proto.Marshaler) (*aclpb.RawChange, error) AddContent(ctx context.Context, aclTree ACLTree, content proto.Marshaler, isSnapshot bool) (*aclpb.RawChange, error)
AddRawChanges(ctx context.Context, validator ChangeValidator, changes ...*aclpb.RawChange) (AddResult, error) AddRawChanges(ctx context.Context, aclTree ACLTree, changes ...*aclpb.RawChange) (AddResult, error)
Heads() []string Heads() []string
Root() *Change Root() *Change
Iterate(func(change *Change) bool) Iterate(func(change *Change) bool)
@ -41,17 +49,14 @@ type docTree struct {
aclState *ACLState aclState *ACLState
treeBuilder *treeBuilder treeBuilder *treeBuilder
validator DocTreeValidator
sync.RWMutex sync.RWMutex
} }
func BuildDocTreeWithIdentity( func BuildDocTreeWithIdentity(t treestorage.TreeStorage, acc *account.AccountData, listener TreeUpdateListener, aclTree ACLTree) (DocTree, error) {
t treestorage.TreeStorage,
acc *account.AccountData,
listener TreeUpdateListener) (DocTree, error) {
treeBuilder := newTreeBuilder(t, acc.Decoder) treeBuilder := newTreeBuilder(t, acc.Decoder)
aclStateBuilder := newACLStateBuilderWithIdentity(acc.Decoder, acc) validator := newTreeValidator()
changeBuilder := newChangeBuilder()
docTree := &docTree{ docTree := &docTree{
treeStorage: t, treeStorage: t,
@ -59,11 +64,10 @@ func BuildDocTreeWithIdentity(
tree: nil, tree: nil,
aclState: nil, aclState: nil,
treeBuilder: treeBuilder, treeBuilder: treeBuilder,
aclStateBuilder: aclStateBuilder, validator: validator,
changeBuilder: changeBuilder,
updateListener: listener, updateListener: listener,
} }
err := docTree.rebuildFromStorage() err := docTree.rebuildFromStorage(aclTree)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -89,106 +93,155 @@ func BuildDocTreeWithIdentity(
return docTree, nil return docTree, nil
} }
func BuildACLTree(t treestorage.TreeStorage) { func BuildDocTree(t treestorage.TreeStorage, decoder signingkey.PubKeyDecoder, listener TreeUpdateListener, aclTree ACLTree) (DocTree, error) {
// TODO: Add logic for building without identity treeBuilder := newTreeBuilder(t, decoder)
validator := newTreeValidator()
docTree := &docTree{
treeStorage: t,
tree: nil,
aclState: nil,
treeBuilder: treeBuilder,
validator: validator,
updateListener: listener,
}
err := docTree.rebuildFromStorage(aclTree)
if err != nil {
return nil, err
}
err = docTree.removeOrphans()
if err != nil {
return nil, err
}
err = t.SetHeads(docTree.Heads())
if err != nil {
return nil, err
}
docTree.id, err = t.TreeID()
if err != nil {
return nil, err
}
docTree.header, err = t.Header()
if err != nil {
return nil, err
} }
func (a *docTree) removeOrphans() error { listener.Rebuild(docTree)
return docTree, nil
}
func (d *docTree) removeOrphans() error {
// removing attached or invalid orphans // removing attached or invalid orphans
var toRemove []string var toRemove []string
orphans, err := a.treeStorage.Orphans() orphans, err := d.treeStorage.Orphans()
if err != nil { if err != nil {
return err return err
} }
for _, orphan := range orphans { for _, orphan := range orphans {
if _, exists := a.tree.attached[orphan]; exists { if _, exists := d.tree.attached[orphan]; exists {
toRemove = append(toRemove, orphan) toRemove = append(toRemove, orphan)
} }
if _, exists := a.tree.invalidChanges[orphan]; exists { if _, exists := d.tree.invalidChanges[orphan]; exists {
toRemove = append(toRemove, orphan) toRemove = append(toRemove, orphan)
} }
} }
return a.treeStorage.RemoveOrphans(toRemove...) return d.treeStorage.RemoveOrphans(toRemove...)
} }
func (a *docTree) rebuildFromStorage() (err error) { func (d *docTree) rebuildFromStorage(aclTree ACLTree) (err error) {
a.treeBuilder.Init() d.treeBuilder.Init()
a.tree, err = a.treeBuilder.Build(false) d.tree, err = d.treeBuilder.Build(false)
if err != nil { if err != nil {
return err return err
} }
err = a.aclStateBuilder.Init(a.tree) return d.validator.ValidateTree(d.tree, aclTree)
if err != nil {
return err
} }
a.aclState, err = a.aclStateBuilder.Build() func (d *docTree) ID() string {
if err != nil { return d.id
return err
} }
return nil func (d *docTree) Header() *treepb.TreeHeader {
return d.header
} }
func (a *docTree) ID() string { func (d *docTree) Storage() treestorage.TreeStorage {
return a.id return d.treeStorage
} }
func (a *docTree) Header() *treepb.TreeHeader { func (d *docTree) AddContent(ctx context.Context, aclTree ACLTree, content proto.Marshaler, isSnapshot bool) (*aclpb.RawChange, error) {
return a.header if d.accountData == nil {
}
func (a *docTree) ACLState() *ACLState {
return a.aclState
}
func (a *docTree) Storage() treestorage.TreeStorage {
return a.treeStorage
}
func (a *docTree) AddContent(ctx context.Context, build func(builder ChangeBuilder) error) (*aclpb.RawChange, error) {
if a.accountData == nil {
return nil, ErrTreeWithoutIdentity return nil, ErrTreeWithoutIdentity
} }
defer func() { defer func() {
// TODO: should this be called in a separate goroutine to prevent accidental cycles (tree->updater->tree) // TODO: should this be called in a separate goroutine to prevent accidental cycles (tree->updater->tree)
a.updateListener.Update(a) d.updateListener.Update(d)
}() }()
state := aclTree.ACLState()
change := &aclpb.Change{
TreeHeadIds: d.tree.Heads(),
AclHeadIds: aclTree.Heads(),
SnapshotBaseId: d.tree.RootId(),
CurrentReadKeyHash: state.currentReadKeyHash,
Timestamp: int64(time.Now().Nanosecond()),
Identity: d.accountData.Identity,
}
a.changeBuilder.Init(a.aclState, a.tree, a.accountData) marshalledData, err := content.Marshal()
err := build(a.changeBuilder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
encrypted, err := state.userReadKeys[state.currentReadKeyHash].Encrypt(marshalledData)
ch, marshalled, err := a.changeBuilder.BuildAndApply()
if err != nil { if err != nil {
return nil, err return nil, err
} }
a.tree.AddFast(ch) change.ChangesData = encrypted
fullMarshalledChange, err := proto.Marshal(change)
if err != nil {
return nil, err
}
signature, err := d.accountData.SignKey.Sign(fullMarshalledChange)
if err != nil {
return nil, err
}
id, err := cid.NewCIDFromBytes(fullMarshalledChange)
if err != nil {
return nil, err
}
ch := NewChange(id, change)
ch.ParsedModel = content
ch.Sign = signature
if isSnapshot {
// clearing tree, because we already fixed everything in the last snapshot
d.tree = &Tree{}
}
d.tree.AddFast(ch)
rawCh := &aclpb.RawChange{ rawCh := &aclpb.RawChange{
Payload: marshalled, Payload: fullMarshalledChange,
Signature: ch.Signature(), Signature: ch.Signature(),
Id: ch.Id, Id: ch.Id,
} }
err = a.treeStorage.AddRawChange(rawCh) err = d.treeStorage.AddRawChange(rawCh)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = a.treeStorage.SetHeads([]string{ch.Id}) err = d.treeStorage.SetHeads([]string{ch.Id})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return rawCh, nil return rawCh, nil
} }
func (a *docTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawChange) (AddResult, error) { func (d *docTree) AddRawChanges(ctx context.Context, aclTree ACLTree, rawChanges ...*aclpb.RawChange) (AddResult, error) {
// TODO: make proper error handling, because there are a lot of corner cases where this will break // TODO: make proper error handling, because there are a lot of corner cases where this will break
var err error var err error
var mode Mode var mode Mode
@ -208,21 +261,21 @@ func (a *docTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawCha
return return
} }
err = a.removeOrphans() err = d.removeOrphans()
if err != nil { if err != nil {
return return
} }
err = a.treeStorage.SetHeads(a.tree.Heads()) err = d.treeStorage.SetHeads(d.tree.Heads())
if err != nil { if err != nil {
return return
} }
switch mode { switch mode {
case Append: case Append:
a.updateListener.Update(a) d.updateListener.Update(d)
case Rebuild: case Rebuild:
a.updateListener.Rebuild(a) d.updateListener.Rebuild(d)
default: default:
break break
} }
@ -231,28 +284,49 @@ func (a *docTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawCha
getAddedChanges := func() []*aclpb.RawChange { getAddedChanges := func() []*aclpb.RawChange {
var added []*aclpb.RawChange var added []*aclpb.RawChange
for _, ch := range rawChanges { for _, ch := range rawChanges {
if _, exists := a.tree.attached[ch.Id]; exists { if _, exists := d.tree.attached[ch.Id]; exists {
added = append(added, ch) added = append(added, ch)
} }
} }
return added return added
} }
for _, ch := range changes { prevHeads := d.tree.Heads()
err = a.treeStorage.AddChange(ch) rebuild := func() (AddResult, error) {
err = d.rebuildFromStorage(aclTree)
if err != nil { if err != nil {
return AddResult{}, err return AddResult{}, err
} }
err = a.treeStorage.AddOrphans(ch.Id)
return AddResult{
OldHeads: prevHeads,
Heads: d.tree.Heads(),
Added: getAddedChanges(),
Summary: AddResultSummaryRebuild,
}, nil
}
for _, ch := range changes {
err = d.treeStorage.AddChange(ch)
if err != nil {
return AddResult{}, err
}
err = d.treeStorage.AddOrphans(ch.Id)
if err != nil { if err != nil {
return AddResult{}, err return AddResult{}, err
} }
} }
prevHeads := a.tree.Heads() mode = d.tree.Add(changes...)
mode = a.tree.Add(changes...)
switch mode { switch mode {
case Nothing: case Nothing:
for _, ch := range changes {
// rebuilding if the snapshot is different from the root
if ch.SnapshotId != d.tree.RootId() {
return rebuild()
}
}
return AddResult{ return AddResult{
OldHeads: prevHeads, OldHeads: prevHeads,
Heads: prevHeads, Heads: prevHeads,
@ -260,69 +334,59 @@ func (a *docTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawCha
}, nil }, nil
case Rebuild: case Rebuild:
err = a.rebuildFromStorage() return rebuild()
if err != nil {
return AddResult{}, err
}
return AddResult{
OldHeads: prevHeads,
Heads: a.tree.Heads(),
Added: getAddedChanges(),
Summary: AddResultSummaryRebuild,
}, nil
default: default:
// just rebuilding the state from start without reloading everything from tree storage // just rebuilding the state from start without reloading everything from tree storage
// as an optimization we could've started from current heads, but I didn't implement that // as an optimization we could've started from current heads, but I didn't implement that
a.aclState, err = a.aclStateBuilder.Build() err = d.validator.ValidateTree(d.tree, aclTree)
if err != nil { if err != nil {
return AddResult{}, err return AddResult{}, err
} }
return AddResult{ return AddResult{
OldHeads: prevHeads, OldHeads: prevHeads,
Heads: a.tree.Heads(), Heads: d.tree.Heads(),
Added: getAddedChanges(), Added: getAddedChanges(),
Summary: AddResultSummaryAppend, Summary: AddResultSummaryAppend,
}, nil }, nil
} }
} }
func (a *docTree) Iterate(f func(change *Change) bool) { func (d *docTree) Iterate(f func(change *Change) bool) {
a.tree.Iterate(a.tree.RootId(), f) d.tree.Iterate(d.tree.RootId(), f)
} }
func (a *docTree) IterateFrom(s string, f func(change *Change) bool) { func (d *docTree) IterateFrom(s string, f func(change *Change) bool) {
a.tree.Iterate(s, f) d.tree.Iterate(s, f)
} }
func (a *docTree) HasChange(s string) bool { func (d *docTree) HasChange(s string) bool {
_, attachedExists := a.tree.attached[s] _, attachedExists := d.tree.attached[s]
_, unattachedExists := a.tree.unAttached[s] _, unattachedExists := d.tree.unAttached[s]
_, invalidExists := a.tree.invalidChanges[s] _, invalidExists := d.tree.invalidChanges[s]
return attachedExists || unattachedExists || invalidExists return attachedExists || unattachedExists || invalidExists
} }
func (a *docTree) Heads() []string { func (d *docTree) Heads() []string {
return a.tree.Heads() return d.tree.Heads()
} }
func (a *docTree) Root() *Change { func (d *docTree) Root() *Change {
return a.tree.Root() return d.tree.Root()
} }
func (a *docTree) Close() error { func (d *docTree) Close() error {
return nil return nil
} }
func (a *docTree) SnapshotPath() []string { func (d *docTree) SnapshotPath() []string {
// TODO: think about caching this // TODO: think about caching this
var path []string var path []string
// TODO: think that the user may have not all of the snapshots locally // TODO: think that the user may have not all of the snapshots locally
currentSnapshotId := a.tree.RootId() currentSnapshotId := d.tree.RootId()
for currentSnapshotId != "" { for currentSnapshotId != "" {
sn, err := a.treeBuilder.loadChange(currentSnapshotId) sn, err := d.treeBuilder.loadChange(currentSnapshotId)
if err != nil { if err != nil {
break break
} }
@ -332,13 +396,13 @@ func (a *docTree) SnapshotPath() []string {
return path return path
} }
func (a *docTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawChange, error) { func (d *docTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawChange, error) {
// TODO: think about when the clients will have their full acl tree and thus full snapshots // TODO: think about when the clients will have their full acl tree and thus full snapshots
// but no changes after some of the snapshots // but no changes after some of the snapshots
var ( var (
isNewDocument = len(theirPath) == 0 isNewDocument = len(theirPath) == 0
ourPath = a.SnapshotPath() ourPath = d.SnapshotPath()
// by default returning everything we have // by default returning everything we have
commonSnapshot = ourPath[len(ourPath)-1] // TODO: root snapshot, probably it is better to have a specific method in treestorage commonSnapshot = ourPath[len(ourPath)-1] // TODO: root snapshot, probably it is better to have a specific method in treestorage
err error err error
@ -354,12 +418,12 @@ func (a *docTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawCh
var rawChanges []*aclpb.RawChange var rawChanges []*aclpb.RawChange
// using custom load function to skip verification step and save raw changes // using custom load function to skip verification step and save raw changes
load := func(id string) (*Change, error) { load := func(id string) (*Change, error) {
raw, err := a.treeStorage.GetChange(context.Background(), id) raw, err := d.treeStorage.GetChange(context.Background(), id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
aclChange, err := a.treeBuilder.makeUnverifiedACLChange(raw) aclChange, err := d.treeBuilder.makeUnverifiedACLChange(raw)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -370,11 +434,11 @@ func (a *docTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawCh
} }
// we presume that we have everything after the common snapshot, though this may not be the case in case of clients and only ACL tree changes // we presume that we have everything after the common snapshot, though this may not be the case in case of clients and only ACL tree changes
log.With( log.With(
zap.Strings("heads", a.tree.Heads()), zap.Strings("heads", d.tree.Heads()),
zap.String("breakpoint", commonSnapshot), zap.String("breakpoint", commonSnapshot),
zap.String("id", a.id)). zap.String("id", d.id)).
Debug("getting all changes from common snapshot") Debug("getting all changes from common snapshot")
_, err = a.treeBuilder.dfs(a.tree.Heads(), commonSnapshot, load) _, err = d.treeBuilder.dfs(d.tree.Heads(), commonSnapshot, load)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -387,12 +451,12 @@ func (a *docTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawCh
} }
log.With( log.With(
zap.Int("len(changes)", len(rawChanges)), zap.Int("len(changes)", len(rawChanges)),
zap.String("id", a.id)). zap.String("id", d.id)).
Debug("returning all changes after common snapshot") Debug("returning all changes after common snapshot")
return rawChanges, nil return rawChanges, nil
} }
func (a *docTree) DebugDump() (string, error) { func (d *docTree) DebugDump() (string, error) {
return a.tree.Graph(ACLDescriptionParser) return d.tree.Graph(NoOpDescriptionParser)
} }

View File

@ -5,5 +5,11 @@ option go_package = "treepb";
message TreeHeader { message TreeHeader {
string firstChangeId = 1; string firstChangeId = 1;
bool isWorkspace = 2; bool isWorkspace = 2;
TreeType type = 3;
// TODO: add user identity, signature and nano timestamp // TODO: add user identity, signature and nano timestamp
enum TreeType {
ACLTree = 0;
DocTree = 1;
}
} }

View File

@ -22,9 +22,35 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type TreeHeaderTreeType int32
const (
TreeHeader_ACLTree TreeHeaderTreeType = 0
TreeHeader_DocTree TreeHeaderTreeType = 1
)
var TreeHeaderTreeType_name = map[int32]string{
0: "ACLTree",
1: "DocTree",
}
var TreeHeaderTreeType_value = map[string]int32{
"ACLTree": 0,
"DocTree": 1,
}
func (x TreeHeaderTreeType) String() string {
return proto.EnumName(TreeHeaderTreeType_name, int32(x))
}
func (TreeHeaderTreeType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_e7d760b855878644, []int{0, 0}
}
type TreeHeader struct { type TreeHeader struct {
FirstChangeId string `protobuf:"bytes,1,opt,name=firstChangeId,proto3" json:"firstChangeId,omitempty"` FirstChangeId string `protobuf:"bytes,1,opt,name=firstChangeId,proto3" json:"firstChangeId,omitempty"`
IsWorkspace bool `protobuf:"varint,2,opt,name=isWorkspace,proto3" json:"isWorkspace,omitempty"` IsWorkspace bool `protobuf:"varint,2,opt,name=isWorkspace,proto3" json:"isWorkspace,omitempty"`
Type TreeHeaderTreeType `protobuf:"varint,3,opt,name=type,proto3,enum=tree.TreeHeaderTreeType" json:"type,omitempty"`
} }
func (m *TreeHeader) Reset() { *m = TreeHeader{} } func (m *TreeHeader) Reset() { *m = TreeHeader{} }
@ -74,7 +100,15 @@ func (m *TreeHeader) GetIsWorkspace() bool {
return false return false
} }
func (m *TreeHeader) GetType() TreeHeaderTreeType {
if m != nil {
return m.Type
}
return TreeHeader_ACLTree
}
func init() { func init() {
proto.RegisterEnum("tree.TreeHeaderTreeType", TreeHeaderTreeType_name, TreeHeaderTreeType_value)
proto.RegisterType((*TreeHeader)(nil), "tree.TreeHeader") proto.RegisterType((*TreeHeader)(nil), "tree.TreeHeader")
} }
@ -83,18 +117,21 @@ func init() {
} }
var fileDescriptor_e7d760b855878644 = []byte{ var fileDescriptor_e7d760b855878644 = []byte{
// 165 bytes of a gzipped FileDescriptorProto // 220 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0xc8, 0x4e, 0xd7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0xc8, 0x4e, 0xd7,
0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x29, 0x4a, 0x4d, 0x2d, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0x05, 0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x29, 0x4a, 0x4d, 0x2d, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0x05,
0xb3, 0x0b, 0x92, 0xf4, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0x8b, 0xc1, 0x3c, 0x3d, 0x30, 0x5b, 0x88, 0xb3, 0x0b, 0x92, 0xf4, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0x8b, 0xc1, 0x3c, 0x3d, 0x30, 0x5b, 0x88,
0x05, 0xc4, 0x56, 0x0a, 0xe1, 0xe2, 0x0a, 0x29, 0x4a, 0x4d, 0xf5, 0x48, 0x4d, 0x4c, 0x49, 0x2d, 0x05, 0xc4, 0x56, 0x5a, 0xc9, 0xc8, 0xc5, 0x15, 0x52, 0x94, 0x9a, 0xea, 0x91, 0x9a, 0x98, 0x92,
0x12, 0x52, 0xe1, 0xe2, 0x4d, 0xcb, 0x2c, 0x2a, 0x2e, 0x71, 0xce, 0x48, 0xcc, 0x4b, 0x4f, 0xf5, 0x5a, 0x24, 0xa4, 0xc2, 0xc5, 0x9b, 0x96, 0x59, 0x54, 0x5c, 0xe2, 0x9c, 0x91, 0x98, 0x97, 0x9e,
0x4c, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x42, 0x15, 0x14, 0x52, 0xe0, 0xe2, 0xce, 0x2c, 0xea, 0x99, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x19, 0x84, 0x2a, 0x28, 0xa4, 0xc0, 0xc5, 0x9d,
0x0e, 0xcf, 0x2f, 0xca, 0x2e, 0x2e, 0x48, 0x4c, 0x4e, 0x95, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x08, 0x59, 0x1c, 0x9e, 0x5f, 0x94, 0x5d, 0x5c, 0x90, 0x98, 0x9c, 0x2a, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1,
0x42, 0x16, 0x72, 0x52, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x11, 0x84, 0x2c, 0x24, 0xa4, 0xcb, 0xc5, 0x52, 0x52, 0x59, 0x90, 0x2a, 0xc1, 0xac, 0xc0, 0xa8,
0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x36, 0xc1, 0x67, 0x24, 0xa9, 0x07, 0xb6, 0x17, 0x61, 0x0f, 0x98, 0x19, 0x52, 0x59, 0x90, 0x1a, 0x04,
0x88, 0x7b, 0x92, 0xd8, 0xc0, 0x8e, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x09, 0x4f, 0xc6, 0x56, 0xa6, 0xa4, 0xc2, 0xc5, 0x01, 0x13, 0x11, 0xe2, 0xe6, 0x62, 0x77, 0x74, 0xf6, 0x01, 0x71,
0xec, 0xb4, 0x00, 0x00, 0x00, 0x05, 0x18, 0x40, 0x1c, 0x97, 0xfc, 0x64, 0x30, 0x87, 0xd1, 0x49, 0xe1, 0xc4, 0x23, 0x39, 0xc6,
0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39,
0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xd8, 0x20, 0xbe, 0x4c, 0x62, 0x03, 0x7b, 0xcd, 0x18, 0x10,
0x00, 0x00, 0xff, 0xff, 0x72, 0x29, 0xbc, 0x0e, 0x0a, 0x01, 0x00, 0x00,
} }
func (m *TreeHeader) Marshal() (dAtA []byte, err error) { func (m *TreeHeader) Marshal() (dAtA []byte, err error) {
@ -117,6 +154,11 @@ func (m *TreeHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.Type != 0 {
i = encodeVarintTree(dAtA, i, uint64(m.Type))
i--
dAtA[i] = 0x18
}
if m.IsWorkspace { if m.IsWorkspace {
i-- i--
if m.IsWorkspace { if m.IsWorkspace {
@ -161,6 +203,9 @@ func (m *TreeHeader) Size() (n int) {
if m.IsWorkspace { if m.IsWorkspace {
n += 2 n += 2
} }
if m.Type != 0 {
n += 1 + sovTree(uint64(m.Type))
}
return n return n
} }
@ -251,6 +296,25 @@ func (m *TreeHeader) Unmarshal(dAtA []byte) error {
} }
} }
m.IsWorkspace = bool(v != 0) m.IsWorkspace = bool(v != 0)
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTree
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Type |= TreeHeaderTreeType(b&0x7F) << shift
if b < 0x80 {
break
}
}
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTree(dAtA[iNdEx:]) skippy, err := skipTree(dAtA[iNdEx:])