From 4f1767d512214c3eaefcf98431ac1f6479c6c48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Ga=C4=87e=C5=A1a?= Date: Thu, 22 Jun 2023 14:18:23 +0200 Subject: [PATCH] dedicated api to get the last commit info --- cache/redis_cache.go | 89 ++ cmd/gitness/wire_gen.go | 4 +- gitrpc/interface.go | 1 + gitrpc/internal/gitea/gitea.go | 15 +- gitrpc/internal/gitea/last_commit_cache.go | 154 +++ gitrpc/internal/gitea/mapping.go | 17 +- gitrpc/internal/gitea/paths_details.go | 82 ++ gitrpc/internal/gitea/repo_cache.go | 35 + gitrpc/internal/gitea/tree.go | 159 ++- gitrpc/internal/service/commit.go | 10 - gitrpc/internal/service/errors.go | 3 +- gitrpc/internal/service/interface.go | 4 +- gitrpc/internal/service/tree.go | 79 +- gitrpc/internal/types/errors.go | 1 + gitrpc/internal/types/types.go | 6 + gitrpc/proto/repo.proto | 20 +- gitrpc/rpc/repo.pb.go | 1097 ++++++++++------- gitrpc/rpc/repo_grpc.pb.go | 36 + gitrpc/server/config.go | 10 + gitrpc/server/wire.go | 32 +- gitrpc/tree.go | 80 +- .../repo/{get_content.go => content_get.go} | 74 +- .../controller/repo/content_paths_details.go | 70 ++ .../repo/{get_content.go => content_get.go} | 4 +- .../api/handler/repo/content_paths_details.go | 44 + internal/api/openapi/repo.go | 17 + internal/router/api.go | 2 + internal/store/cache/path.go | 24 +- internal/store/cache/wire.go | 2 +- types/repo.go | 4 - .../FolderContent/FolderContent.tsx | 2 +- 31 files changed, 1515 insertions(+), 662 deletions(-) create mode 100644 cache/redis_cache.go create mode 100644 gitrpc/internal/gitea/last_commit_cache.go create mode 100644 gitrpc/internal/gitea/paths_details.go create mode 100644 gitrpc/internal/gitea/repo_cache.go rename internal/api/controller/repo/{get_content.go => content_get.go} (78%) create mode 100644 internal/api/controller/repo/content_paths_details.go rename internal/api/handler/repo/{get_content.go => content_get.go} (93%) create mode 100644 internal/api/handler/repo/content_paths_details.go diff --git a/cache/redis_cache.go b/cache/redis_cache.go new file mode 100644 index 000000000..8f9c154f6 --- /dev/null +++ b/cache/redis_cache.go @@ -0,0 +1,89 @@ +// Copyright 2022 Harness Inc. All rights reserved. +// Use of this source code is governed by the Polyform Free Trial License +// that can be found in the LICENSE.md file for this repository. + +package cache + +import ( + "context" + "fmt" + "time" + + "github.com/go-redis/redis/v8" +) + +type Redis[K any, V any] struct { + client redis.UniversalClient + duration time.Duration + getter Getter[K, V] + keyEncoder func(K) string + codec Codec[V] + countHit int64 + countMiss int64 +} + +type Encoder[V any] interface { + Encode(value V) string +} + +type Decoder[V any] interface { + Decode(encoded string) (V, error) +} + +type Codec[V any] interface { + Encoder[V] + Decoder[V] +} + +func NewRedis[K any, V any]( + client redis.UniversalClient, + getter Getter[K, V], + keyEncoder func(K) string, + codec Codec[V], + duration time.Duration, +) *Redis[K, V] { + return &Redis[K, V]{ + client: client, + duration: duration, + getter: getter, + keyEncoder: keyEncoder, + codec: codec, + countHit: 0, + countMiss: 0, + } +} + +// Stats returns number of cache hits and misses and can be used to monitor the cache efficiency. +func (c *Redis[K, V]) Stats() (int64, int64) { + return c.countHit, c.countMiss +} + +// Get implements the cache.Cache interface. +func (c *Redis[K, V]) Get(ctx context.Context, key K) (V, error) { + var nothing V + + strKey := c.keyEncoder(key) + + raw, err := c.client.Get(ctx, strKey).Result() + if err == nil { + c.countHit++ + return c.codec.Decode(raw) + } + if err != redis.Nil { + return nothing, err + } + + c.countMiss++ + + item, err := c.getter.Find(ctx, key) + if err != nil { + return nothing, fmt.Errorf("cache: failed to find one: %w", err) + } + + err = c.client.Set(ctx, strKey, c.codec.Encode(item), c.duration).Err() + if err != nil { + return nothing, err + } + + return item, nil +} diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index ee8870a0f..27aee0b41 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -147,7 +147,9 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - gitAdapter, err := server3.ProvideGITAdapter() + cacheCache := server3.ProvideGoGitRepoCache() + cache2 := server3.ProvideLastCommitCache(serverConfig, universalClient, cacheCache) + gitAdapter, err := server3.ProvideGITAdapter(cacheCache, cache2) if err != nil { return nil, err } diff --git a/gitrpc/interface.go b/gitrpc/interface.go index 0752d3408..0f1b609a1 100644 --- a/gitrpc/interface.go +++ b/gitrpc/interface.go @@ -23,6 +23,7 @@ type Interface interface { DeleteBranch(ctx context.Context, params *DeleteBranchParams) error ListBranches(ctx context.Context, params *ListBranchesParams) (*ListBranchesOutput, error) GetRef(ctx context.Context, params GetRefParams) (GetRefResponse, error) + PathsDetails(ctx context.Context, params PathsDetailsParams) (PathsDetailsOutput, error) // UpdateRef creates, updates or deletes a git ref. If the OldValue is defined it must match the reference value // prior to the call. To remove a ref use the zero ref as the NewValue. To require the creation of a new one and diff --git a/gitrpc/internal/gitea/gitea.go b/gitrpc/internal/gitea/gitea.go index d41e6a317..4a9a7dc20 100644 --- a/gitrpc/internal/gitea/gitea.go +++ b/gitrpc/internal/gitea/gitea.go @@ -7,14 +7,22 @@ package gitea import ( "context" + "github.com/harness/gitness/cache" + "github.com/harness/gitness/gitrpc/internal/types" + gitea "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" ) type Adapter struct { + repoCache cache.Cache[string, *RepoEntryValue] + lastCommitCache cache.Cache[CommitEntryKey, *types.Commit] } -func New() (Adapter, error) { +func New( + repoCache cache.Cache[string, *RepoEntryValue], + lastCommitCache cache.Cache[CommitEntryKey, *types.Commit], +) (Adapter, error) { // TODO: should be subdir of gitRoot? What is it being used for? setting.Git.HomePath = "home" @@ -23,5 +31,8 @@ func New() (Adapter, error) { return Adapter{}, err } - return Adapter{}, nil + return Adapter{ + repoCache: repoCache, + lastCommitCache: lastCommitCache, + }, nil } diff --git a/gitrpc/internal/gitea/last_commit_cache.go b/gitrpc/internal/gitea/last_commit_cache.go new file mode 100644 index 000000000..23ffea3ba --- /dev/null +++ b/gitrpc/internal/gitea/last_commit_cache.go @@ -0,0 +1,154 @@ +// Copyright 2022 Harness Inc. All rights reserved. +// Use of this source code is governed by the Polyform Free Trial License +// that can be found in the LICENSE.md file for this repository. + +package gitea + +import ( + "context" + "crypto/sha256" + "encoding/gob" + "encoding/hex" + "fmt" + "strings" + "time" + + "github.com/harness/gitness/cache" + "github.com/harness/gitness/gitrpc/internal/types" + + gitea "code.gitea.io/gitea/modules/git" + gogitplumbing "github.com/go-git/go-git/v5/plumbing" + "github.com/go-redis/redis/v8" +) + +func NewInMemoryLastCommitCache( + cacheDuration time.Duration, + repoCache cache.Cache[string, *RepoEntryValue], +) cache.Cache[CommitEntryKey, *types.Commit] { + return cache.New[CommitEntryKey, *types.Commit]( + commitEntryGetter{ + repoCache: repoCache, + }, + cacheDuration) +} + +func NewRedisLastCommitCache( + redisClient redis.UniversalClient, + cacheDuration time.Duration, + repoCache cache.Cache[string, *RepoEntryValue], +) cache.Cache[CommitEntryKey, *types.Commit] { + return cache.NewRedis[CommitEntryKey, *types.Commit]( + redisClient, + commitEntryGetter{ + repoCache: repoCache, + }, + func(key CommitEntryKey) string { + h := sha256.New() + h.Write([]byte(key)) + return "gitrpc:last_commit:" + hex.EncodeToString(h.Sum(nil)) + }, + commitValueCodec{}, + cacheDuration) +} + +type CommitEntryKey string + +const commitEntryKeySeparator = "\x00" + +func makeCommitEntryKey(repoPath, commitSHA, path string) CommitEntryKey { + return CommitEntryKey(repoPath + commitEntryKeySeparator + commitSHA + commitEntryKeySeparator + path) +} + +func (c CommitEntryKey) Split() (repoPath, commitSHA, path string) { + parts := strings.Split(string(c), commitEntryKeySeparator) + if len(parts) != 3 { + return + } + + repoPath = parts[0] + commitSHA = parts[1] + path = parts[2] + + return +} + +type commitValueCodec struct{} + +func (c commitValueCodec) Encode(v *types.Commit) string { + buffer := &strings.Builder{} + _ = gob.NewEncoder(buffer).Encode(v) + return buffer.String() +} + +func (c commitValueCodec) Decode(s string) (*types.Commit, error) { + commit := &types.Commit{} + if err := gob.NewDecoder(strings.NewReader(s)).Decode(commit); err != nil { + return nil, fmt.Errorf("failed to unpack commit entry value: %w", err) + } + + return commit, nil +} + +type commitEntryGetter struct { + repoCache cache.Cache[string, *RepoEntryValue] +} + +// Find implements the cache.Getter interface. +func (c commitEntryGetter) Find(ctx context.Context, key CommitEntryKey) (*types.Commit, error) { + repoPath, rev, path := key.Split() + + if path == "" { + path = "." + } + + args := []string{"log", "--max-count=1", "--format=%H", rev, "--", path} + commitSHA, _, runErr := gitea.NewCommand(ctx, args...).RunStdString(&gitea.RunOpts{Dir: repoPath}) + if runErr != nil { + return nil, fmt.Errorf("failed to run git: %w", runErr) + } + + commitSHA = strings.TrimSpace(commitSHA) + + if commitSHA == "" { + return nil, types.ErrNotFound + } + + repo, err := c.repoCache.Get(ctx, repoPath) + if err != nil { + return nil, fmt.Errorf("failed to get repository %s from cache: %w", repoPath, err) + } + + commit, err := repo.Repo().CommitObject(gogitplumbing.NewHash(commitSHA)) + if err != nil { + return nil, fmt.Errorf("failed to load commit data: %w", err) + } + + var title string + var message string + + title = commit.Message + if idx := strings.IndexRune(commit.Message, '\n'); idx >= 0 { + title = commit.Message[:idx] + message = commit.Message[idx+1:] + } + + return &types.Commit{ + SHA: commitSHA, + Title: title, + Message: message, + Author: types.Signature{ + Identity: types.Identity{ + Name: commit.Author.Name, + Email: commit.Author.Email, + }, + When: commit.Author.When, + }, + Committer: types.Signature{ + Identity: types.Identity{ + Name: commit.Committer.Name, + Email: commit.Committer.Email, + }, + When: commit.Committer.When, + }, + }, nil +} diff --git a/gitrpc/internal/gitea/mapping.go b/gitrpc/internal/gitea/mapping.go index e44d1402b..cb6435c43 100644 --- a/gitrpc/internal/gitea/mapping.go +++ b/gitrpc/internal/gitea/mapping.go @@ -12,6 +12,7 @@ import ( "github.com/harness/gitness/gitrpc/internal/types" gitea "code.gitea.io/gitea/modules/git" + gogitfilemode "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/rs/zerolog/log" ) @@ -132,21 +133,21 @@ func mapGiteaCommit(giteaCommit *gitea.Commit) (*types.Commit, error) { }, nil } -func mapGiteaNodeToTreeNodeModeAndType(giteaMode gitea.EntryMode) (types.TreeNodeType, types.TreeNodeMode, error) { - switch giteaMode { - case gitea.EntryModeBlob: +func mapGogitNodeToTreeNodeModeAndType(gogitMode gogitfilemode.FileMode) (types.TreeNodeType, types.TreeNodeMode, error) { + switch gogitMode { + case gogitfilemode.Regular, gogitfilemode.Deprecated: return types.TreeNodeTypeBlob, types.TreeNodeModeFile, nil - case gitea.EntryModeSymlink: + case gogitfilemode.Symlink: return types.TreeNodeTypeBlob, types.TreeNodeModeSymlink, nil - case gitea.EntryModeExec: + case gogitfilemode.Executable: return types.TreeNodeTypeBlob, types.TreeNodeModeExec, nil - case gitea.EntryModeCommit: + case gogitfilemode.Submodule: return types.TreeNodeTypeCommit, types.TreeNodeModeCommit, nil - case gitea.EntryModeTree: + case gogitfilemode.Dir: return types.TreeNodeTypeTree, types.TreeNodeModeTree, nil default: return types.TreeNodeTypeBlob, types.TreeNodeModeFile, - fmt.Errorf("received unknown tree node mode from gitea: '%s'", giteaMode.String()) + fmt.Errorf("received unknown tree node mode from gogit: '%s'", gogitMode.String()) } } diff --git a/gitrpc/internal/gitea/paths_details.go b/gitrpc/internal/gitea/paths_details.go new file mode 100644 index 000000000..b11e60d86 --- /dev/null +++ b/gitrpc/internal/gitea/paths_details.go @@ -0,0 +1,82 @@ +// Copyright 2022 Harness Inc. All rights reserved. +// Use of this source code is governed by the Polyform Free Trial License +// that can be found in the LICENSE.md file for this repository. + +package gitea + +import ( + "context" + "errors" + "fmt" + + "github.com/harness/gitness/gitrpc/internal/types" + + gogitplumbing "github.com/go-git/go-git/v5/plumbing" + gogitfilemode "github.com/go-git/go-git/v5/plumbing/filemode" + gogitobject "github.com/go-git/go-git/v5/plumbing/object" +) + +// PathsDetails returns additional details about provided the paths. +func (g Adapter) PathsDetails(ctx context.Context, + repoPath string, + rev string, + paths []string, +) ([]types.PathDetails, error) { + repoEntry, err := g.repoCache.Get(ctx, repoPath) + if err != nil { + return nil, fmt.Errorf("failed to open repository: %w", err) + } + + repo := repoEntry.Repo() + + refSHA, err := repo.ResolveRevision(gogitplumbing.Revision(rev)) + if errors.Is(err, gogitplumbing.ErrReferenceNotFound) { + return nil, types.ErrNotFound + } else if err != nil { + return nil, fmt.Errorf("failed to resolve revision %s: %w", rev, err) + } + + refCommit, err := repo.CommitObject(*refSHA) + if err != nil { + return nil, fmt.Errorf("failed to load commit data: %w", err) + } + + tree, err := refCommit.Tree() + if err != nil { + return nil, fmt.Errorf("failed to get tree for the commit: %w", err) + } + + results := make([]types.PathDetails, len(paths)) + + for i, path := range paths { + results[i].Path = path + + if len(path) > 0 { + entry, err := tree.FindEntry(path) + if errors.Is(err, gogitobject.ErrDirectoryNotFound) || errors.Is(err, gogitobject.ErrEntryNotFound) { + return nil, types.ErrPathNotFound + } else if err != nil { + return nil, fmt.Errorf("can't find path entry %s: %w", path, err) + } + + if entry.Mode == gogitfilemode.Regular || entry.Mode == gogitfilemode.Executable { + blobObj, err := repo.Object(gogitplumbing.BlobObject, entry.Hash) + if err != nil { + return nil, fmt.Errorf("failed to get blob object size for the path %s and hash %s: %w", + path, entry.Hash.String(), err) + } + + results[i].Size = blobObj.(*gogitobject.Blob).Size + } + } + + commitEntry, err := g.lastCommitCache.Get(ctx, makeCommitEntryKey(repoPath, refSHA.String(), path)) + if err != nil { + return nil, fmt.Errorf("failed to find last commit for path %s: %w", path, err) + } + + results[i].LastCommit = commitEntry + } + + return results, nil +} diff --git a/gitrpc/internal/gitea/repo_cache.go b/gitrpc/internal/gitea/repo_cache.go new file mode 100644 index 000000000..a9dc1da24 --- /dev/null +++ b/gitrpc/internal/gitea/repo_cache.go @@ -0,0 +1,35 @@ +// Copyright 2022 Harness Inc. All rights reserved. +// Use of this source code is governed by the Polyform Free Trial License +// that can be found in the LICENSE.md file for this repository. + +package gitea + +import ( + "context" + "time" + + "github.com/harness/gitness/cache" + + gogit "github.com/go-git/go-git/v5" +) + +func NewRepoCache() cache.Cache[string, *RepoEntryValue] { + return cache.New[string, *RepoEntryValue](repoGetter{}, 4*time.Hour) +} + +type repoGetter struct{} + +type RepoEntryValue gogit.Repository + +func (repo *RepoEntryValue) Repo() *gogit.Repository { + return (*gogit.Repository)(repo) +} + +func (r repoGetter) Find(_ context.Context, path string) (*RepoEntryValue, error) { + repo, err := gogit.PlainOpen(path) + if err != nil { + return nil, err + } + + return (*RepoEntryValue)(repo), nil +} diff --git a/gitrpc/internal/gitea/tree.go b/gitrpc/internal/gitea/tree.go index e0bbea392..e56514f1c 100644 --- a/gitrpc/internal/gitea/tree.go +++ b/gitrpc/internal/gitea/tree.go @@ -7,6 +7,7 @@ package gitea import ( "bytes" "context" + "errors" "fmt" "io" "path" @@ -16,6 +17,9 @@ import ( "github.com/harness/gitness/gitrpc/internal/types" gitea "code.gitea.io/gitea/modules/git" + gogitplumbing "github.com/go-git/go-git/v5/plumbing" + gogitfilemode "github.com/go-git/go-git/v5/plumbing/filemode" + gogitobject "github.com/go-git/go-git/v5/plumbing/object" ) func cleanTreePath(treePath string) string { @@ -24,30 +28,53 @@ func cleanTreePath(treePath string) string { // GetTreeNode returns the tree node at the given path as found for the provided reference. // Note: ref can be Branch / Tag / CommitSHA. -func (g Adapter) GetTreeNode(ctx context.Context, repoPath string, - ref string, treePath string) (*types.TreeNode, error) { +func (g Adapter) GetTreeNode(ctx context.Context, + repoPath string, + ref string, + treePath string, +) (*types.TreeNode, error) { treePath = cleanTreePath(treePath) - giteaRepo, err := gitea.OpenRepository(ctx, repoPath) + repoEntry, err := g.repoCache.Get(ctx, repoPath) if err != nil { return nil, processGiteaErrorf(err, "failed to open repository") } - defer giteaRepo.Close() - // Get the giteaCommit object for the ref - giteaCommit, err := giteaRepo.GetCommit(ref) - if err != nil { - return nil, processGiteaErrorf(err, "error getting commit for ref '%s'", ref) + repo := repoEntry.Repo() + + refSHA, err := repo.ResolveRevision(gogitplumbing.Revision(ref)) + if errors.Is(err, gogitplumbing.ErrReferenceNotFound) { + return nil, types.ErrNotFound + } else if err != nil { + return nil, fmt.Errorf("failed to resolve revision %s: %w", ref, err) } - // TODO: handle ErrNotExist :) - giteaTreeEntry, err := giteaCommit.GetTreeEntryByPath(treePath) + refCommit, err := repo.CommitObject(*refSHA) if err != nil { - return nil, processGiteaErrorf(err, "failed to get tree entry for commit '%s' at path '%s'", - giteaCommit.ID.String(), treePath) + return nil, fmt.Errorf("failed to load commit data: %w", err) } - nodeType, mode, err := mapGiteaNodeToTreeNodeModeAndType(giteaTreeEntry.Mode()) + rootEntry := gogitobject.TreeEntry{ + Name: "", + Mode: gogitfilemode.Dir, + Hash: refCommit.TreeHash, + } + + treeEntry := &rootEntry + + if len(treePath) > 0 { + tree, err := refCommit.Tree() + if err != nil { + return nil, fmt.Errorf("failed to get tree for the commit: %w", err) + } + + treeEntry, err = tree.FindEntry(treePath) + if err != nil { + return nil, fmt.Errorf("can't find path entry %s: %w", treePath, types.ErrPathNotFound) + } + } + + nodeType, mode, err := mapGogitNodeToTreeNodeModeAndType(treeEntry.Mode) if err != nil { return nil, err } @@ -55,106 +82,74 @@ func (g Adapter) GetTreeNode(ctx context.Context, repoPath string, return &types.TreeNode{ Mode: mode, NodeType: nodeType, - Sha: giteaTreeEntry.ID.String(), - Name: giteaTreeEntry.Name(), + Sha: treeEntry.Hash.String(), + Name: treeEntry.Name, Path: treePath, }, nil } // ListTreeNodes lists the child nodes of a tree reachable from ref via the specified path // and includes the latest commit for all nodes if requested. -// IMPORTANT: recursive and includeLatestCommit can't be used together. // Note: ref can be Branch / Tag / CommitSHA. // //nolint:gocognit // refactor if needed -func (g Adapter) ListTreeNodes(ctx context.Context, repoPath string, - ref string, treePath string, recursive bool, includeLatestCommit bool) ([]types.TreeNodeWithCommit, error) { - if recursive && includeLatestCommit { - // To avoid potential performance catastrophe, block recursive with includeLatestCommit - // TODO: this should return bad error to caller if needed? - // TODO: should this be refactored in two methods? - return nil, fmt.Errorf("latest commit with recursive query is not supported") - } - +func (g Adapter) ListTreeNodes(ctx context.Context, + repoPath string, + ref string, + treePath string, +) ([]types.TreeNode, error) { treePath = cleanTreePath(treePath) - giteaRepo, err := gitea.OpenRepository(ctx, repoPath) + repoEntry, err := g.repoCache.Get(ctx, repoPath) if err != nil { return nil, processGiteaErrorf(err, "failed to open repository") } - defer giteaRepo.Close() - // Get the giteaCommit object for the ref - giteaCommit, err := giteaRepo.GetCommit(ref) + repo := repoEntry.Repo() + + refSHA, err := repo.ResolveRevision(gogitplumbing.Revision(ref)) + if errors.Is(err, gogitplumbing.ErrReferenceNotFound) { + return nil, types.ErrNotFound + } else if err != nil { + return nil, fmt.Errorf("failed to resolve revision %s: %w", ref, err) + } + + refCommit, err := repo.CommitObject(*refSHA) if err != nil { - return nil, processGiteaErrorf(err, "error getting commit for ref '%s'", ref) + return nil, fmt.Errorf("failed to load commit data: %w", err) } - // Get the giteaTree object for the ref - giteaTree, err := giteaCommit.SubTree(treePath) + tree, err := refCommit.Tree() if err != nil { - return nil, processGiteaErrorf(err, "error getting tree for '%s'", treePath) + return nil, fmt.Errorf("failed to get tree for the commit: %w", err) } - var giteaEntries gitea.Entries - if recursive { - giteaEntries, err = giteaTree.ListEntriesRecursive() - } else { - giteaEntries, err = giteaTree.ListEntries() - } - if err != nil { - return nil, processGiteaErrorf(err, "failed to list entries for tree '%s'", treePath) - } - - var latestCommits []gitea.CommitInfo - if includeLatestCommit { - // TODO: can be speed up with latestCommitCache (currently nil) - latestCommits, _, err = giteaEntries.GetCommitsInfo(ctx, giteaCommit, treePath, nil) - if err != nil { - return nil, processGiteaErrorf(err, "failed to get latest commits for entries") - } - - if len(latestCommits) != len(giteaEntries) { - return nil, fmt.Errorf("latest commit info doesn't match tree node info - count differs") + if len(treePath) > 0 { + tree, err = tree.Tree(treePath) + if errors.Is(err, gogitobject.ErrDirectoryNotFound) || errors.Is(err, gogitobject.ErrEntryNotFound) { + return nil, types.ErrPathNotFound + } else if err != nil { + return nil, fmt.Errorf("can't find path entry %s: %w", treePath, err) } } - nodes := make([]types.TreeNodeWithCommit, len(giteaEntries)) - for i := range giteaEntries { - giteaEntry := giteaEntries[i] - - var nodeType types.TreeNodeType - var mode types.TreeNodeMode - nodeType, mode, err = mapGiteaNodeToTreeNodeModeAndType(giteaEntry.Mode()) + treeNodes := make([]types.TreeNode, len(tree.Entries)) + for i, treeEntry := range tree.Entries { + nodeType, mode, err := mapGogitNodeToTreeNodeModeAndType(treeEntry.Mode) if err != nil { return nil, err } - // giteaNode.Name() returns the path of the node relative to the tree. - relPath := giteaEntry.Name() - name := filepath.Base(relPath) - - var commit *types.Commit - if includeLatestCommit { - commit, err = mapGiteaCommit(latestCommits[i].Commit) - if err != nil { - return nil, err - } - } - - nodes[i] = types.TreeNodeWithCommit{ - TreeNode: types.TreeNode{ - NodeType: nodeType, - Mode: mode, - Sha: giteaEntry.ID.String(), - Name: name, - Path: filepath.Join(treePath, relPath), - }, - Commit: commit, + treeNodes[i] = types.TreeNode{ + NodeType: nodeType, + Mode: mode, + Sha: treeEntry.Hash.String(), + Name: treeEntry.Name, + Path: filepath.Join(treePath, treeEntry.Name), } } - return nodes, nil + return treeNodes, nil } func (g Adapter) ReadTree(ctx context.Context, repoPath, ref string, w io.Writer, args ...string) error { diff --git a/gitrpc/internal/service/commit.go b/gitrpc/internal/service/commit.go index 6a5e96aba..e467dfafe 100644 --- a/gitrpc/internal/service/commit.go +++ b/gitrpc/internal/service/commit.go @@ -86,16 +86,6 @@ func (s RepositoryService) ListCommits(request *rpc.ListCommitsRequest, return nil } -func (s RepositoryService) getLatestCommit(ctx context.Context, repoPath string, - ref string, path string) (*rpc.Commit, error) { - gitCommit, err := s.adapter.GetLatestCommit(ctx, repoPath, ref, path) - if err != nil { - return nil, processGitErrorf(err, "failed to get latest commit") - } - - return mapGitCommit(gitCommit) -} - func (s RepositoryService) GetCommitDivergences(ctx context.Context, request *rpc.GetCommitDivergencesRequest) (*rpc.GetCommitDivergencesResponse, error) { base := request.GetBase() diff --git a/gitrpc/internal/service/errors.go b/gitrpc/internal/service/errors.go index 27c3097f9..5c05c1df9 100644 --- a/gitrpc/internal/service/errors.go +++ b/gitrpc/internal/service/errors.go @@ -199,7 +199,8 @@ func processGitErrorf(err error, format string, args ...interface{}) error { switch { case errors.Is(err, types.ErrNotFound), errors.Is(err, types.ErrSHADoesNotMatch), - errors.Is(err, types.ErrHunkNotFound): + errors.Is(err, types.ErrHunkNotFound), + errors.Is(err, types.ErrPathNotFound): return ErrNotFoundf(format, args...) case errors.Is(err, types.ErrAlreadyExists): return ErrAlreadyExistsf(format, args...) diff --git a/gitrpc/internal/service/interface.go b/gitrpc/internal/service/interface.go index da0bf7723..255ab68b9 100644 --- a/gitrpc/internal/service/interface.go +++ b/gitrpc/internal/service/interface.go @@ -25,8 +25,8 @@ type GitAdapter interface { Push(ctx context.Context, repoPath string, opts types.PushOptions) error ReadTree(ctx context.Context, repoPath, ref string, w io.Writer, args ...string) error GetTreeNode(ctx context.Context, repoPath string, ref string, treePath string) (*types.TreeNode, error) - ListTreeNodes(ctx context.Context, repoPath string, ref string, treePath string, - recursive bool, includeLatestCommit bool) ([]types.TreeNodeWithCommit, error) + ListTreeNodes(ctx context.Context, repoPath string, ref string, treePath string) ([]types.TreeNode, error) + PathsDetails(ctx context.Context, repoPath string, ref string, paths []string) ([]types.PathDetails, error) GetSubmodule(ctx context.Context, repoPath string, ref string, treePath string) (*types.Submodule, error) GetBlob(ctx context.Context, repoPath string, sha string, sizeLimit int64) (*types.BlobReader, error) WalkReferences(ctx context.Context, repoPath string, handler types.WalkReferencesHandler, diff --git a/gitrpc/internal/service/tree.go b/gitrpc/internal/service/tree.go index 0ec534057..fc4dccccc 100644 --- a/gitrpc/internal/service/tree.go +++ b/gitrpc/internal/service/tree.go @@ -6,6 +6,7 @@ package service import ( "context" + "fmt" "github.com/harness/gitness/gitrpc/internal/types" "github.com/harness/gitness/gitrpc/rpc" @@ -15,8 +16,10 @@ import ( "google.golang.org/grpc/status" ) -func (s RepositoryService) ListTreeNodes(request *rpc.ListTreeNodesRequest, - stream rpc.RepositoryService_ListTreeNodesServer) error { +func (s RepositoryService) ListTreeNodes( + request *rpc.ListTreeNodesRequest, + stream rpc.RepositoryService_ListTreeNodesServer, +) error { ctx := stream.Context() base := request.GetBase() if base == nil { @@ -26,7 +29,7 @@ func (s RepositoryService) ListTreeNodes(request *rpc.ListTreeNodesRequest, repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid()) gitNodes, err := s.adapter.ListTreeNodes(ctx, repoPath, - request.GetGitRef(), request.GetPath(), request.GetRecursive(), request.GetIncludeLatestCommit()) + request.GetGitRef(), request.GetPath()) if err != nil { return processGitErrorf(err, "failed to list tree nodes") } @@ -34,14 +37,6 @@ func (s RepositoryService) ListTreeNodes(request *rpc.ListTreeNodesRequest, log.Ctx(ctx).Trace().Msgf("git adapter returned %d nodes", len(gitNodes)) for _, gitNode := range gitNodes { - var commit *rpc.Commit - if request.GetIncludeLatestCommit() { - commit, err = mapGitCommit(gitNode.Commit) - if err != nil { - return status.Errorf(codes.Internal, "failed to map git commit: %v", err) - } - } - err = stream.Send(&rpc.ListTreeNodesResponse{ Node: &rpc.TreeNode{ Type: mapGitNodeType(gitNode.NodeType), @@ -50,7 +45,6 @@ func (s RepositoryService) ListTreeNodes(request *rpc.ListTreeNodesRequest, Name: gitNode.Name, Path: gitNode.Path, }, - Commit: commit, }) if err != nil { return status.Errorf(codes.Internal, "failed to send node: %v", err) @@ -61,15 +55,16 @@ func (s RepositoryService) ListTreeNodes(request *rpc.ListTreeNodesRequest, } func (s RepositoryService) GetTreeNode(ctx context.Context, - request *rpc.GetTreeNodeRequest) (*rpc.GetTreeNodeResponse, error) { + request *rpc.GetTreeNodeRequest, +) (*rpc.GetTreeNodeResponse, error) { base := request.GetBase() if base == nil { return nil, types.ErrBaseCannotBeEmpty } repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid()) - // TODO: do we need to validate request for nil? - gitNode, err := s.adapter.GetTreeNode(ctx, repoPath, request.GetGitRef(), request.GetPath()) + + gitNode, err := s.adapter.GetTreeNode(ctx, repoPath, request.GitRef, request.Path) if err != nil { return nil, processGitErrorf(err, "no such path '%s' in '%s'", request.Path, request.GetGitRef()) } @@ -84,15 +79,61 @@ func (s RepositoryService) GetTreeNode(ctx context.Context, }, } - // TODO: improve performance, could be done in lower layer? if request.GetIncludeLatestCommit() { - var commit *rpc.Commit - commit, err = s.getLatestCommit(ctx, repoPath, request.GetGitRef(), request.GetPath()) + pathDetails, err := s.adapter.PathsDetails(ctx, repoPath, request.GitRef, []string{request.Path}) if err != nil { return nil, err } - res.Commit = commit + + if len(pathDetails) != 1 { + return nil, fmt.Errorf("failed to get details for the path %s", request.Path) + } + + if pathDetails[0].LastCommit != nil { + res.Commit, err = mapGitCommit(pathDetails[0].LastCommit) + if err != nil { + return nil, err + } + } } return res, nil } + +func (s RepositoryService) PathsDetails(ctx context.Context, + request *rpc.PathsDetailsRequest, +) (*rpc.PathsDetailsResponse, error) { + base := request.GetBase() + if base == nil { + return nil, types.ErrBaseCannotBeEmpty + } + + repoPath := getFullPathForRepo(s.reposRoot, base.GetRepoUid()) + + pathsDetails, err := s.adapter.PathsDetails(ctx, repoPath, request.GetGitRef(), request.GetPaths()) + if err != nil { + return nil, processGitErrorf(err, "failed to get path details in '%s'", request.GetGitRef()) + } + + details := make([]*rpc.PathDetails, len(pathsDetails)) + for i, pathDetails := range pathsDetails { + var lastCommit *rpc.Commit + + if pathDetails.LastCommit != nil { + lastCommit, err = mapGitCommit(pathDetails.LastCommit) + if err != nil { + return nil, fmt.Errorf("failed to map commit: %w", err) + } + } + + details[i] = &rpc.PathDetails{ + Path: pathDetails.Path, + LastCommit: lastCommit, + Size: pathDetails.Size, + } + } + + return &rpc.PathsDetailsResponse{ + PathDetails: details, + }, nil +} diff --git a/gitrpc/internal/types/errors.go b/gitrpc/internal/types/errors.go index fb8b6cd29..27161c883 100644 --- a/gitrpc/internal/types/errors.go +++ b/gitrpc/internal/types/errors.go @@ -15,6 +15,7 @@ var ( ErrAlreadyExists = errors.New("already exists") ErrInvalidArgument = errors.New("invalid argument") ErrNotFound = errors.New("not found") + ErrPathNotFound = errors.New("path not found") ErrInvalidPath = errors.New("path is invalid") ErrUndefinedAction = errors.New("undefined action") ErrActionNotAllowedOnEmptyRepo = errors.New("action not allowed on empty repository") diff --git a/gitrpc/internal/types/types.go b/gitrpc/internal/types/types.go index 0d9cff775..5bb7964c1 100644 --- a/gitrpc/internal/types/types.go +++ b/gitrpc/internal/types/types.go @@ -320,3 +320,9 @@ type TempRepository struct { BaseSHA string HeadSHA string } + +type PathDetails struct { + Path string + LastCommit *Commit + Size int64 +} diff --git a/gitrpc/proto/repo.proto b/gitrpc/proto/repo.proto index c0c819c4c..d24861a38 100644 --- a/gitrpc/proto/repo.proto +++ b/gitrpc/proto/repo.proto @@ -10,6 +10,7 @@ service RepositoryService { rpc CreateRepository(stream CreateRepositoryRequest) returns (CreateRepositoryResponse); rpc GetTreeNode(GetTreeNodeRequest) returns (GetTreeNodeResponse); rpc ListTreeNodes(ListTreeNodesRequest) returns (stream ListTreeNodesResponse); + rpc PathsDetails(PathsDetailsRequest) returns (PathsDetailsResponse); rpc GetSubmodule(GetSubmoduleRequest) returns (GetSubmoduleResponse); rpc GetBlob(GetBlobRequest) returns (stream GetBlobResponse); rpc ListCommits(ListCommitsRequest) returns (stream ListCommitsResponse); @@ -55,13 +56,10 @@ message ListTreeNodesRequest { ReadRequest base = 1; string git_ref = 2; string path = 3; - bool include_latest_commit = 4; - bool recursive = 5; } message ListTreeNodesResponse { TreeNode node = 1; - Commit commit = 2; } message TreeNode { @@ -86,6 +84,22 @@ enum TreeNodeMode { TreeNodeModeCommit = 4; } +message PathsDetailsRequest { + ReadRequest base = 1; + string git_ref = 2; + repeated string paths = 3; +} + +message PathsDetailsResponse { + repeated PathDetails path_details = 1; +} + +message PathDetails { + string path = 1; + Commit last_commit = 2; + int64 size = 3; +} + message GetCommitRequest { ReadRequest base = 1; string sha = 2; diff --git a/gitrpc/rpc/repo.pb.go b/gitrpc/rpc/repo.pb.go index 5c9f42d3e..ba0029a59 100644 --- a/gitrpc/rpc/repo.pb.go +++ b/gitrpc/rpc/repo.pb.go @@ -547,11 +547,9 @@ type ListTreeNodesRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Base *ReadRequest `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` - GitRef string `protobuf:"bytes,2,opt,name=git_ref,json=gitRef,proto3" json:"git_ref,omitempty"` - Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` - IncludeLatestCommit bool `protobuf:"varint,4,opt,name=include_latest_commit,json=includeLatestCommit,proto3" json:"include_latest_commit,omitempty"` - Recursive bool `protobuf:"varint,5,opt,name=recursive,proto3" json:"recursive,omitempty"` + Base *ReadRequest `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + GitRef string `protobuf:"bytes,2,opt,name=git_ref,json=gitRef,proto3" json:"git_ref,omitempty"` + Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` } func (x *ListTreeNodesRequest) Reset() { @@ -607,27 +605,12 @@ func (x *ListTreeNodesRequest) GetPath() string { return "" } -func (x *ListTreeNodesRequest) GetIncludeLatestCommit() bool { - if x != nil { - return x.IncludeLatestCommit - } - return false -} - -func (x *ListTreeNodesRequest) GetRecursive() bool { - if x != nil { - return x.Recursive - } - return false -} - type ListTreeNodesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Node *TreeNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` - Commit *Commit `protobuf:"bytes,2,opt,name=commit,proto3" json:"commit,omitempty"` + Node *TreeNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` } func (x *ListTreeNodesResponse) Reset() { @@ -669,13 +652,6 @@ func (x *ListTreeNodesResponse) GetNode() *TreeNode { return nil } -func (x *ListTreeNodesResponse) GetCommit() *Commit { - if x != nil { - return x.Commit - } - return nil -} - type TreeNode struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -755,6 +731,179 @@ func (x *TreeNode) GetPath() string { return "" } +type PathsDetailsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Base *ReadRequest `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"` + GitRef string `protobuf:"bytes,2,opt,name=git_ref,json=gitRef,proto3" json:"git_ref,omitempty"` + Paths []string `protobuf:"bytes,3,rep,name=paths,proto3" json:"paths,omitempty"` +} + +func (x *PathsDetailsRequest) Reset() { + *x = PathsDetailsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_repo_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PathsDetailsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PathsDetailsRequest) ProtoMessage() {} + +func (x *PathsDetailsRequest) ProtoReflect() protoreflect.Message { + mi := &file_repo_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PathsDetailsRequest.ProtoReflect.Descriptor instead. +func (*PathsDetailsRequest) Descriptor() ([]byte, []int) { + return file_repo_proto_rawDescGZIP(), []int{8} +} + +func (x *PathsDetailsRequest) GetBase() *ReadRequest { + if x != nil { + return x.Base + } + return nil +} + +func (x *PathsDetailsRequest) GetGitRef() string { + if x != nil { + return x.GitRef + } + return "" +} + +func (x *PathsDetailsRequest) GetPaths() []string { + if x != nil { + return x.Paths + } + return nil +} + +type PathsDetailsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PathDetails []*PathDetails `protobuf:"bytes,1,rep,name=path_details,json=pathDetails,proto3" json:"path_details,omitempty"` +} + +func (x *PathsDetailsResponse) Reset() { + *x = PathsDetailsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_repo_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PathsDetailsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PathsDetailsResponse) ProtoMessage() {} + +func (x *PathsDetailsResponse) ProtoReflect() protoreflect.Message { + mi := &file_repo_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PathsDetailsResponse.ProtoReflect.Descriptor instead. +func (*PathsDetailsResponse) Descriptor() ([]byte, []int) { + return file_repo_proto_rawDescGZIP(), []int{9} +} + +func (x *PathsDetailsResponse) GetPathDetails() []*PathDetails { + if x != nil { + return x.PathDetails + } + return nil +} + +type PathDetails struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + LastCommit *Commit `protobuf:"bytes,2,opt,name=last_commit,json=lastCommit,proto3" json:"last_commit,omitempty"` + Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"` +} + +func (x *PathDetails) Reset() { + *x = PathDetails{} + if protoimpl.UnsafeEnabled { + mi := &file_repo_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PathDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PathDetails) ProtoMessage() {} + +func (x *PathDetails) ProtoReflect() protoreflect.Message { + mi := &file_repo_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PathDetails.ProtoReflect.Descriptor instead. +func (*PathDetails) Descriptor() ([]byte, []int) { + return file_repo_proto_rawDescGZIP(), []int{10} +} + +func (x *PathDetails) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *PathDetails) GetLastCommit() *Commit { + if x != nil { + return x.LastCommit + } + return nil +} + +func (x *PathDetails) GetSize() int64 { + if x != nil { + return x.Size + } + return 0 +} + type GetCommitRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -767,7 +916,7 @@ type GetCommitRequest struct { func (x *GetCommitRequest) Reset() { *x = GetCommitRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[8] + mi := &file_repo_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -780,7 +929,7 @@ func (x *GetCommitRequest) String() string { func (*GetCommitRequest) ProtoMessage() {} func (x *GetCommitRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[8] + mi := &file_repo_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -793,7 +942,7 @@ func (x *GetCommitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCommitRequest.ProtoReflect.Descriptor instead. func (*GetCommitRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{8} + return file_repo_proto_rawDescGZIP(), []int{11} } func (x *GetCommitRequest) GetBase() *ReadRequest { @@ -821,7 +970,7 @@ type GetCommitResponse struct { func (x *GetCommitResponse) Reset() { *x = GetCommitResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[9] + mi := &file_repo_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -834,7 +983,7 @@ func (x *GetCommitResponse) String() string { func (*GetCommitResponse) ProtoMessage() {} func (x *GetCommitResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[9] + mi := &file_repo_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -847,7 +996,7 @@ func (x *GetCommitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCommitResponse.ProtoReflect.Descriptor instead. func (*GetCommitResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{9} + return file_repo_proto_rawDescGZIP(), []int{12} } func (x *GetCommitResponse) GetCommit() *Commit { @@ -876,7 +1025,7 @@ type ListCommitsRequest struct { func (x *ListCommitsRequest) Reset() { *x = ListCommitsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[10] + mi := &file_repo_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -889,7 +1038,7 @@ func (x *ListCommitsRequest) String() string { func (*ListCommitsRequest) ProtoMessage() {} func (x *ListCommitsRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[10] + mi := &file_repo_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -902,7 +1051,7 @@ func (x *ListCommitsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCommitsRequest.ProtoReflect.Descriptor instead. func (*ListCommitsRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{10} + return file_repo_proto_rawDescGZIP(), []int{13} } func (x *ListCommitsRequest) GetBase() *ReadRequest { @@ -980,7 +1129,7 @@ type ListCommitsResponse struct { func (x *ListCommitsResponse) Reset() { *x = ListCommitsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[11] + mi := &file_repo_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -993,7 +1142,7 @@ func (x *ListCommitsResponse) String() string { func (*ListCommitsResponse) ProtoMessage() {} func (x *ListCommitsResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[11] + mi := &file_repo_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1006,7 +1155,7 @@ func (x *ListCommitsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCommitsResponse.ProtoReflect.Descriptor instead. func (*ListCommitsResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{11} + return file_repo_proto_rawDescGZIP(), []int{14} } func (x *ListCommitsResponse) GetCommit() *Commit { @@ -1037,7 +1186,7 @@ type RenameDetails struct { func (x *RenameDetails) Reset() { *x = RenameDetails{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[12] + mi := &file_repo_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1050,7 +1199,7 @@ func (x *RenameDetails) String() string { func (*RenameDetails) ProtoMessage() {} func (x *RenameDetails) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[12] + mi := &file_repo_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1063,7 +1212,7 @@ func (x *RenameDetails) ProtoReflect() protoreflect.Message { // Deprecated: Use RenameDetails.ProtoReflect.Descriptor instead. func (*RenameDetails) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{12} + return file_repo_proto_rawDescGZIP(), []int{15} } func (x *RenameDetails) GetOldPath() string { @@ -1107,7 +1256,7 @@ type GetBlobRequest struct { func (x *GetBlobRequest) Reset() { *x = GetBlobRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[13] + mi := &file_repo_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1120,7 +1269,7 @@ func (x *GetBlobRequest) String() string { func (*GetBlobRequest) ProtoMessage() {} func (x *GetBlobRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[13] + mi := &file_repo_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1133,7 +1282,7 @@ func (x *GetBlobRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBlobRequest.ProtoReflect.Descriptor instead. func (*GetBlobRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{13} + return file_repo_proto_rawDescGZIP(), []int{16} } func (x *GetBlobRequest) GetBase() *ReadRequest { @@ -1172,7 +1321,7 @@ type GetBlobResponse struct { func (x *GetBlobResponse) Reset() { *x = GetBlobResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[14] + mi := &file_repo_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1185,7 +1334,7 @@ func (x *GetBlobResponse) String() string { func (*GetBlobResponse) ProtoMessage() {} func (x *GetBlobResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[14] + mi := &file_repo_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1198,7 +1347,7 @@ func (x *GetBlobResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBlobResponse.ProtoReflect.Descriptor instead. func (*GetBlobResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{14} + return file_repo_proto_rawDescGZIP(), []int{17} } func (m *GetBlobResponse) GetData() isGetBlobResponse_Data { @@ -1251,7 +1400,7 @@ type GetBlobResponseHeader struct { func (x *GetBlobResponseHeader) Reset() { *x = GetBlobResponseHeader{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[15] + mi := &file_repo_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1264,7 +1413,7 @@ func (x *GetBlobResponseHeader) String() string { func (*GetBlobResponseHeader) ProtoMessage() {} func (x *GetBlobResponseHeader) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[15] + mi := &file_repo_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1277,7 +1426,7 @@ func (x *GetBlobResponseHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBlobResponseHeader.ProtoReflect.Descriptor instead. func (*GetBlobResponseHeader) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{15} + return file_repo_proto_rawDescGZIP(), []int{18} } func (x *GetBlobResponseHeader) GetSha() string { @@ -1314,7 +1463,7 @@ type GetSubmoduleRequest struct { func (x *GetSubmoduleRequest) Reset() { *x = GetSubmoduleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[16] + mi := &file_repo_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1327,7 +1476,7 @@ func (x *GetSubmoduleRequest) String() string { func (*GetSubmoduleRequest) ProtoMessage() {} func (x *GetSubmoduleRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[16] + mi := &file_repo_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1340,7 +1489,7 @@ func (x *GetSubmoduleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSubmoduleRequest.ProtoReflect.Descriptor instead. func (*GetSubmoduleRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{16} + return file_repo_proto_rawDescGZIP(), []int{19} } func (x *GetSubmoduleRequest) GetBase() *ReadRequest { @@ -1375,7 +1524,7 @@ type GetSubmoduleResponse struct { func (x *GetSubmoduleResponse) Reset() { *x = GetSubmoduleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[17] + mi := &file_repo_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1388,7 +1537,7 @@ func (x *GetSubmoduleResponse) String() string { func (*GetSubmoduleResponse) ProtoMessage() {} func (x *GetSubmoduleResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[17] + mi := &file_repo_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1401,7 +1550,7 @@ func (x *GetSubmoduleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSubmoduleResponse.ProtoReflect.Descriptor instead. func (*GetSubmoduleResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{17} + return file_repo_proto_rawDescGZIP(), []int{20} } func (x *GetSubmoduleResponse) GetSubmodule() *Submodule { @@ -1423,7 +1572,7 @@ type Submodule struct { func (x *Submodule) Reset() { *x = Submodule{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[18] + mi := &file_repo_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1436,7 +1585,7 @@ func (x *Submodule) String() string { func (*Submodule) ProtoMessage() {} func (x *Submodule) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[18] + mi := &file_repo_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1449,7 +1598,7 @@ func (x *Submodule) ProtoReflect() protoreflect.Message { // Deprecated: Use Submodule.ProtoReflect.Descriptor instead. func (*Submodule) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{18} + return file_repo_proto_rawDescGZIP(), []int{21} } func (x *Submodule) GetName() string { @@ -1479,7 +1628,7 @@ type GetCommitDivergencesRequest struct { func (x *GetCommitDivergencesRequest) Reset() { *x = GetCommitDivergencesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[19] + mi := &file_repo_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1492,7 +1641,7 @@ func (x *GetCommitDivergencesRequest) String() string { func (*GetCommitDivergencesRequest) ProtoMessage() {} func (x *GetCommitDivergencesRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[19] + mi := &file_repo_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1505,7 +1654,7 @@ func (x *GetCommitDivergencesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCommitDivergencesRequest.ProtoReflect.Descriptor instead. func (*GetCommitDivergencesRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{19} + return file_repo_proto_rawDescGZIP(), []int{22} } func (x *GetCommitDivergencesRequest) GetBase() *ReadRequest { @@ -1541,7 +1690,7 @@ type CommitDivergenceRequest struct { func (x *CommitDivergenceRequest) Reset() { *x = CommitDivergenceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[20] + mi := &file_repo_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1554,7 +1703,7 @@ func (x *CommitDivergenceRequest) String() string { func (*CommitDivergenceRequest) ProtoMessage() {} func (x *CommitDivergenceRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[20] + mi := &file_repo_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1567,7 +1716,7 @@ func (x *CommitDivergenceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CommitDivergenceRequest.ProtoReflect.Descriptor instead. func (*CommitDivergenceRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{20} + return file_repo_proto_rawDescGZIP(), []int{23} } func (x *CommitDivergenceRequest) GetFrom() string { @@ -1595,7 +1744,7 @@ type GetCommitDivergencesResponse struct { func (x *GetCommitDivergencesResponse) Reset() { *x = GetCommitDivergencesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[21] + mi := &file_repo_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1608,7 +1757,7 @@ func (x *GetCommitDivergencesResponse) String() string { func (*GetCommitDivergencesResponse) ProtoMessage() {} func (x *GetCommitDivergencesResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[21] + mi := &file_repo_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1621,7 +1770,7 @@ func (x *GetCommitDivergencesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCommitDivergencesResponse.ProtoReflect.Descriptor instead. func (*GetCommitDivergencesResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{21} + return file_repo_proto_rawDescGZIP(), []int{24} } func (x *GetCommitDivergencesResponse) GetDivergences() []*CommitDivergence { @@ -1643,7 +1792,7 @@ type CommitDivergence struct { func (x *CommitDivergence) Reset() { *x = CommitDivergence{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[22] + mi := &file_repo_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1656,7 +1805,7 @@ func (x *CommitDivergence) String() string { func (*CommitDivergence) ProtoMessage() {} func (x *CommitDivergence) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[22] + mi := &file_repo_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1669,7 +1818,7 @@ func (x *CommitDivergence) ProtoReflect() protoreflect.Message { // Deprecated: Use CommitDivergence.ProtoReflect.Descriptor instead. func (*CommitDivergence) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{22} + return file_repo_proto_rawDescGZIP(), []int{25} } func (x *CommitDivergence) GetAhead() int32 { @@ -1697,7 +1846,7 @@ type DeleteRepositoryRequest struct { func (x *DeleteRepositoryRequest) Reset() { *x = DeleteRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[23] + mi := &file_repo_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1710,7 +1859,7 @@ func (x *DeleteRepositoryRequest) String() string { func (*DeleteRepositoryRequest) ProtoMessage() {} func (x *DeleteRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[23] + mi := &file_repo_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1723,7 +1872,7 @@ func (x *DeleteRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRepositoryRequest.ProtoReflect.Descriptor instead. func (*DeleteRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{23} + return file_repo_proto_rawDescGZIP(), []int{26} } func (x *DeleteRepositoryRequest) GetBase() *WriteRequest { @@ -1742,7 +1891,7 @@ type DeleteRepositoryResponse struct { func (x *DeleteRepositoryResponse) Reset() { *x = DeleteRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[24] + mi := &file_repo_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1755,7 +1904,7 @@ func (x *DeleteRepositoryResponse) String() string { func (*DeleteRepositoryResponse) ProtoMessage() {} func (x *DeleteRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[24] + mi := &file_repo_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1768,7 +1917,7 @@ func (x *DeleteRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRepositoryResponse.ProtoReflect.Descriptor instead. func (*DeleteRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{24} + return file_repo_proto_rawDescGZIP(), []int{27} } type SyncRepositoryRequest struct { @@ -1784,7 +1933,7 @@ type SyncRepositoryRequest struct { func (x *SyncRepositoryRequest) Reset() { *x = SyncRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[25] + mi := &file_repo_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1797,7 +1946,7 @@ func (x *SyncRepositoryRequest) String() string { func (*SyncRepositoryRequest) ProtoMessage() {} func (x *SyncRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[25] + mi := &file_repo_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1810,7 +1959,7 @@ func (x *SyncRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncRepositoryRequest.ProtoReflect.Descriptor instead. func (*SyncRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{25} + return file_repo_proto_rawDescGZIP(), []int{28} } func (x *SyncRepositoryRequest) GetBase() *WriteRequest { @@ -1843,7 +1992,7 @@ type SyncRepositoryResponse struct { func (x *SyncRepositoryResponse) Reset() { *x = SyncRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[26] + mi := &file_repo_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1856,7 +2005,7 @@ func (x *SyncRepositoryResponse) String() string { func (*SyncRepositoryResponse) ProtoMessage() {} func (x *SyncRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[26] + mi := &file_repo_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1869,7 +2018,7 @@ func (x *SyncRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncRepositoryResponse.ProtoReflect.Descriptor instead. func (*SyncRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{26} + return file_repo_proto_rawDescGZIP(), []int{29} } type HashRepositoryRequest struct { @@ -1885,7 +2034,7 @@ type HashRepositoryRequest struct { func (x *HashRepositoryRequest) Reset() { *x = HashRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[27] + mi := &file_repo_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1898,7 +2047,7 @@ func (x *HashRepositoryRequest) String() string { func (*HashRepositoryRequest) ProtoMessage() {} func (x *HashRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[27] + mi := &file_repo_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1911,7 +2060,7 @@ func (x *HashRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HashRepositoryRequest.ProtoReflect.Descriptor instead. func (*HashRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{27} + return file_repo_proto_rawDescGZIP(), []int{30} } func (x *HashRepositoryRequest) GetBase() *ReadRequest { @@ -1946,7 +2095,7 @@ type HashRepositoryResponse struct { func (x *HashRepositoryResponse) Reset() { *x = HashRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[28] + mi := &file_repo_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1959,7 +2108,7 @@ func (x *HashRepositoryResponse) String() string { func (*HashRepositoryResponse) ProtoMessage() {} func (x *HashRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[28] + mi := &file_repo_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1972,7 +2121,7 @@ func (x *HashRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HashRepositoryResponse.ProtoReflect.Descriptor instead. func (*HashRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{28} + return file_repo_proto_rawDescGZIP(), []int{31} } func (x *HashRepositoryResponse) GetHash() []byte { @@ -1995,7 +2144,7 @@ type MergeBaseRequest struct { func (x *MergeBaseRequest) Reset() { *x = MergeBaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[29] + mi := &file_repo_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2008,7 +2157,7 @@ func (x *MergeBaseRequest) String() string { func (*MergeBaseRequest) ProtoMessage() {} func (x *MergeBaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[29] + mi := &file_repo_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2021,7 +2170,7 @@ func (x *MergeBaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeBaseRequest.ProtoReflect.Descriptor instead. func (*MergeBaseRequest) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{29} + return file_repo_proto_rawDescGZIP(), []int{32} } func (x *MergeBaseRequest) GetBase() *ReadRequest { @@ -2056,7 +2205,7 @@ type MergeBaseResponse struct { func (x *MergeBaseResponse) Reset() { *x = MergeBaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repo_proto_msgTypes[30] + mi := &file_repo_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2069,7 +2218,7 @@ func (x *MergeBaseResponse) String() string { func (*MergeBaseResponse) ProtoMessage() {} func (x *MergeBaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_repo_proto_msgTypes[30] + mi := &file_repo_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2082,7 +2231,7 @@ func (x *MergeBaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeBaseResponse.ProtoReflect.Descriptor instead. func (*MergeBaseResponse) Descriptor() ([]byte, []int) { - return file_repo_proto_rawDescGZIP(), []int{30} + return file_repo_proto_rawDescGZIP(), []int{33} } func (x *MergeBaseResponse) GetMergeBaseSha() string { @@ -2139,249 +2288,264 @@ var file_repo_proto_rawDesc = []byte{ 0x0b, 0x32, 0x0d, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0xbb, 0x01, 0x0a, 0x14, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, - 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, - 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x32, 0x0a, 0x15, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, - 0x61, 0x74, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x72, - 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x22, 0x5f, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0d, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, - 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0x92, 0x01, 0x0a, 0x08, 0x54, - 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x25, - 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x72, - 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, - 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, - 0x4a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0x69, 0x0a, 0x14, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x22, 0x38, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0xf1, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, - 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, - 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x66, 0x74, 0x65, - 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, - 0x73, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x22, 0x75, 0x0a, 0x13, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x39, 0x0a, 0x0e, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, - 0x73, 0x52, 0x0d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, - 0x22, 0x9b, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, - 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x42, 0x65, - 0x66, 0x6f, 0x72, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, - 0x68, 0x61, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x41, 0x66, 0x74, 0x65, 0x72, 0x22, 0x67, - 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, - 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x69, - 0x7a, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x6b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x6c, - 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x06, 0x0a, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x22, 0x60, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, - 0x03, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, - 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, - 0x69, 0x7a, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x68, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, - 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, - 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, - 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, - 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x22, 0x44, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6d, - 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x09, 0x73, 0x75, 0x62, - 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x31, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, - 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x9a, 0x01, 0x0a, 0x1b, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, + 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, + 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, + 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x3a, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, + 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x21, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, + 0x64, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x08, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, + 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, + 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4e, + 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x73, 0x68, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x6a, 0x0a, 0x13, 0x50, 0x61, 0x74, 0x68, 0x73, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, + 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, + 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, + 0x62, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, 0x66, 0x12, 0x14, 0x0a, + 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, + 0x74, 0x68, 0x73, 0x22, 0x4b, 0x0a, 0x14, 0x50, 0x61, 0x74, 0x68, 0x73, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0c, 0x70, + 0x61, 0x74, 0x68, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x52, 0x0b, 0x70, 0x61, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x22, 0x63, 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x68, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x12, 0x2c, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x4a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, - 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x08, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, - 0x67, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x3d, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x57, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, - 0x65, 0x52, 0x0b, 0x64, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x40, - 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, - 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x68, 0x65, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x05, 0x61, 0x68, 0x65, 0x61, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x65, 0x68, 0x69, - 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, - 0x22, 0x40, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, - 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, - 0x73, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x87, - 0x01, 0x0a, 0x15, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x5f, 0x69, 0x66, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x66, 0x4e, - 0x6f, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x53, 0x79, 0x6e, 0x63, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0xae, 0x01, 0x0a, 0x15, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, - 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, - 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x09, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x61, 0x73, 0x68, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x68, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x43, - 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, - 0x61, 0x73, 0x68, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x22, 0x2c, 0x0a, 0x16, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, - 0x68, 0x22, 0x60, 0x0a, 0x10, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, - 0x65, 0x66, 0x31, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x66, 0x31, 0x12, - 0x12, 0x0a, 0x04, 0x72, 0x65, 0x66, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, - 0x65, 0x66, 0x32, 0x22, 0x39, 0x0a, 0x11, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x65, 0x72, 0x67, - 0x65, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x53, 0x68, 0x61, 0x2a, 0x52, - 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, - 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x54, 0x72, - 0x65, 0x65, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x72, - 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x10, 0x02, 0x2a, 0x81, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, - 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x72, 0x65, - 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, - 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, - 0x64, 0x65, 0x45, 0x78, 0x65, 0x63, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, 0x65, 0x65, 0x10, 0x03, 0x12, 0x16, - 0x0a, 0x12, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x10, 0x04, 0x2a, 0x1e, 0x0a, 0x08, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x53, 0x48, - 0x41, 0x32, 0x35, 0x36, 0x10, 0x00, 0x2a, 0x31, 0x0a, 0x13, 0x48, 0x61, 0x73, 0x68, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, - 0x16, 0x48, 0x61, 0x73, 0x68, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x79, 0x70, 0x65, 0x58, 0x4f, 0x52, 0x10, 0x00, 0x32, 0xf3, 0x06, 0x0a, 0x11, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x51, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x28, 0x01, 0x12, 0x40, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, - 0x65, 0x12, 0x17, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, - 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x65, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, - 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x43, - 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x18, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x13, - 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, - 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0b, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x17, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, - 0x3a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x15, 0x2e, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x14, 0x47, + 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, + 0x61, 0x22, 0x38, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0xf1, 0x01, 0x0a, 0x12, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, + 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, + 0x66, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x61, 0x66, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x75, + 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x75, 0x6e, 0x74, 0x69, + 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x22, + 0x75, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x39, 0x0a, 0x0e, 0x72, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x44, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2a, + 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x5f, 0x62, 0x65, 0x66, + 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x53, 0x68, 0x61, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x41, + 0x66, 0x74, 0x65, 0x72, 0x22, 0x67, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, + 0x73, 0x68, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x6b, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x34, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x60, 0x0a, 0x15, 0x47, 0x65, + 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x73, 0x68, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x68, 0x0a, 0x13, + 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, + 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, + 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x44, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, + 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, + 0x65, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x31, 0x0a, 0x09, + 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, + 0x9a, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, + 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x3d, 0x0a, 0x17, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, + 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x57, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x72, - 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x53, 0x79, 0x6e, - 0x63, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x79, - 0x6e, 0x63, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, - 0x61, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x09, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, - 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x65, - 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, - 0x72, 0x6e, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x69, - 0x74, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, + 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, + 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0b, 0x64, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x22, 0x40, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, + 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x68, 0x65, 0x61, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x61, 0x68, 0x65, 0x61, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, + 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x22, 0x40, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x25, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x15, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, + 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, + 0x70, 0x63, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x0a, + 0x14, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x66, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, + 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x49, 0x66, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x18, + 0x0a, 0x16, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xae, 0x01, 0x0a, 0x15, 0x48, 0x61, 0x73, + 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x09, 0x68, 0x61, 0x73, 0x68, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x68, 0x61, 0x73, 0x68, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0x2c, 0x0a, 0x16, 0x48, 0x61, 0x73, + 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x60, 0x0a, 0x10, 0x4d, 0x65, 0x72, 0x67, 0x65, + 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x72, 0x70, 0x63, 0x2e, + 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x66, 0x31, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x72, 0x65, 0x66, 0x31, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x66, 0x32, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x66, 0x32, 0x22, 0x39, 0x0a, 0x11, 0x4d, 0x65, 0x72, + 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, + 0x0a, 0x0e, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x68, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, + 0x65, 0x53, 0x68, 0x61, 0x2a, 0x52, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x54, 0x72, 0x65, 0x65, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, + 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x10, 0x01, + 0x12, 0x16, 0x0a, 0x12, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x10, 0x02, 0x2a, 0x81, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, 0x65, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x10, 0x00, 0x12, + 0x17, 0x0a, 0x13, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x53, + 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, + 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x45, 0x78, 0x65, 0x63, 0x10, 0x02, 0x12, 0x14, + 0x0a, 0x10, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, + 0x65, 0x65, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x4d, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x10, 0x04, 0x2a, 0x1e, 0x0a, 0x08, + 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x61, 0x73, 0x68, + 0x54, 0x79, 0x70, 0x65, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x00, 0x2a, 0x31, 0x0a, 0x13, + 0x48, 0x61, 0x73, 0x68, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x61, 0x73, 0x68, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x58, 0x4f, 0x52, 0x10, 0x00, 0x32, + 0xb8, 0x07, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x72, 0x70, 0x63, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x12, 0x40, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x54, + 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x4c, 0x69, + 0x73, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x30, 0x01, 0x12, 0x43, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x68, 0x73, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x73, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x47, 0x65, 0x74, + 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, + 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, + 0x0a, 0x07, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x17, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x09, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x20, + 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x69, + 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x21, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x44, 0x69, 0x76, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3a, + 0x0a, 0x09, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x12, 0x15, 0x2e, 0x72, 0x70, + 0x63, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, + 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x72, 0x6e, 0x65, 0x73, 0x73, + 0x2f, 0x67, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x2f, 0x67, 0x69, 0x74, 0x72, 0x70, 0x63, 0x2f, + 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2397,7 +2561,7 @@ func file_repo_proto_rawDescGZIP() []byte { } var file_repo_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_repo_proto_msgTypes = make([]protoimpl.MessageInfo, 31) +var file_repo_proto_msgTypes = make([]protoimpl.MessageInfo, 34) var file_repo_proto_goTypes = []interface{}{ (TreeNodeType)(0), // 0: rpc.TreeNodeType (TreeNodeMode)(0), // 1: rpc.TreeNodeMode @@ -2411,96 +2575,103 @@ var file_repo_proto_goTypes = []interface{}{ (*ListTreeNodesRequest)(nil), // 9: rpc.ListTreeNodesRequest (*ListTreeNodesResponse)(nil), // 10: rpc.ListTreeNodesResponse (*TreeNode)(nil), // 11: rpc.TreeNode - (*GetCommitRequest)(nil), // 12: rpc.GetCommitRequest - (*GetCommitResponse)(nil), // 13: rpc.GetCommitResponse - (*ListCommitsRequest)(nil), // 14: rpc.ListCommitsRequest - (*ListCommitsResponse)(nil), // 15: rpc.ListCommitsResponse - (*RenameDetails)(nil), // 16: rpc.RenameDetails - (*GetBlobRequest)(nil), // 17: rpc.GetBlobRequest - (*GetBlobResponse)(nil), // 18: rpc.GetBlobResponse - (*GetBlobResponseHeader)(nil), // 19: rpc.GetBlobResponseHeader - (*GetSubmoduleRequest)(nil), // 20: rpc.GetSubmoduleRequest - (*GetSubmoduleResponse)(nil), // 21: rpc.GetSubmoduleResponse - (*Submodule)(nil), // 22: rpc.Submodule - (*GetCommitDivergencesRequest)(nil), // 23: rpc.GetCommitDivergencesRequest - (*CommitDivergenceRequest)(nil), // 24: rpc.CommitDivergenceRequest - (*GetCommitDivergencesResponse)(nil), // 25: rpc.GetCommitDivergencesResponse - (*CommitDivergence)(nil), // 26: rpc.CommitDivergence - (*DeleteRepositoryRequest)(nil), // 27: rpc.DeleteRepositoryRequest - (*DeleteRepositoryResponse)(nil), // 28: rpc.DeleteRepositoryResponse - (*SyncRepositoryRequest)(nil), // 29: rpc.SyncRepositoryRequest - (*SyncRepositoryResponse)(nil), // 30: rpc.SyncRepositoryResponse - (*HashRepositoryRequest)(nil), // 31: rpc.HashRepositoryRequest - (*HashRepositoryResponse)(nil), // 32: rpc.HashRepositoryResponse - (*MergeBaseRequest)(nil), // 33: rpc.MergeBaseRequest - (*MergeBaseResponse)(nil), // 34: rpc.MergeBaseResponse - (*FileUpload)(nil), // 35: rpc.FileUpload - (*WriteRequest)(nil), // 36: rpc.WriteRequest - (*Identity)(nil), // 37: rpc.Identity - (*ReadRequest)(nil), // 38: rpc.ReadRequest - (*Commit)(nil), // 39: rpc.Commit + (*PathsDetailsRequest)(nil), // 12: rpc.PathsDetailsRequest + (*PathsDetailsResponse)(nil), // 13: rpc.PathsDetailsResponse + (*PathDetails)(nil), // 14: rpc.PathDetails + (*GetCommitRequest)(nil), // 15: rpc.GetCommitRequest + (*GetCommitResponse)(nil), // 16: rpc.GetCommitResponse + (*ListCommitsRequest)(nil), // 17: rpc.ListCommitsRequest + (*ListCommitsResponse)(nil), // 18: rpc.ListCommitsResponse + (*RenameDetails)(nil), // 19: rpc.RenameDetails + (*GetBlobRequest)(nil), // 20: rpc.GetBlobRequest + (*GetBlobResponse)(nil), // 21: rpc.GetBlobResponse + (*GetBlobResponseHeader)(nil), // 22: rpc.GetBlobResponseHeader + (*GetSubmoduleRequest)(nil), // 23: rpc.GetSubmoduleRequest + (*GetSubmoduleResponse)(nil), // 24: rpc.GetSubmoduleResponse + (*Submodule)(nil), // 25: rpc.Submodule + (*GetCommitDivergencesRequest)(nil), // 26: rpc.GetCommitDivergencesRequest + (*CommitDivergenceRequest)(nil), // 27: rpc.CommitDivergenceRequest + (*GetCommitDivergencesResponse)(nil), // 28: rpc.GetCommitDivergencesResponse + (*CommitDivergence)(nil), // 29: rpc.CommitDivergence + (*DeleteRepositoryRequest)(nil), // 30: rpc.DeleteRepositoryRequest + (*DeleteRepositoryResponse)(nil), // 31: rpc.DeleteRepositoryResponse + (*SyncRepositoryRequest)(nil), // 32: rpc.SyncRepositoryRequest + (*SyncRepositoryResponse)(nil), // 33: rpc.SyncRepositoryResponse + (*HashRepositoryRequest)(nil), // 34: rpc.HashRepositoryRequest + (*HashRepositoryResponse)(nil), // 35: rpc.HashRepositoryResponse + (*MergeBaseRequest)(nil), // 36: rpc.MergeBaseRequest + (*MergeBaseResponse)(nil), // 37: rpc.MergeBaseResponse + (*FileUpload)(nil), // 38: rpc.FileUpload + (*WriteRequest)(nil), // 39: rpc.WriteRequest + (*Identity)(nil), // 40: rpc.Identity + (*ReadRequest)(nil), // 41: rpc.ReadRequest + (*Commit)(nil), // 42: rpc.Commit } var file_repo_proto_depIdxs = []int32{ 5, // 0: rpc.CreateRepositoryRequest.header:type_name -> rpc.CreateRepositoryRequestHeader - 35, // 1: rpc.CreateRepositoryRequest.file:type_name -> rpc.FileUpload - 36, // 2: rpc.CreateRepositoryRequestHeader.base:type_name -> rpc.WriteRequest - 37, // 3: rpc.CreateRepositoryRequestHeader.author:type_name -> rpc.Identity - 37, // 4: rpc.CreateRepositoryRequestHeader.committer:type_name -> rpc.Identity - 38, // 5: rpc.GetTreeNodeRequest.base:type_name -> rpc.ReadRequest + 38, // 1: rpc.CreateRepositoryRequest.file:type_name -> rpc.FileUpload + 39, // 2: rpc.CreateRepositoryRequestHeader.base:type_name -> rpc.WriteRequest + 40, // 3: rpc.CreateRepositoryRequestHeader.author:type_name -> rpc.Identity + 40, // 4: rpc.CreateRepositoryRequestHeader.committer:type_name -> rpc.Identity + 41, // 5: rpc.GetTreeNodeRequest.base:type_name -> rpc.ReadRequest 11, // 6: rpc.GetTreeNodeResponse.node:type_name -> rpc.TreeNode - 39, // 7: rpc.GetTreeNodeResponse.commit:type_name -> rpc.Commit - 38, // 8: rpc.ListTreeNodesRequest.base:type_name -> rpc.ReadRequest + 42, // 7: rpc.GetTreeNodeResponse.commit:type_name -> rpc.Commit + 41, // 8: rpc.ListTreeNodesRequest.base:type_name -> rpc.ReadRequest 11, // 9: rpc.ListTreeNodesResponse.node:type_name -> rpc.TreeNode - 39, // 10: rpc.ListTreeNodesResponse.commit:type_name -> rpc.Commit - 0, // 11: rpc.TreeNode.type:type_name -> rpc.TreeNodeType - 1, // 12: rpc.TreeNode.mode:type_name -> rpc.TreeNodeMode - 38, // 13: rpc.GetCommitRequest.base:type_name -> rpc.ReadRequest - 39, // 14: rpc.GetCommitResponse.commit:type_name -> rpc.Commit - 38, // 15: rpc.ListCommitsRequest.base:type_name -> rpc.ReadRequest - 39, // 16: rpc.ListCommitsResponse.commit:type_name -> rpc.Commit - 16, // 17: rpc.ListCommitsResponse.rename_details:type_name -> rpc.RenameDetails - 38, // 18: rpc.GetBlobRequest.base:type_name -> rpc.ReadRequest - 19, // 19: rpc.GetBlobResponse.header:type_name -> rpc.GetBlobResponseHeader - 38, // 20: rpc.GetSubmoduleRequest.base:type_name -> rpc.ReadRequest - 22, // 21: rpc.GetSubmoduleResponse.submodule:type_name -> rpc.Submodule - 38, // 22: rpc.GetCommitDivergencesRequest.base:type_name -> rpc.ReadRequest - 24, // 23: rpc.GetCommitDivergencesRequest.requests:type_name -> rpc.CommitDivergenceRequest - 26, // 24: rpc.GetCommitDivergencesResponse.divergences:type_name -> rpc.CommitDivergence - 36, // 25: rpc.DeleteRepositoryRequest.base:type_name -> rpc.WriteRequest - 36, // 26: rpc.SyncRepositoryRequest.base:type_name -> rpc.WriteRequest - 38, // 27: rpc.HashRepositoryRequest.base:type_name -> rpc.ReadRequest - 2, // 28: rpc.HashRepositoryRequest.hash_type:type_name -> rpc.HashType - 3, // 29: rpc.HashRepositoryRequest.aggregation_type:type_name -> rpc.HashAggregationType - 38, // 30: rpc.MergeBaseRequest.base:type_name -> rpc.ReadRequest - 4, // 31: rpc.RepositoryService.CreateRepository:input_type -> rpc.CreateRepositoryRequest - 7, // 32: rpc.RepositoryService.GetTreeNode:input_type -> rpc.GetTreeNodeRequest - 9, // 33: rpc.RepositoryService.ListTreeNodes:input_type -> rpc.ListTreeNodesRequest - 20, // 34: rpc.RepositoryService.GetSubmodule:input_type -> rpc.GetSubmoduleRequest - 17, // 35: rpc.RepositoryService.GetBlob:input_type -> rpc.GetBlobRequest - 14, // 36: rpc.RepositoryService.ListCommits:input_type -> rpc.ListCommitsRequest - 12, // 37: rpc.RepositoryService.GetCommit:input_type -> rpc.GetCommitRequest - 23, // 38: rpc.RepositoryService.GetCommitDivergences:input_type -> rpc.GetCommitDivergencesRequest - 27, // 39: rpc.RepositoryService.DeleteRepository:input_type -> rpc.DeleteRepositoryRequest - 29, // 40: rpc.RepositoryService.SyncRepository:input_type -> rpc.SyncRepositoryRequest - 31, // 41: rpc.RepositoryService.HashRepository:input_type -> rpc.HashRepositoryRequest - 33, // 42: rpc.RepositoryService.MergeBase:input_type -> rpc.MergeBaseRequest - 6, // 43: rpc.RepositoryService.CreateRepository:output_type -> rpc.CreateRepositoryResponse - 8, // 44: rpc.RepositoryService.GetTreeNode:output_type -> rpc.GetTreeNodeResponse - 10, // 45: rpc.RepositoryService.ListTreeNodes:output_type -> rpc.ListTreeNodesResponse - 21, // 46: rpc.RepositoryService.GetSubmodule:output_type -> rpc.GetSubmoduleResponse - 18, // 47: rpc.RepositoryService.GetBlob:output_type -> rpc.GetBlobResponse - 15, // 48: rpc.RepositoryService.ListCommits:output_type -> rpc.ListCommitsResponse - 13, // 49: rpc.RepositoryService.GetCommit:output_type -> rpc.GetCommitResponse - 25, // 50: rpc.RepositoryService.GetCommitDivergences:output_type -> rpc.GetCommitDivergencesResponse - 28, // 51: rpc.RepositoryService.DeleteRepository:output_type -> rpc.DeleteRepositoryResponse - 30, // 52: rpc.RepositoryService.SyncRepository:output_type -> rpc.SyncRepositoryResponse - 32, // 53: rpc.RepositoryService.HashRepository:output_type -> rpc.HashRepositoryResponse - 34, // 54: rpc.RepositoryService.MergeBase:output_type -> rpc.MergeBaseResponse - 43, // [43:55] is the sub-list for method output_type - 31, // [31:43] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name + 0, // 10: rpc.TreeNode.type:type_name -> rpc.TreeNodeType + 1, // 11: rpc.TreeNode.mode:type_name -> rpc.TreeNodeMode + 41, // 12: rpc.PathsDetailsRequest.base:type_name -> rpc.ReadRequest + 14, // 13: rpc.PathsDetailsResponse.path_details:type_name -> rpc.PathDetails + 42, // 14: rpc.PathDetails.last_commit:type_name -> rpc.Commit + 41, // 15: rpc.GetCommitRequest.base:type_name -> rpc.ReadRequest + 42, // 16: rpc.GetCommitResponse.commit:type_name -> rpc.Commit + 41, // 17: rpc.ListCommitsRequest.base:type_name -> rpc.ReadRequest + 42, // 18: rpc.ListCommitsResponse.commit:type_name -> rpc.Commit + 19, // 19: rpc.ListCommitsResponse.rename_details:type_name -> rpc.RenameDetails + 41, // 20: rpc.GetBlobRequest.base:type_name -> rpc.ReadRequest + 22, // 21: rpc.GetBlobResponse.header:type_name -> rpc.GetBlobResponseHeader + 41, // 22: rpc.GetSubmoduleRequest.base:type_name -> rpc.ReadRequest + 25, // 23: rpc.GetSubmoduleResponse.submodule:type_name -> rpc.Submodule + 41, // 24: rpc.GetCommitDivergencesRequest.base:type_name -> rpc.ReadRequest + 27, // 25: rpc.GetCommitDivergencesRequest.requests:type_name -> rpc.CommitDivergenceRequest + 29, // 26: rpc.GetCommitDivergencesResponse.divergences:type_name -> rpc.CommitDivergence + 39, // 27: rpc.DeleteRepositoryRequest.base:type_name -> rpc.WriteRequest + 39, // 28: rpc.SyncRepositoryRequest.base:type_name -> rpc.WriteRequest + 41, // 29: rpc.HashRepositoryRequest.base:type_name -> rpc.ReadRequest + 2, // 30: rpc.HashRepositoryRequest.hash_type:type_name -> rpc.HashType + 3, // 31: rpc.HashRepositoryRequest.aggregation_type:type_name -> rpc.HashAggregationType + 41, // 32: rpc.MergeBaseRequest.base:type_name -> rpc.ReadRequest + 4, // 33: rpc.RepositoryService.CreateRepository:input_type -> rpc.CreateRepositoryRequest + 7, // 34: rpc.RepositoryService.GetTreeNode:input_type -> rpc.GetTreeNodeRequest + 9, // 35: rpc.RepositoryService.ListTreeNodes:input_type -> rpc.ListTreeNodesRequest + 12, // 36: rpc.RepositoryService.PathsDetails:input_type -> rpc.PathsDetailsRequest + 23, // 37: rpc.RepositoryService.GetSubmodule:input_type -> rpc.GetSubmoduleRequest + 20, // 38: rpc.RepositoryService.GetBlob:input_type -> rpc.GetBlobRequest + 17, // 39: rpc.RepositoryService.ListCommits:input_type -> rpc.ListCommitsRequest + 15, // 40: rpc.RepositoryService.GetCommit:input_type -> rpc.GetCommitRequest + 26, // 41: rpc.RepositoryService.GetCommitDivergences:input_type -> rpc.GetCommitDivergencesRequest + 30, // 42: rpc.RepositoryService.DeleteRepository:input_type -> rpc.DeleteRepositoryRequest + 32, // 43: rpc.RepositoryService.SyncRepository:input_type -> rpc.SyncRepositoryRequest + 34, // 44: rpc.RepositoryService.HashRepository:input_type -> rpc.HashRepositoryRequest + 36, // 45: rpc.RepositoryService.MergeBase:input_type -> rpc.MergeBaseRequest + 6, // 46: rpc.RepositoryService.CreateRepository:output_type -> rpc.CreateRepositoryResponse + 8, // 47: rpc.RepositoryService.GetTreeNode:output_type -> rpc.GetTreeNodeResponse + 10, // 48: rpc.RepositoryService.ListTreeNodes:output_type -> rpc.ListTreeNodesResponse + 13, // 49: rpc.RepositoryService.PathsDetails:output_type -> rpc.PathsDetailsResponse + 24, // 50: rpc.RepositoryService.GetSubmodule:output_type -> rpc.GetSubmoduleResponse + 21, // 51: rpc.RepositoryService.GetBlob:output_type -> rpc.GetBlobResponse + 18, // 52: rpc.RepositoryService.ListCommits:output_type -> rpc.ListCommitsResponse + 16, // 53: rpc.RepositoryService.GetCommit:output_type -> rpc.GetCommitResponse + 28, // 54: rpc.RepositoryService.GetCommitDivergences:output_type -> rpc.GetCommitDivergencesResponse + 31, // 55: rpc.RepositoryService.DeleteRepository:output_type -> rpc.DeleteRepositoryResponse + 33, // 56: rpc.RepositoryService.SyncRepository:output_type -> rpc.SyncRepositoryResponse + 35, // 57: rpc.RepositoryService.HashRepository:output_type -> rpc.HashRepositoryResponse + 37, // 58: rpc.RepositoryService.MergeBase:output_type -> rpc.MergeBaseResponse + 46, // [46:59] is the sub-list for method output_type + 33, // [33:46] is the sub-list for method input_type + 33, // [33:33] is the sub-list for extension type_name + 33, // [33:33] is the sub-list for extension extendee + 0, // [0:33] is the sub-list for field type_name } func init() { file_repo_proto_init() } @@ -2607,7 +2778,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCommitRequest); i { + switch v := v.(*PathsDetailsRequest); i { case 0: return &v.state case 1: @@ -2619,7 +2790,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCommitResponse); i { + switch v := v.(*PathsDetailsResponse); i { case 0: return &v.state case 1: @@ -2631,7 +2802,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListCommitsRequest); i { + switch v := v.(*PathDetails); i { case 0: return &v.state case 1: @@ -2643,7 +2814,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListCommitsResponse); i { + switch v := v.(*GetCommitRequest); i { case 0: return &v.state case 1: @@ -2655,7 +2826,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RenameDetails); i { + switch v := v.(*GetCommitResponse); i { case 0: return &v.state case 1: @@ -2667,7 +2838,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetBlobRequest); i { + switch v := v.(*ListCommitsRequest); i { case 0: return &v.state case 1: @@ -2679,7 +2850,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetBlobResponse); i { + switch v := v.(*ListCommitsResponse); i { case 0: return &v.state case 1: @@ -2691,7 +2862,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetBlobResponseHeader); i { + switch v := v.(*RenameDetails); i { case 0: return &v.state case 1: @@ -2703,7 +2874,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSubmoduleRequest); i { + switch v := v.(*GetBlobRequest); i { case 0: return &v.state case 1: @@ -2715,7 +2886,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSubmoduleResponse); i { + switch v := v.(*GetBlobResponse); i { case 0: return &v.state case 1: @@ -2727,7 +2898,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Submodule); i { + switch v := v.(*GetBlobResponseHeader); i { case 0: return &v.state case 1: @@ -2739,7 +2910,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCommitDivergencesRequest); i { + switch v := v.(*GetSubmoduleRequest); i { case 0: return &v.state case 1: @@ -2751,7 +2922,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CommitDivergenceRequest); i { + switch v := v.(*GetSubmoduleResponse); i { case 0: return &v.state case 1: @@ -2763,7 +2934,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCommitDivergencesResponse); i { + switch v := v.(*Submodule); i { case 0: return &v.state case 1: @@ -2775,7 +2946,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CommitDivergence); i { + switch v := v.(*GetCommitDivergencesRequest); i { case 0: return &v.state case 1: @@ -2787,7 +2958,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteRepositoryRequest); i { + switch v := v.(*CommitDivergenceRequest); i { case 0: return &v.state case 1: @@ -2799,7 +2970,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteRepositoryResponse); i { + switch v := v.(*GetCommitDivergencesResponse); i { case 0: return &v.state case 1: @@ -2811,7 +2982,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncRepositoryRequest); i { + switch v := v.(*CommitDivergence); i { case 0: return &v.state case 1: @@ -2823,7 +2994,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncRepositoryResponse); i { + switch v := v.(*DeleteRepositoryRequest); i { case 0: return &v.state case 1: @@ -2835,7 +3006,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HashRepositoryRequest); i { + switch v := v.(*DeleteRepositoryResponse); i { case 0: return &v.state case 1: @@ -2847,7 +3018,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HashRepositoryResponse); i { + switch v := v.(*SyncRepositoryRequest); i { case 0: return &v.state case 1: @@ -2859,7 +3030,7 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MergeBaseRequest); i { + switch v := v.(*SyncRepositoryResponse); i { case 0: return &v.state case 1: @@ -2871,6 +3042,42 @@ func file_repo_proto_init() { } } file_repo_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HashRepositoryRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_repo_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HashRepositoryResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_repo_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MergeBaseRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_repo_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MergeBaseResponse); i { case 0: return &v.state @@ -2887,7 +3094,7 @@ func file_repo_proto_init() { (*CreateRepositoryRequest_Header)(nil), (*CreateRepositoryRequest_File)(nil), } - file_repo_proto_msgTypes[14].OneofWrappers = []interface{}{ + file_repo_proto_msgTypes[17].OneofWrappers = []interface{}{ (*GetBlobResponse_Header)(nil), (*GetBlobResponse_Content)(nil), } @@ -2897,7 +3104,7 @@ func file_repo_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_repo_proto_rawDesc, NumEnums: 4, - NumMessages: 31, + NumMessages: 34, NumExtensions: 0, NumServices: 1, }, diff --git a/gitrpc/rpc/repo_grpc.pb.go b/gitrpc/rpc/repo_grpc.pb.go index 568e656b7..d3154e88c 100644 --- a/gitrpc/rpc/repo_grpc.pb.go +++ b/gitrpc/rpc/repo_grpc.pb.go @@ -25,6 +25,7 @@ type RepositoryServiceClient interface { CreateRepository(ctx context.Context, opts ...grpc.CallOption) (RepositoryService_CreateRepositoryClient, error) GetTreeNode(ctx context.Context, in *GetTreeNodeRequest, opts ...grpc.CallOption) (*GetTreeNodeResponse, error) ListTreeNodes(ctx context.Context, in *ListTreeNodesRequest, opts ...grpc.CallOption) (RepositoryService_ListTreeNodesClient, error) + PathsDetails(ctx context.Context, in *PathsDetailsRequest, opts ...grpc.CallOption) (*PathsDetailsResponse, error) GetSubmodule(ctx context.Context, in *GetSubmoduleRequest, opts ...grpc.CallOption) (*GetSubmoduleResponse, error) GetBlob(ctx context.Context, in *GetBlobRequest, opts ...grpc.CallOption) (RepositoryService_GetBlobClient, error) ListCommits(ctx context.Context, in *ListCommitsRequest, opts ...grpc.CallOption) (RepositoryService_ListCommitsClient, error) @@ -119,6 +120,15 @@ func (x *repositoryServiceListTreeNodesClient) Recv() (*ListTreeNodesResponse, e return m, nil } +func (c *repositoryServiceClient) PathsDetails(ctx context.Context, in *PathsDetailsRequest, opts ...grpc.CallOption) (*PathsDetailsResponse, error) { + out := new(PathsDetailsResponse) + err := c.cc.Invoke(ctx, "/rpc.RepositoryService/PathsDetails", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *repositoryServiceClient) GetSubmodule(ctx context.Context, in *GetSubmoduleRequest, opts ...grpc.CallOption) (*GetSubmoduleResponse, error) { out := new(GetSubmoduleResponse) err := c.cc.Invoke(ctx, "/rpc.RepositoryService/GetSubmodule", in, out, opts...) @@ -253,6 +263,7 @@ type RepositoryServiceServer interface { CreateRepository(RepositoryService_CreateRepositoryServer) error GetTreeNode(context.Context, *GetTreeNodeRequest) (*GetTreeNodeResponse, error) ListTreeNodes(*ListTreeNodesRequest, RepositoryService_ListTreeNodesServer) error + PathsDetails(context.Context, *PathsDetailsRequest) (*PathsDetailsResponse, error) GetSubmodule(context.Context, *GetSubmoduleRequest) (*GetSubmoduleResponse, error) GetBlob(*GetBlobRequest, RepositoryService_GetBlobServer) error ListCommits(*ListCommitsRequest, RepositoryService_ListCommitsServer) error @@ -278,6 +289,9 @@ func (UnimplementedRepositoryServiceServer) GetTreeNode(context.Context, *GetTre func (UnimplementedRepositoryServiceServer) ListTreeNodes(*ListTreeNodesRequest, RepositoryService_ListTreeNodesServer) error { return status.Errorf(codes.Unimplemented, "method ListTreeNodes not implemented") } +func (UnimplementedRepositoryServiceServer) PathsDetails(context.Context, *PathsDetailsRequest) (*PathsDetailsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PathsDetails not implemented") +} func (UnimplementedRepositoryServiceServer) GetSubmodule(context.Context, *GetSubmoduleRequest) (*GetSubmoduleResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetSubmodule not implemented") } @@ -383,6 +397,24 @@ func (x *repositoryServiceListTreeNodesServer) Send(m *ListTreeNodesResponse) er return x.ServerStream.SendMsg(m) } +func _RepositoryService_PathsDetails_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PathsDetailsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RepositoryServiceServer).PathsDetails(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rpc.RepositoryService/PathsDetails", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RepositoryServiceServer).PathsDetails(ctx, req.(*PathsDetailsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _RepositoryService_GetSubmodule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetSubmoduleRequest) if err := dec(in); err != nil { @@ -562,6 +594,10 @@ var RepositoryService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetTreeNode", Handler: _RepositoryService_GetTreeNode_Handler, }, + { + MethodName: "PathsDetails", + Handler: _RepositoryService_PathsDetails_Handler, + }, { MethodName: "GetSubmodule", Handler: _RepositoryService_GetSubmodule_Handler, diff --git a/gitrpc/server/config.go b/gitrpc/server/config.go index 46ecedf6a..8e736ba3e 100644 --- a/gitrpc/server/config.go +++ b/gitrpc/server/config.go @@ -25,6 +25,16 @@ type Config struct { } MaxConnAge time.Duration `envconfig:"GITRPC_SERVER_MAX_CONN_AGE" default:"630720000s"` MaxConnAgeGrace time.Duration `envconfig:"GITRPC_SERVER_MAX_CONN_AGE_GRACE" default:"630720000s"` + + // LastCommitCacheSeconds defines cache duration in seconds of last commit, default=12h + LastCommitCacheSeconds int `envconfig:"GITRPC_LAST_COMMIT_CACHE_SECONDS" default:"43200"` + + Redis struct { + Endpoint string `envconfig:"GITRPC_REDIS_ENDPOINT" default:"localhost:6379"` + MaxRetries int `envconfig:"GITRPC_REDIS_MAX_RETRIES" default:"3"` + MinIdleConnections int `envconfig:"GITRPC_REDIS_MIN_IDLE_CONNECTIONS" default:"0"` + Password string `envconfig:"GITRPC_REDIS_PASSWORD"` + } } func (c *Config) Validate() error { diff --git a/gitrpc/server/wire.go b/gitrpc/server/wire.go index 599c0f771..e50667606 100644 --- a/gitrpc/server/wire.go +++ b/gitrpc/server/wire.go @@ -5,9 +5,14 @@ package server import ( + "time" + + "github.com/harness/gitness/cache" "github.com/harness/gitness/gitrpc/internal/gitea" "github.com/harness/gitness/gitrpc/internal/service" + "github.com/harness/gitness/gitrpc/internal/types" + "github.com/go-redis/redis/v8" "github.com/google/wire" ) @@ -16,10 +21,33 @@ var WireSet = wire.NewSet( ProvideServer, ProvideHTTPServer, ProvideGITAdapter, + ProvideGoGitRepoCache, + ProvideLastCommitCache, ) -func ProvideGITAdapter() (service.GitAdapter, error) { - return gitea.New() +func ProvideGoGitRepoCache() cache.Cache[string, *gitea.RepoEntryValue] { + return gitea.NewRepoCache() +} + +func ProvideLastCommitCache( + config Config, + redisClient redis.UniversalClient, + repoCache cache.Cache[string, *gitea.RepoEntryValue], +) cache.Cache[gitea.CommitEntryKey, *types.Commit] { + cacheDuration := time.Duration(config.LastCommitCacheSeconds) * time.Second + + if redisClient == nil { + return gitea.NewInMemoryLastCommitCache(cacheDuration, repoCache) + } + + return gitea.NewRedisLastCommitCache(redisClient, cacheDuration, repoCache) +} + +func ProvideGITAdapter( + repoCache cache.Cache[string, *gitea.RepoEntryValue], + lastCommitCache cache.Cache[gitea.CommitEntryKey, *types.Commit], +) (service.GitAdapter, error) { + return gitea.New(repoCache, lastCommitCache) } func ProvideServer(config Config, adapter service.GitAdapter) (*GRPCServer, error) { diff --git a/gitrpc/tree.go b/gitrpc/tree.go index 03e51886e..90cca5669 100644 --- a/gitrpc/tree.go +++ b/gitrpc/tree.go @@ -51,16 +51,10 @@ type ListTreeNodeParams struct { GitREF string Path string IncludeLatestCommit bool - Recursive bool } type ListTreeNodeOutput struct { - Nodes []TreeNodeWithCommit -} - -type TreeNodeWithCommit struct { - TreeNode - Commit *Commit + Nodes []TreeNode } type GetTreeNodeParams struct { @@ -94,6 +88,7 @@ func (c *Client) GetTreeNode(ctx context.Context, params *GetTreeNodeParams) (*G if err != nil { return nil, fmt.Errorf("failed to map rpc node: %w", err) } + var commit *Commit if resp.GetCommit() != nil { commit, err = mapRPCCommit(resp.GetCommit()) @@ -113,17 +108,15 @@ func (c *Client) ListTreeNodes(ctx context.Context, params *ListTreeNodeParams) return nil, ErrNoParamsProvided } stream, err := c.repoService.ListTreeNodes(ctx, &rpc.ListTreeNodesRequest{ - Base: mapToRPCReadRequest(params.ReadParams), - GitRef: params.GitREF, - Path: params.Path, - IncludeLatestCommit: params.IncludeLatestCommit, - Recursive: params.Recursive, + Base: mapToRPCReadRequest(params.ReadParams), + GitRef: params.GitREF, + Path: params.Path, }) if err != nil { return nil, fmt.Errorf("failed to start stream for tree nodes: %w", err) } - nodes := make([]TreeNodeWithCommit, 0, 16) + nodes := make([]TreeNode, 0, 16) for { var next *rpc.ListTreeNodesResponse next, err = stream.Recv() @@ -140,21 +133,60 @@ func (c *Client) ListTreeNodes(ctx context.Context, params *ListTreeNodeParams) if err != nil { return nil, fmt.Errorf("failed to map rpc node: %w", err) } - var commit *Commit - if next.GetCommit() != nil { - commit, err = mapRPCCommit(next.GetCommit()) - if err != nil { - return nil, fmt.Errorf("failed to map rpc commit: %w", err) - } - } - nodes = append(nodes, TreeNodeWithCommit{ - TreeNode: node, - Commit: commit, - }) + nodes = append(nodes, node) } return &ListTreeNodeOutput{ Nodes: nodes, }, nil } + +type PathsDetailsParams struct { + ReadParams + GitREF string + Paths []string +} + +type PathsDetailsOutput struct { + Details []PathDetails +} + +type PathDetails struct { + Path string `json:"path"` + LastCommit *Commit `json:"last_commit,omitempty"` + Size int64 `json:"size,omitempty"` +} + +func (c *Client) PathsDetails(ctx context.Context, params PathsDetailsParams) (PathsDetailsOutput, error) { + response, err := c.repoService.PathsDetails(ctx, &rpc.PathsDetailsRequest{ + Base: mapToRPCReadRequest(params.ReadParams), + GitRef: params.GitREF, + Paths: params.Paths, + }) + if err != nil { + return PathsDetailsOutput{}, processRPCErrorf(err, "failed to get paths details") + } + + details := make([]PathDetails, len(response.PathDetails)) + for i, pathDetail := range response.PathDetails { + var lastCommit *Commit + + if pathDetail.LastCommit != nil { + lastCommit, err = mapRPCCommit(pathDetail.LastCommit) + if err != nil { + return PathsDetailsOutput{}, fmt.Errorf("failed to map last commit: %w", err) + } + } + + details[i] = PathDetails{ + Path: pathDetail.Path, + Size: pathDetail.Size, + LastCommit: lastCommit, + } + } + + return PathsDetailsOutput{ + Details: details, + }, nil +} diff --git a/internal/api/controller/repo/get_content.go b/internal/api/controller/repo/content_get.go similarity index 78% rename from internal/api/controller/repo/get_content.go rename to internal/api/controller/repo/content_get.go index 039f453d3..5ca0f7d98 100644 --- a/internal/api/controller/repo/get_content.go +++ b/internal/api/controller/repo/content_get.go @@ -80,13 +80,15 @@ type SubmoduleContent struct { func (c *SubmoduleContent) isContent() {} -/* - * GetContent finds the content of the repo at the given path. - * If no gitRef is provided, the content is retrieved from the default branch. - * If includeLatestCommit is enabled, the response contains information of the latest commit that changed the object. - */ -func (c *Controller) GetContent(ctx context.Context, session *auth.Session, repoRef string, - gitRef string, repoPath string, includeLatestCommit bool) (*GetContentOutput, error) { +// GetContent finds the content of the repo at the given path. +// If no gitRef is provided, the content is retrieved from the default branch. +func (c *Controller) GetContent(ctx context.Context, + session *auth.Session, + repoRef string, + gitRef string, + repoPath string, + includeLatestCommit bool, +) (*GetContentOutput, error) { repo, err := c.repoStore.FindByRef(ctx, repoRef) if err != nil { return nil, err @@ -114,7 +116,7 @@ func (c *Controller) GetContent(ctx context.Context, session *auth.Session, repo return nil, err } - info, err := mapToContentInfo(&treeNodeOutput.Node, treeNodeOutput.Commit) + info, err := mapToContentInfo(treeNodeOutput.Node, treeNodeOutput.Commit, includeLatestCommit) if err != nil { return nil, err } @@ -122,8 +124,7 @@ func (c *Controller) GetContent(ctx context.Context, session *auth.Session, repo var content Content switch info.Type { case ContentTypeDir: - // for getContent we don't want any recursiveness for dir content. - content, err = c.getDirContent(ctx, readParams, gitRef, repoPath, includeLatestCommit, false) + content, err = c.getDirContent(ctx, readParams, gitRef, repoPath, includeLatestCommit) case ContentTypeFile: content, err = c.getFileContent(ctx, readParams, info.SHA) case ContentTypeSymlink: @@ -139,13 +140,17 @@ func (c *Controller) GetContent(ctx context.Context, session *auth.Session, repo } return &GetContentOutput{ - ContentInfo: *info, + ContentInfo: info, Content: content, }, nil } -func (c *Controller) getSubmoduleContent(ctx context.Context, readParams gitrpc.ReadParams, gitRef string, - repoPath string, commitSHA string) (*SubmoduleContent, error) { +func (c *Controller) getSubmoduleContent(ctx context.Context, + readParams gitrpc.ReadParams, + gitRef string, + repoPath string, + commitSHA string, +) (*SubmoduleContent, error) { output, err := c.gitRPCClient.GetSubmodule(ctx, &gitrpc.GetSubmoduleParams{ ReadParams: readParams, GitREF: gitRef, @@ -163,8 +168,10 @@ func (c *Controller) getSubmoduleContent(ctx context.Context, readParams gitrpc. }, nil } -func (c *Controller) getFileContent(ctx context.Context, readParams gitrpc.ReadParams, - blobSHA string) (*FileContent, error) { +func (c *Controller) getFileContent(ctx context.Context, + readParams gitrpc.ReadParams, + blobSHA string, +) (*FileContent, error) { output, err := c.gitRPCClient.GetBlob(ctx, &gitrpc.GetBlobParams{ ReadParams: readParams, SHA: blobSHA, @@ -187,8 +194,10 @@ func (c *Controller) getFileContent(ctx context.Context, readParams gitrpc.ReadP }, nil } -func (c *Controller) getSymlinkContent(ctx context.Context, readParams gitrpc.ReadParams, - blobSHA string) (*SymlinkContent, error) { +func (c *Controller) getSymlinkContent(ctx context.Context, + readParams gitrpc.ReadParams, + blobSHA string, +) (*SymlinkContent, error) { output, err := c.gitRPCClient.GetBlob(ctx, &gitrpc.GetBlobParams{ ReadParams: readParams, SHA: blobSHA, @@ -211,14 +220,17 @@ func (c *Controller) getSymlinkContent(ctx context.Context, readParams gitrpc.Re }, nil } -func (c *Controller) getDirContent(ctx context.Context, readParams gitrpc.ReadParams, gitRef string, - repoPath string, includeLatestCommit bool, recursive bool) (*DirContent, error) { +func (c *Controller) getDirContent(ctx context.Context, + readParams gitrpc.ReadParams, + gitRef string, + repoPath string, + includeLatestCommit bool, +) (*DirContent, error) { output, err := c.gitRPCClient.ListTreeNodes(ctx, &gitrpc.ListTreeNodeParams{ ReadParams: readParams, GitREF: gitRef, Path: repoPath, IncludeLatestCommit: includeLatestCommit, - Recursive: recursive, }) if err != nil { // TODO: handle not found error @@ -227,15 +239,11 @@ func (c *Controller) getDirContent(ctx context.Context, readParams gitrpc.ReadPa } entries := make([]ContentInfo, len(output.Nodes)) - for i := range output.Nodes { - node := output.Nodes[i] - - var entry *ContentInfo - entry, err = mapToContentInfo(&node.TreeNode, node.Commit) + for i, node := range output.Nodes { + entries[i], err = mapToContentInfo(node, nil, false) if err != nil { return nil, err } - entries[i] = *entry } return &DirContent{ @@ -243,17 +251,13 @@ func (c *Controller) getDirContent(ctx context.Context, readParams gitrpc.ReadPa }, nil } -func mapToContentInfo(node *gitrpc.TreeNode, commit *gitrpc.Commit) (*ContentInfo, error) { - // node data is expected - if node == nil { - return nil, fmt.Errorf("node can't be nil") - } +func mapToContentInfo(node gitrpc.TreeNode, commit *gitrpc.Commit, includeLatestCommit bool) (ContentInfo, error) { typ, err := mapNodeModeToContentType(node.Mode) if err != nil { - return nil, err + return ContentInfo{}, err } - res := &ContentInfo{ + res := ContentInfo{ Type: typ, SHA: node.SHA, Name: node.Name, @@ -261,10 +265,10 @@ func mapToContentInfo(node *gitrpc.TreeNode, commit *gitrpc.Commit) (*ContentInf } // parse commit only if available - if commit != nil { + if commit != nil && includeLatestCommit { res.LatestCommit, err = controller.MapCommit(commit) if err != nil { - return nil, err + return ContentInfo{}, err } } diff --git a/internal/api/controller/repo/content_paths_details.go b/internal/api/controller/repo/content_paths_details.go new file mode 100644 index 000000000..b42d9d71b --- /dev/null +++ b/internal/api/controller/repo/content_paths_details.go @@ -0,0 +1,70 @@ +// Copyright 2022 Harness Inc. All rights reserved. +// Use of this source code is governed by the Polyform Free Trial License +// that can be found in the LICENSE.md file for this repository. + +package repo + +import ( + "context" + + "github.com/harness/gitness/gitrpc" + apiauth "github.com/harness/gitness/internal/api/auth" + "github.com/harness/gitness/internal/api/usererror" + "github.com/harness/gitness/internal/auth" + "github.com/harness/gitness/types/enum" +) + +type PathsDetailsInput struct { + Paths []string `json:"paths"` +} + +type PathsDetailsOutput struct { + Details []gitrpc.PathDetails `json:"details"` +} + +// PathsDetails finds the additional info about the provided paths of the repo. +// If no gitRef is provided, the content is retrieved from the default branch. +func (c *Controller) PathsDetails(ctx context.Context, + session *auth.Session, + repoRef string, + gitRef string, + input PathsDetailsInput, +) (PathsDetailsOutput, error) { + repo, err := c.repoStore.FindByRef(ctx, repoRef) + if err != nil { + return PathsDetailsOutput{}, err + } + + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, true); err != nil { + return PathsDetailsOutput{}, err + } + + if len(input.Paths) == 0 { + return PathsDetailsOutput{}, nil + } + + if len(input.Paths) > 50 { + return PathsDetailsOutput{}, usererror.BadRequest("maximum number of elements in the Paths array is 25") + } + + // set gitRef to default branch in case an empty reference was provided + if gitRef == "" { + gitRef = repo.DefaultBranch + } + + // create read params once + readParams := CreateRPCReadParams(repo) + + result, err := c.gitRPCClient.PathsDetails(ctx, gitrpc.PathsDetailsParams{ + ReadParams: readParams, + GitREF: gitRef, + Paths: input.Paths, + }) + if err != nil { + return PathsDetailsOutput{}, err + } + + return PathsDetailsOutput{ + Details: result.Details, + }, nil +} diff --git a/internal/api/handler/repo/get_content.go b/internal/api/handler/repo/content_get.go similarity index 93% rename from internal/api/handler/repo/get_content.go rename to internal/api/handler/repo/content_get.go index 71f7e3e68..c2cd8e17f 100644 --- a/internal/api/handler/repo/get_content.go +++ b/internal/api/handler/repo/content_get.go @@ -12,9 +12,7 @@ import ( "github.com/harness/gitness/internal/api/request" ) -/* - * Writes json-encoded content information to the http response body. - */ +// HandleGetContent handles the get content HTTP API. func HandleGetContent(repoCtrl *repo.Controller) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() diff --git a/internal/api/handler/repo/content_paths_details.go b/internal/api/handler/repo/content_paths_details.go new file mode 100644 index 000000000..995c9f3c3 --- /dev/null +++ b/internal/api/handler/repo/content_paths_details.go @@ -0,0 +1,44 @@ +// Copyright 2022 Harness Inc. All rights reserved. +// Use of this source code is governed by the Polyform Free Trial License +// that can be found in the LICENSE.md file for this repository. + +package repo + +import ( + "encoding/json" + "net/http" + + "github.com/harness/gitness/internal/api/controller/repo" + "github.com/harness/gitness/internal/api/render" + "github.com/harness/gitness/internal/api/request" +) + +// HandlePathsDetails handles get file or directory details HTTP API. +func HandlePathsDetails(repoCtrl *repo.Controller) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + session, _ := request.AuthSessionFrom(ctx) + repoRef, err := request.GetRepoRefFromPath(r) + if err != nil { + render.TranslatedUserError(w, err) + return + } + + gitRef := request.GetGitRefFromQueryOrDefault(r, "") + + var in repo.PathsDetailsInput + err = json.NewDecoder(r.Body).Decode(&in) + if err != nil { + render.BadRequestf(w, "Invalid request body: %s.", err) + return + } + + resp, err := repoCtrl.PathsDetails(ctx, session, repoRef, gitRef, in) + if err != nil { + render.TranslatedUserError(w, err) + return + } + + render.JSON(w, http.StatusOK, resp) + } +} diff --git a/internal/api/openapi/repo.go b/internal/api/openapi/repo.go index 7c44a4fe0..2d9478a3a 100644 --- a/internal/api/openapi/repo.go +++ b/internal/api/openapi/repo.go @@ -57,6 +57,11 @@ type getContentRequest struct { Path string `path:"path"` } +type pathsDetailsRequest struct { + repoRequest + repo.PathsDetailsInput +} + type getBlameRequest struct { repoRequest Path string `path:"path"` @@ -481,6 +486,18 @@ func repoOperations(reflector *openapi3.Reflector) { _ = reflector.SetJSONResponse(&opGetContent, new(usererror.Error), http.StatusNotFound) _ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/content/{path}", opGetContent) + opPathDetails := openapi3.Operation{} + opPathDetails.WithTags("repository") + opPathDetails.WithMapOfAnything(map[string]interface{}{"operationId": "pathDetails"}) + opPathDetails.WithParameters(queryParameterGitRef) + _ = reflector.SetRequest(&opPathDetails, new(pathsDetailsRequest), http.MethodPost) + _ = reflector.SetJSONResponse(&opPathDetails, new(repo.PathsDetailsOutput), http.StatusOK) + _ = reflector.SetJSONResponse(&opPathDetails, new(usererror.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opPathDetails, new(usererror.Error), http.StatusUnauthorized) + _ = reflector.SetJSONResponse(&opPathDetails, new(usererror.Error), http.StatusForbidden) + _ = reflector.SetJSONResponse(&opPathDetails, new(usererror.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation(http.MethodPost, "/repos/{repo_ref}/path-details", opPathDetails) + opGetRaw := openapi3.Operation{} opGetRaw.WithTags("repository") opGetRaw.WithMapOfAnything(map[string]interface{}{"operationId": "getRaw"}) diff --git a/internal/router/api.go b/internal/router/api.go index 35dc4238d..a5c17226a 100644 --- a/internal/router/api.go +++ b/internal/router/api.go @@ -200,6 +200,8 @@ func setupRepos(r chi.Router, r.Get("/*", handlerrepo.HandleGetContent(repoCtrl)) }) + r.Post("/path-details", handlerrepo.HandlePathsDetails(repoCtrl)) + r.Route("/blame", func(r chi.Router) { r.Get("/*", handlerrepo.HandleBlame(repoCtrl)) }) diff --git a/internal/store/cache/path.go b/internal/store/cache/path.go index 8a47d7ef3..41b725ce5 100644 --- a/internal/store/cache/path.go +++ b/internal/store/cache/path.go @@ -13,38 +13,24 @@ import ( "github.com/harness/gitness/types" ) -// pathCacheEntry is used to return the proper transformed value as identifier when storing a path in cache. -type pathCacheEntry struct { - inner *types.Path - valueUnique string -} - -func (e *pathCacheEntry) Identifier() string { - return e.valueUnique -} - // pathCacheGetter is used to hook a PathStore as source of a pathCache. // IMPORTANT: It assumes that the pathCache already transformed the key. type pathCacheGetter struct { pathStore store.PathStore } -func (g *pathCacheGetter) Find(ctx context.Context, key string) (*pathCacheEntry, error) { +func (g *pathCacheGetter) Find(ctx context.Context, key string) (*types.Path, error) { path, err := g.pathStore.FindValue(ctx, key) if err != nil { return nil, err } - return &pathCacheEntry{ - inner: path, - // key is already transformed - pathCache transforms the path before calling the inner cache. - valueUnique: key, - }, nil + return path, nil } // pathCache is a decorator of a Cache required to handle path transformations. type pathCache struct { - inner cache.Cache[string, *pathCacheEntry] + inner cache.Cache[string, *types.Path] pathTransformation store.PathTransformation } @@ -54,12 +40,12 @@ func (c *pathCache) Get(ctx context.Context, key string) (*types.Path, error) { return nil, fmt.Errorf("failed to transform path: %w", err) } - cacheEntry, err := c.inner.Get(ctx, uniqueKey) + path, err := c.inner.Get(ctx, uniqueKey) if err != nil { return nil, err } - return cacheEntry.inner, nil + return path, nil } func (c *pathCache) Stats() (int64, int64) { diff --git a/internal/store/cache/wire.go b/internal/store/cache/wire.go index 58231d950..da4eaf6f6 100644 --- a/internal/store/cache/wire.go +++ b/internal/store/cache/wire.go @@ -29,7 +29,7 @@ func ProvidePrincipalInfoCache(getter store.PrincipalInfoView) store.PrincipalIn // ProvidePathCache provides a cache for storing routing paths and their types.Path objects. func ProvidePathCache(pathStore store.PathStore, pathTransformation store.PathTransformation) store.PathCache { return &pathCache{ - inner: cache.New[string, *pathCacheEntry]( + inner: cache.New[string, *types.Path]( &pathCacheGetter{ pathStore: pathStore, }, diff --git a/types/repo.go b/types/repo.go index bce22ac2d..c14635992 100644 --- a/types/repo.go +++ b/types/repo.go @@ -57,7 +57,3 @@ type RepositoryGitInfo struct { ID int64 GitUID string } - -func (p *RepositoryGitInfo) Identifier() int64 { - return p.ID -} diff --git a/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx b/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx index 6d6d62966..5b2d250e5 100644 --- a/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx +++ b/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx @@ -70,7 +70,7 @@ export function FolderContent({ Cell: ({ row }: CellProps) => { return ( - {formatDate(row.original.latest_commit?.author?.when as string)} + {!!row.original.latest_commit?.author?.when ? formatDate(row.original.latest_commit?.author?.when as string) : ""} ) }