diff options
author | GitLab Release Tools Bot <delivery-team+release-tools@gitlab.com> | 2024-01-12 02:30:23 +0300 |
---|---|---|
committer | GitLab Release Tools Bot <delivery-team+release-tools@gitlab.com> | 2024-01-12 02:30:23 +0300 |
commit | a22e2401ee6aa35ae70ca67013264b72fc29b6f5 (patch) | |
tree | 73edfda7212e3b2c6f369fdad59e34ca7b15e5e0 | |
parent | e723389f79dea270432590bbb1cb68a5f8df5b87 (diff) | |
parent | 7266ae482ea8dd634a39d3607fbb9b8647b63f3e (diff) |
Merge remote-tracking branch 'dev/master'
47 files changed, 1613 insertions, 1907 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b34e6ad6c..d835e6cf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Gitaly changelog +## 16.7.2 (2024-01-10) + +### Security (1 change) + +- [commit: Fix bug in commit signature parsing](gitlab-org/security/gitaly@50ef27b6e9af04d821133dd6a11fbe6d8cee8e97) ([merge request](gitlab-org/security/gitaly!87)) + +## 16.7.1 (2023-12-23) + +No changes. + ## 16.7.0 (2023-12-20) ### Fixed (3 changes) @@ -19,6 +29,16 @@ - [gitaly: Move asynchronous tasks to end of startup](gitlab-org/gitaly@dd4ea4388b4b8e7c49ea423126f8be5e067729cd) ([merge request](gitlab-org/gitaly!6532)) - [cgroups: Create repository cgroups on-demand](gitlab-org/gitaly@105f6dd81689b7819b844b8be1be844bca6f2a67) ([merge request](gitlab-org/gitaly!6499)) +## 16.6.4 (2024-01-10) + +### Security (1 change) + +- [commit: Fix bug in commit signature parsing](gitlab-org/security/gitaly@615b117d20f45b8dd2b91a8a1f01e12dc966f193) ([merge request](gitlab-org/security/gitaly!91)) + +## 16.6.3 (2023-12-23) + +No changes. + ## 16.6.2 (2023-12-13) No changes. @@ -53,6 +73,16 @@ No changes. - [backup: Use --all when creating an incremental backup bundle](gitlab-org/gitaly@d874d8c3eb0d0c9b9362b583ba8ccc42221140cd) ([merge request](gitlab-org/gitaly!6421)) +## 16.5.6 (2024-01-11) + +### Security (1 change) + +- [commit: Fix bug in commit signature parsing](gitlab-org/security/gitaly@d410c35c0906cb75bc0d8d967744b12991cefaa0) ([merge request](gitlab-org/security/gitaly!89)) + +## 16.5.5 (2023-12-23) + +No changes. + ## 16.5.4 (2023-12-13) No changes. @@ -95,6 +125,10 @@ No changes. - [gitaly: Don't block on preloading licensedb](gitlab-org/gitaly@d96964bf6fe4a17adfded56a28bc276377351bc8) ([merge request](gitlab-org/gitaly!6397)) - [packed_binaries: Extract binaries in parallel](gitlab-org/gitaly@2f5d4f93bdd27d3299f9ccc005ee7bcca35efcc9) ([merge request](gitlab-org/gitaly!6401)) +## 16.4.5 (2024-01-11) + +No changes. + ## 16.4.4 (2023-12-13) No changes. @@ -153,6 +187,10 @@ No changes. - [backup: Improve time taken to create a full backup bundle](gitlab-org/gitaly@c43b91c07de39a4e32b3bb855787ab43e9c6a6c7) ([merge request](gitlab-org/gitaly!6305)) - [backup: Improve performance of writing ref lists](gitlab-org/gitaly@897aadac824654041b9c383b17ec8a5f217eac6b) ([merge request](gitlab-org/gitaly!6305)) +## 16.3.7 (2024-01-11) + +No changes. + ## 16.3.6 (2023-10-30) No changes. @@ -220,6 +258,10 @@ No changes. - [backup: Write an empty ref list for empty repositories](gitlab-org/gitaly@7fbae125172570e5bef222908388ba0ca1c9e43a) ([merge request](gitlab-org/gitaly!6090)) +## 16.2.9 (2024-01-11) + +No changes. + ## 16.2.8 (2023-09-28) No changes. @@ -292,6 +334,10 @@ No changes. - [localrepo: Avoid getting all branches for default branch detection](gitlab-org/gitaly@bdd3c05a2cc2889260050f2714884cc24503ae1a) by @blanet ([merge request](gitlab-org/gitaly!5725)) +## 16.1.6 (2024-01-11) + +No changes. + ## 16.1.5 (2023-08-31) No changes. diff --git a/internal/backup/backup.go b/internal/backup/backup.go index a15f47abe..5eed0724a 100644 --- a/internal/backup/backup.go +++ b/internal/backup/backup.go @@ -211,56 +211,25 @@ func NewManagerLocal( } } -// RemoveRepository removes the specified repository from its storage. -func (mgr *Manager) RemoveRepository(ctx context.Context, req *RemoveRepositoryRequest) error { - if err := setContextServerInfo(ctx, &req.Server, req.Repo.StorageName); err != nil { - return fmt.Errorf("remove repo: set context: %w", err) +// RemoveAllRepositories removes all repositories in the specified storage name. +func (mgr *Manager) RemoveAllRepositories(ctx context.Context, req *RemoveAllRepositoriesRequest) error { + if err := setContextServerInfo(ctx, &req.Server, req.StorageName); err != nil { + return fmt.Errorf("manager: %w", err) } repoClient, err := mgr.newRepoClient(ctx, req.Server) if err != nil { - return fmt.Errorf("remove repo: create client: %w", err) + return fmt.Errorf("manager: %w", err) } - _, err = repoClient.RemoveRepository(ctx, &gitalypb.RemoveRepositoryRequest{Repository: req.Repo}) + _, err = repoClient.RemoveAll(ctx, &gitalypb.RemoveAllRequest{StorageName: req.StorageName}) if err != nil { - return fmt.Errorf("remove repo: remove: %w", err) + return fmt.Errorf("manager: %w", err) } return nil } -// ListRepositories returns a list of repositories found in the given storage. -func (mgr *Manager) ListRepositories(ctx context.Context, req *ListRepositoriesRequest) (repos []*gitalypb.Repository, err error) { - if err := setContextServerInfo(ctx, &req.Server, req.StorageName); err != nil { - return nil, fmt.Errorf("list repos: set context: %w", err) - } - - internalClient, err := mgr.newInternalClient(ctx, req.Server) - if err != nil { - return nil, fmt.Errorf("list repos: create client: %w", err) - } - - stream, err := internalClient.WalkRepos(ctx, &gitalypb.WalkReposRequest{StorageName: req.StorageName}) - if err != nil { - return nil, fmt.Errorf("list repos: walk: %w", err) - } - - for { - resp, err := stream.Recv() - if errors.Is(err, io.EOF) { - break - } - if err != nil { - return nil, fmt.Errorf("list repos: receiving messages: %w", err) - } - - repos = append(repos, &gitalypb.Repository{RelativePath: resp.RelativePath, StorageName: req.StorageName}) - } - - return repos, nil -} - // Create creates a repository backup. func (mgr *Manager) Create(ctx context.Context, req *CreateRequest) error { if req.VanityRepository == nil { @@ -604,12 +573,3 @@ func (mgr *Manager) newRepoClient(ctx context.Context, server storage.ServerInfo return gitalypb.NewRepositoryServiceClient(conn), nil } - -func (mgr *Manager) newInternalClient(ctx context.Context, server storage.ServerInfo) (gitalypb.InternalGitalyClient, error) { - conn, err := mgr.conns.Dial(ctx, server.Address, server.Token) - if err != nil { - return nil, err - } - - return gitalypb.NewInternalGitalyClient(conn), nil -} diff --git a/internal/backup/backup_test.go b/internal/backup/backup_test.go index 81e87a33a..14341ec6a 100644 --- a/internal/backup/backup_test.go +++ b/internal/backup/backup_test.go @@ -28,10 +28,13 @@ import ( "google.golang.org/protobuf/proto" ) -func TestManager_RemoveRepository(t *testing.T) { - if testhelper.IsPraefectEnabled() { - t.Skip("local backup manager expects to operate on the local filesystem so cannot operate through praefect") - } +func TestManager_RemoveAllRepositories(t *testing.T) { + testhelper.SkipWithWAL(t, ` +RemoveAll is removing the entire content of the storage. This would also remove the database's and +the transaction manager's disk state. The RPC needs to be updated to shut down all partitions and +the database and only then perform the removal. + +Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) t.Parallel() @@ -55,109 +58,11 @@ func TestManager_RemoveRepository(t *testing.T) { require.NoError(t, err) fsBackup := backup.NewManager(sink, locator, pool) - err = fsBackup.RemoveRepository(ctx, &backup.RemoveRepositoryRequest{ - Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, - Repo: repo, + err = fsBackup.RemoveAllRepositories(ctx, &backup.RemoveAllRepositoriesRequest{ + Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, + StorageName: repo.StorageName, }) require.NoError(t, err) - require.NoDirExists(t, repoPath) - - // With an invalid repository - err = fsBackup.RemoveRepository(ctx, &backup.RemoveRepositoryRequest{ - Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, - Repo: &gitalypb.Repository{StorageName: "nonexistent", RelativePath: "nonexistent"}, - }) - - require.EqualError(t, err, "remove repo: remove: rpc error: code = InvalidArgument desc = storage name not found") -} - -func TestManager_ListRepositories(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - desc string - repos map[string][]*gitalypb.Repository - }{ - { - desc: "no repos", - repos: make(map[string][]*gitalypb.Repository), - }, - { - desc: "repos in a single storage", - repos: map[string][]*gitalypb.Repository{ - "storage-1": { - {RelativePath: "a", StorageName: "storage-1"}, - {RelativePath: "b", StorageName: "storage-1"}, - }, - }, - }, - { - desc: "repos in multiple storages", - repos: map[string][]*gitalypb.Repository{ - "storage-1": { - {RelativePath: "a", StorageName: "storage-1"}, - {RelativePath: "b", StorageName: "storage-1"}, - }, - "storage-2": { - {RelativePath: "c", StorageName: "storage-2"}, - {RelativePath: "d", StorageName: "storage-2"}, - }, - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - if testhelper.IsPraefectEnabled() { - t.Skip("local backup manager expects to operate on the local filesystem so cannot operate through praefect") - } - - var storages []string - for storageName := range tc.repos { - storages = append(storages, storageName) - } - - // We don't really need a "default" storage, but this makes initialisation cleaner since - // WithStorages() takes at least one argument. - cfg := testcfg.Build(t, testcfg.WithStorages("default", storages...)) - cfg.SocketPath = testserver.RunGitalyServer(t, cfg, setup.RegisterAll) - - ctx := testhelper.Context(t) - - for storageName, repos := range tc.repos { - for _, repo := range repos { - storagePath, ok := cfg.StoragePath(storageName) - require.True(t, ok) - - _, _ = gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{ - SkipCreationViaService: true, - RelativePath: repo.RelativePath, - Storage: config.Storage{Name: storageName, Path: storagePath}, - }) - } - } - - pool := client.NewPool() - defer testhelper.MustClose(t, pool) - - backupRoot := testhelper.TempDir(t) - sink := backup.NewFilesystemSink(backupRoot) - defer testhelper.MustClose(t, sink) - - locator, err := backup.ResolveLocator("pointer", sink) - require.NoError(t, err) - - fsBackup := backup.NewManager(sink, locator, pool) - - for storageName, repos := range tc.repos { - actualRepos, err := fsBackup.ListRepositories(ctx, &backup.ListRepositoriesRequest{ - Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, - StorageName: storageName, - }) - - require.NoError(t, err) - require.EqualValues(t, repos, actualRepos) - } - }) - } } func TestManager_Create(t *testing.T) { diff --git a/internal/backup/pipeline.go b/internal/backup/pipeline.go index 3eb91de91..5672493ac 100644 --- a/internal/backup/pipeline.go +++ b/internal/backup/pipeline.go @@ -16,8 +16,7 @@ import ( type Strategy interface { Create(context.Context, *CreateRequest) error Restore(context.Context, *RestoreRequest) error - ListRepositories(context.Context, *ListRepositoriesRequest) ([]*gitalypb.Repository, error) - RemoveRepository(context.Context, *RemoveRepositoryRequest) error + RemoveAllRepositories(context.Context, *RemoveAllRepositoriesRequest) error } // CreateRequest is the request to create a backup @@ -53,14 +52,9 @@ type RestoreRequest struct { BackupID string } -// RemoveRepositoryRequest is a request to remove an individual repository from its storage. -type RemoveRepositoryRequest struct { - Server storage.ServerInfo - Repo *gitalypb.Repository -} - -// ListRepositoriesRequest is the request to list repositories in a given storage. -type ListRepositoriesRequest struct { +// RemoveAllRepositoriesRequest is the request to remove all repositories in the specified +// storage name. +type RemoveAllRepositoriesRequest struct { Server storage.ServerInfo StorageName string } @@ -187,9 +181,6 @@ type Pipeline struct { pipelineError error cmdErrors *commandErrors - - processedRepos map[string]map[*gitalypb.Repository]struct{} - processedReposMu sync.Mutex } // NewPipeline creates a pipeline that executes backup and restore jobs. @@ -204,7 +195,6 @@ func NewPipeline(log log.Logger, opts ...PipelineOption) (*Pipeline, error) { done: make(chan struct{}), workersByStorage: make(map[string]chan *contextCommand), cmdErrors: &commandErrors{}, - processedRepos: make(map[string]map[*gitalypb.Repository]struct{}), } for _, opt := range opts { @@ -262,19 +252,19 @@ func (p *Pipeline) Handle(ctx context.Context, cmd Command) { } // Done waits for any in progress jobs to complete then reports any accumulated errors -func (p *Pipeline) Done() (processedRepos map[string]map[*gitalypb.Repository]struct{}, err error) { +func (p *Pipeline) Done() error { close(p.done) p.workerWg.Wait() if p.pipelineError != nil { - return nil, fmt.Errorf("pipeline: %w", p.pipelineError) + return fmt.Errorf("pipeline: %w", p.pipelineError) } if len(p.cmdErrors.errs) > 0 { - return nil, fmt.Errorf("pipeline: %w", p.cmdErrors) + return fmt.Errorf("pipeline: %w", p.cmdErrors) } - return p.processedRepos, nil + return nil } // getWorker finds the channel associated with a storage. When no channel is @@ -335,14 +325,6 @@ func (p *Pipeline) processCommand(ctx context.Context, cmd Command) { return } - storageName := cmd.Repository().StorageName - p.processedReposMu.Lock() - if _, ok := p.processedRepos[storageName]; !ok { - p.processedRepos[storageName] = make(map[*gitalypb.Repository]struct{}) - } - p.processedRepos[storageName][cmd.Repository()] = struct{}{} - p.processedReposMu.Unlock() - log.Info(fmt.Sprintf("completed %s", cmd.Name())) } diff --git a/internal/backup/pipeline_test.go b/internal/backup/pipeline_test.go index 37f7c2e5b..04c539a5f 100644 --- a/internal/backup/pipeline_test.go +++ b/internal/backup/pipeline_test.go @@ -98,8 +98,7 @@ func TestPipeline(t *testing.T) { p.Handle(ctx, NewCreateCommand(strategy, CreateRequest{Repository: &gitalypb.Repository{StorageName: "storage1"}})) p.Handle(ctx, NewCreateCommand(strategy, CreateRequest{Repository: &gitalypb.Repository{StorageName: "storage2"}})) } - _, err = p.Done() - require.NoError(t, err) + require.NoError(t, p.Done()) }) } }) @@ -116,16 +115,14 @@ func TestPipeline(t *testing.T) { p.Handle(ctx, NewCreateCommand(strategy, CreateRequest{Repository: &gitalypb.Repository{StorageName: "default"}})) - _, err = p.Done() - require.EqualError(t, err, "pipeline: context canceled") + require.EqualError(t, p.Done(), "pipeline: context canceled") }) } type MockStrategy struct { - CreateFunc func(context.Context, *CreateRequest) error - RestoreFunc func(context.Context, *RestoreRequest) error - RemoveRepositoryFunc func(context.Context, *RemoveRepositoryRequest) error - ListRepositoriesFunc func(context.Context, *ListRepositoriesRequest) ([]*gitalypb.Repository, error) + CreateFunc func(context.Context, *CreateRequest) error + RestoreFunc func(context.Context, *RestoreRequest) error + RemoveAllRepositoriesFunc func(context.Context, *RemoveAllRepositoriesRequest) error } func (s MockStrategy) Create(ctx context.Context, req *CreateRequest) error { @@ -142,20 +139,13 @@ func (s MockStrategy) Restore(ctx context.Context, req *RestoreRequest) error { return nil } -func (s MockStrategy) RemoveRepository(ctx context.Context, req *RemoveRepositoryRequest) error { - if s.RemoveRepositoryFunc != nil { - return s.RemoveRepositoryFunc(ctx, req) +func (s MockStrategy) RemoveAllRepositories(ctx context.Context, req *RemoveAllRepositoriesRequest) error { + if s.RemoveAllRepositoriesFunc != nil { + return s.RemoveAllRepositoriesFunc(ctx, req) } return nil } -func (s MockStrategy) ListRepositories(ctx context.Context, req *ListRepositoriesRequest) ([]*gitalypb.Repository, error) { - if s.ListRepositoriesFunc != nil { - return s.ListRepositoriesFunc(ctx, req) - } - return nil, nil -} - func testPipeline(t *testing.T, init func() *Pipeline) { strategy := MockStrategy{ CreateFunc: func(_ context.Context, req *CreateRequest) error { @@ -232,7 +222,7 @@ func testPipeline(t *testing.T, init func() *Pipeline) { require.Equal(t, tc.level, logEntry.Level) } - _, err := p.Done() + err := p.Done() if tc.level == logrus.ErrorLevel { require.EqualError(t, err, "pipeline: 1 failures encountered:\n - c.git: assert.AnError general error for testing\n") @@ -268,7 +258,7 @@ func testPipeline(t *testing.T, init func() *Pipeline) { for _, cmd := range commands { p.Handle(ctx, cmd) } - _, err := p.Done() + err := p.Done() require.EqualError(t, err, "pipeline: 1 failures encountered:\n - c.git: assert.AnError general error for testing\n") }) } @@ -319,34 +309,3 @@ func TestPipelineError(t *testing.T) { }) } } - -func TestPipelineProcessedRepos(t *testing.T) { - strategy := MockStrategy{} - - repos := map[string]map[*gitalypb.Repository]struct{}{ - "storage1": { - &gitalypb.Repository{RelativePath: "a.git", StorageName: "storage1"}: struct{}{}, - &gitalypb.Repository{RelativePath: "b.git", StorageName: "storage1"}: struct{}{}, - }, - "storage2": { - &gitalypb.Repository{RelativePath: "c.git", StorageName: "storage2"}: struct{}{}, - }, - "storage3": { - &gitalypb.Repository{RelativePath: "d.git", StorageName: "storage3"}: struct{}{}, - }, - } - - p, err := NewPipeline(testhelper.SharedLogger(t)) - require.NoError(t, err) - - ctx := testhelper.Context(t) - for _, v := range repos { - for repo := range v { - p.Handle(ctx, NewRestoreCommand(strategy, RestoreRequest{Repository: repo})) - } - } - - processedRepos, err := p.Done() - require.NoError(t, err) - require.EqualValues(t, repos, processedRepos) -} diff --git a/internal/backup/server_side.go b/internal/backup/server_side.go index a1a9a37eb..35654f215 100644 --- a/internal/backup/server_side.go +++ b/internal/backup/server_side.go @@ -2,9 +2,7 @@ package backup import ( "context" - "errors" "fmt" - "io" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/client" @@ -95,56 +93,25 @@ func (ss ServerSideAdapter) Restore(ctx context.Context, req *RestoreRequest) er return nil } -// RemoveRepository removes the specified repository from its storage. -func (ss ServerSideAdapter) RemoveRepository(ctx context.Context, req *RemoveRepositoryRequest) error { - if err := setContextServerInfo(ctx, &req.Server, req.Repo.StorageName); err != nil { - return fmt.Errorf("server-side remove repo: set context: %w", err) +// RemoveAllRepositories removes all repositories in the specified storage name. +func (ss ServerSideAdapter) RemoveAllRepositories(ctx context.Context, req *RemoveAllRepositoriesRequest) error { + if err := setContextServerInfo(ctx, &req.Server, req.StorageName); err != nil { + return fmt.Errorf("server-side remove all: %w", err) } repoClient, err := ss.newRepoClient(ctx, req.Server) if err != nil { - return fmt.Errorf("server-side remove repo: create client: %w", err) + return fmt.Errorf("server-side remove all: %w", err) } - _, err = repoClient.RemoveRepository(ctx, &gitalypb.RemoveRepositoryRequest{Repository: req.Repo}) + _, err = repoClient.RemoveAll(ctx, &gitalypb.RemoveAllRequest{StorageName: req.StorageName}) if err != nil { - return fmt.Errorf("server-side remove repo: remove: %w", err) + return fmt.Errorf("server-side remove all: %w", err) } return nil } -// ListRepositories returns a list of repositories found in the given storage. -func (ss ServerSideAdapter) ListRepositories(ctx context.Context, req *ListRepositoriesRequest) (repos []*gitalypb.Repository, err error) { - if err := setContextServerInfo(ctx, &req.Server, req.StorageName); err != nil { - return nil, fmt.Errorf("server-side list repos: set context: %w", err) - } - - internalClient, err := ss.newInternalClient(ctx, req.Server) - if err != nil { - return nil, fmt.Errorf("server-side list repos: create client: %w", err) - } - - stream, err := internalClient.WalkRepos(ctx, &gitalypb.WalkReposRequest{StorageName: req.StorageName}) - if err != nil { - return nil, fmt.Errorf("server-side list repos: walk: %w", err) - } - - for { - resp, err := stream.Recv() - if errors.Is(err, io.EOF) { - break - } - if err != nil { - return nil, err - } - - repos = append(repos, &gitalypb.Repository{RelativePath: resp.RelativePath, StorageName: req.StorageName}) - } - - return repos, nil -} - func (ss ServerSideAdapter) newRepoClient(ctx context.Context, server storage.ServerInfo) (gitalypb.RepositoryServiceClient, error) { conn, err := ss.pool.Dial(ctx, server.Address, server.Token) if err != nil { @@ -153,12 +120,3 @@ func (ss ServerSideAdapter) newRepoClient(ctx context.Context, server storage.Se return gitalypb.NewRepositoryServiceClient(conn), nil } - -func (ss ServerSideAdapter) newInternalClient(ctx context.Context, server storage.ServerInfo) (gitalypb.InternalGitalyClient, error) { - conn, err := ss.pool.Dial(ctx, server.Address, server.Token) - if err != nil { - return nil, err - } - - return gitalypb.NewInternalGitalyClient(conn), nil -} diff --git a/internal/backup/server_side_test.go b/internal/backup/server_side_test.go index 69669df60..2acc547c5 100644 --- a/internal/backup/server_side_test.go +++ b/internal/backup/server_side_test.go @@ -13,11 +13,9 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/setup" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/client" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" - "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testdb" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" ) @@ -259,15 +257,28 @@ func TestServerSideAdapter_Restore(t *testing.T) { } } -func TestServerSideAdapter_RemoveRepository(t *testing.T) { +func TestServerSideAdapter_RemoveAllRepositories(t *testing.T) { + testhelper.SkipWithWAL(t, ` +RemoveAll is removing the entire content of the storage. This would also remove the database's and +the transaction manager's disk state. The RPC needs to be updated to shut down all partitions and +the database and only then perform the removal. + +Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) + t.Parallel() - db := testdb.New(t) - db.TruncateAll(t) - datastore.NewPostgresRepositoryStore(db, map[string][]string{"virtual-storage": {"default"}}) + backupRoot := testhelper.TempDir(t) + sink := backup.NewFilesystemSink(backupRoot) + defer testhelper.MustClose(t, sink) + + locator, err := backup.ResolveLocator("pointer", sink) + require.NoError(t, err) cfg := testcfg.Build(t) - cfg.SocketPath = testserver.RunGitalyServer(t, cfg, setup.RegisterAll) + cfg.SocketPath = testserver.RunGitalyServer(t, cfg, setup.RegisterAll, + testserver.WithBackupSink(sink), + testserver.WithBackupLocator(locator), + ) ctx := testhelper.Context(t) @@ -278,103 +289,9 @@ func TestServerSideAdapter_RemoveRepository(t *testing.T) { defer testhelper.MustClose(t, pool) adapter := backup.NewServerSideAdapter(pool) - err := adapter.RemoveRepository(ctx, &backup.RemoveRepositoryRequest{ - Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, - Repo: repo, + err = adapter.RemoveAllRepositories(ctx, &backup.RemoveAllRepositoriesRequest{ + Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, + StorageName: repo.StorageName, }) require.NoError(t, err) - require.NoDirExists(t, repoPath) - - // With an invalid repository - err = adapter.RemoveRepository(ctx, &backup.RemoveRepositoryRequest{ - Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, - Repo: &gitalypb.Repository{StorageName: "default", RelativePath: "nonexistent"}, - }) - - require.EqualError(t, err, "server-side remove repo: remove: rpc error: code = NotFound desc = repository does not exist") -} - -func TestServerSideAdapter_ListRepositories(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - desc string - repos map[string][]*gitalypb.Repository - }{ - { - desc: "no repos", - repos: make(map[string][]*gitalypb.Repository), - }, - { - desc: "repos in a single storage", - repos: map[string][]*gitalypb.Repository{ - "storage-1": { - {RelativePath: "a", StorageName: "storage-1"}, - {RelativePath: "b", StorageName: "storage-1"}, - }, - }, - }, - { - desc: "repos in multiple storages", - repos: map[string][]*gitalypb.Repository{ - "storage-1": { - {RelativePath: "a", StorageName: "storage-1"}, - {RelativePath: "b", StorageName: "storage-1"}, - }, - "storage-2": { - {RelativePath: "c", StorageName: "storage-2"}, - {RelativePath: "d", StorageName: "storage-2"}, - }, - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - var storages []string - for storageName := range tc.repos { - storages = append(storages, storageName) - } - - db := testdb.New(t) - db.TruncateAll(t) - rs := datastore.NewPostgresRepositoryStore(db, map[string][]string{"virtual-storage": storages}) - - // We don't really need a "default" storage, but this makes initialisation cleaner since - // WithStorages() takes at least one argument. - cfg := testcfg.Build(t, testcfg.WithStorages("default", storages...)) - cfg.SocketPath = testserver.RunGitalyServer(t, cfg, setup.RegisterAll) - - ctx := testhelper.Context(t) - - repoID := 1 - for storageName, repos := range tc.repos { - for _, repo := range repos { - storagePath, ok := cfg.StoragePath(storageName) - require.True(t, ok) - - _, _ = gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{ - RelativePath: repo.RelativePath, - Storage: config.Storage{Name: storageName, Path: storagePath}, - }) - - require.NoError(t, rs.CreateRepository(ctx, int64(repoID), "virtual-storage", repo.RelativePath, repo.RelativePath, storageName, nil, nil, false, false)) - - repoID++ - } - } - - pool := client.NewPool() - defer testhelper.MustClose(t, pool) - - adapter := backup.NewServerSideAdapter(pool) - - for storageName, repos := range tc.repos { - actualRepos, err := adapter.ListRepositories(ctx, &backup.ListRepositoriesRequest{ - Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token}, - StorageName: storageName, - }) - require.NoError(t, err) - require.EqualValues(t, repos, actualRepos) - } - }) - } } diff --git a/internal/cli/gitalybackup/create.go b/internal/cli/gitalybackup/create.go index be7e75cdb..4ad653490 100644 --- a/internal/cli/gitalybackup/create.go +++ b/internal/cli/gitalybackup/create.go @@ -174,7 +174,7 @@ func (cmd *createSubcommand) run(ctx context.Context, logger log.Logger, stdin i })) } - if _, err := pipeline.Done(); err != nil { + if err := pipeline.Done(); err != nil { return fmt.Errorf("create: %w", err) } return nil diff --git a/internal/cli/gitalybackup/restore.go b/internal/cli/gitalybackup/restore.go index defffa223..de9e2cd3d 100644 --- a/internal/cli/gitalybackup/restore.go +++ b/internal/cli/gitalybackup/restore.go @@ -135,18 +135,15 @@ func (cmd *restoreSubcommand) run(ctx context.Context, logger log.Logger, stdin manager = backup.NewManager(sink, locator, pool) } - // Get the set of existing repositories keyed by storage. We'll later use this to determine any - // dangling repos that should be removed. - existingRepos := make(map[string][]*gitalypb.Repository) for _, storageName := range cmd.removeAllRepositories { - repos, err := manager.ListRepositories(ctx, &backup.ListRepositoriesRequest{ + err := manager.RemoveAllRepositories(ctx, &backup.RemoveAllRepositoriesRequest{ StorageName: storageName, }) if err != nil { - logger.WithError(err).WithField("storage_name", storageName).Warn("failed to list repositories") + // Treat RemoveAll failures as soft failures until we can determine + // how often it fails. + logger.WithError(err).WithField("storage_name", storageName).Warn("failed to remove all repositories") } - - existingRepos[storageName] = repos } var opts []backup.PipelineOption @@ -181,29 +178,8 @@ func (cmd *restoreSubcommand) run(ctx context.Context, logger log.Logger, stdin })) } - restoredRepos, err := pipeline.Done() - if err != nil { + if err := pipeline.Done(); err != nil { return fmt.Errorf("restore: %w", err) } - - var removalErrors []error - for storageName, repos := range existingRepos { - for _, repo := range repos { - if dangling := restoredRepos[storageName][repo]; dangling == struct{}{} { - // If we have dangling repos (those which exist in the storage but - // weren't part of the restore), they need to be deleted so the - // state of repos in Gitaly matches that in the Rails DB. - if err := manager.RemoveRepository(ctx, &backup.RemoveRepositoryRequest{Repo: repo}); err != nil { - removalErrors = append(removalErrors, fmt.Errorf("storage_name %q relative_path %q: %w", storageName, repo.RelativePath, err)) - } - } - } - } - - if len(removalErrors) > 0 { - return fmt.Errorf("remove dangling repositories: %d failures encountered: %w", - len(removalErrors), errors.Join(removalErrors...)) - } - return nil } diff --git a/internal/cli/gitalybackup/restore_test.go b/internal/cli/gitalybackup/restore_test.go index 6d235525c..4eae52e4c 100644 --- a/internal/cli/gitalybackup/restore_test.go +++ b/internal/cli/gitalybackup/restore_test.go @@ -75,6 +75,12 @@ Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) })) } + require.NoError(t, encoder.Encode(map[string]string{ + "address": "invalid", + "token": "invalid", + "relative_path": "invalid", + })) + ctx = testhelper.MergeIncomingMetadata(ctx, testcfg.GitalyServersMetadataFromCfg(t, cfg)) args := []string{ @@ -97,7 +103,9 @@ Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) require.DirExists(t, existRepoPath) - require.NoError(t, cmd.RunContext(ctx, args)) + require.EqualError(t, + cmd.RunContext(ctx, args), + "restore: pipeline: 1 failures encountered:\n - invalid: manager: could not dial source: invalid connection string: \"invalid\"\n") require.NoDirExists(t, existRepoPath) @@ -171,6 +179,12 @@ Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) })) } + require.NoError(t, encoder.Encode(map[string]string{ + "address": "invalid", + "token": "invalid", + "relative_path": "invalid", + })) + ctx = testhelper.MergeIncomingMetadata(ctx, testcfg.GitalyServersMetadataFromCfg(t, cfg)) args := []string{ @@ -193,7 +207,9 @@ Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) require.DirExists(t, existRepoPath) - require.NoError(t, cmd.RunContext(ctx, args)) + require.EqualError(t, + cmd.RunContext(ctx, args), + "restore: pipeline: 1 failures encountered:\n - invalid: server-side restore: could not dial source: invalid connection string: \"invalid\"\n") require.NoDirExists(t, existRepoPath) diff --git a/internal/featureflag/ff_return_structed_errors_in_revert.go b/internal/featureflag/ff_return_structed_errors_in_revert.go deleted file mode 100644 index 52efdae02..000000000 --- a/internal/featureflag/ff_return_structed_errors_in_revert.go +++ /dev/null @@ -1,13 +0,0 @@ -package featureflag - -// ReturnStructuredErrorsInUserRevert enables return structured errors in UserRevert. -// Modify the RPC UserRevert to return structured errors instead of -// inline errors. Modify the handling of the following four -// errors: 'Conflict', 'Changes Already Applied', 'Branch diverged', -// and 'CustomHookError'. Returns the corresponding structured error. -var ReturnStructuredErrorsInUserRevert = NewFeatureFlag( - "return_structured_errors_in_revert", - "v16.8.0", - "https://gitlab.com/gitlab-org/gitaly/-/issues/5752", - false, -) diff --git a/internal/git/catfile/commit.go b/internal/git/catfile/commit.go index 0af44fee8..94277bb10 100644 --- a/internal/git/catfile/commit.go +++ b/internal/git/catfile/commit.go @@ -14,7 +14,7 @@ import ( ) // GetCommit looks up a commit by revision using an existing Batch instance. -func GetCommit(ctx context.Context, objectReader ObjectContentReader, revision git.Revision) (*gitalypb.GitCommit, error) { +func GetCommit(ctx context.Context, objectReader ObjectContentReader, revision git.Revision) (*Commit, error) { object, err := objectReader.Object(ctx, revision+"^{commit}") if err != nil { return nil, err @@ -63,7 +63,7 @@ func GetCommitWithTrailers( } } - return commit, nil + return commit.GitCommit, nil } // GetCommitMessage looks up a commit message and returns it in its entirety. diff --git a/internal/git/catfile/commit_test.go b/internal/git/catfile/commit_test.go index 55d6012d9..d4a51457e 100644 --- a/internal/git/catfile/commit_test.go +++ b/internal/git/catfile/commit_test.go @@ -55,8 +55,11 @@ func TestGetCommit(t *testing.T) { } { t.Run(tc.desc, func(t *testing.T) { commit, err := GetCommit(ctx, objectReader, git.Revision(tc.revision)) - require.Equal(t, tc.expectedErr, err) - testhelper.ProtoEqual(t, tc.expectedCommit, commit) + if tc.expectedErr != nil || err != nil { + require.Equal(t, tc.expectedErr, err) + } else { + testhelper.ProtoEqual(t, tc.expectedCommit, commit.GitCommit) + } }) } } diff --git a/internal/git/catfile/parse_commit.go b/internal/git/catfile/parse_commit.go new file mode 100644 index 000000000..1b22d9d4a --- /dev/null +++ b/internal/git/catfile/parse_commit.go @@ -0,0 +1,252 @@ +package catfile + +import ( + "bytes" + "errors" + "fmt" + "io" + "strings" + + "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/helper" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" +) + +const ( + gpgSignaturePrefix = "gpgsig" + gpgSignaturePrefixSha256 = "gpgsig-sha256" +) + +// parseCommitState is a type used to define the current state while parsing +// a commit message. +// +// To understand the state macihne of parsing commit messages, we need +// to understand the different sections of a commit message. +// +// # Sections of a commit message +// +// Let's consider a sample commit message +// +// tree 798e5474fafac9754ee6b82ab17af8d70df4fbd3 +// parent 86f06b3f55e6334abb99fc168e2dd925895c4e49 +// author John doe <bugfixer@email.com> 1699964265 +0100 +// committer John doe <bugfixer@email.com> 1699964265 +0100 +// gpgsig -----BEGIN PGP SIGNATURE----- +// +// iHUEABYKAB0WIQReCOKeBZren2AFN0T+9BKLUsDX/wUCZVNlaQAKCRD+9BKLUsDX +// /219AP9j8jfQuLieg0Fl8xrOS74eJguYqIsPYI6lPDUvM5XmgQEAkhDUoWFd0ypR +// vXTEU/0CxcaXmlco/ThX2rCYwEUT6wA= +// =Wt+j +// -----END PGP SIGNATURE----- +// +// Commit subject +// +// With this, we can see that commit messages have +// - The first section consiting of headers. This is everything before +// commit message. In our example this consists of the tree, parent, +// author, committer and gpgsig. +// - The headers can also contain the signature. This is either gpgsig +// or gpgsig-256. +// - After the first line, all lines of the signature start with a ' ' +// space character. +// - Any headers post the signature are not parsed but will still be +// considered as part of the signature payload. +// - Post the headers, there is a newline to differentiate the upcoming +// commit body. The commit body consists of the commit subject and the +// message. +// +// Using this information we can now write a parser which represents a state +// machine which can be used to parse commits. +type parseCommitState uint + +const ( + parseCommitStateHeader parseCommitState = iota + parseCommitStateSignature + parseCommitStateUnexpected + parseCommitStateBody + parseCommitStateEnd +) + +// SignatureData holds the raw data used to validate a signed commit. +type SignatureData struct { + // Signatures refers to the signatures present in the commit. Note that + // Git only considers the first signature when parsing commits + Signatures [][]byte + // Payload refers to the commit data which is signed by the signature, + // generally this is everything apart from the signature in the commit. + // Headers present after the signature are not considered in the payload. + Payload []byte +} + +// Commit wraps the gitalypb.GitCommit structure and includes signature information. +type Commit struct { + *gitalypb.GitCommit + SignatureData SignatureData +} + +// ParseCommit implements a state machine to parse the various sections +// of a commit. To understand the state machine, see the definition +// for parseState above. +// +// The goal is to maintain feature parity with how git [1] (see +// parse_buffer_signed_by_header()) itself parses commits. This ensures +// that we throw errors only wherever git does. +// +// [1]: https://gitlab.com/gitlab-org/git/-/blob/master/commit.c +func (p *parser) ParseCommit(object git.Object) (*Commit, error) { + commit := &gitalypb.GitCommit{Id: object.ObjectID().String()} + var payload []byte + currentSignatureIndex := 0 + signatures := [][]byte{} + + bytesRemaining := object.ObjectSize() + p.bufferedReader.Reset(object) + + for state := parseCommitStateHeader; state != parseCommitStateEnd; { + receivedEOF := false + + line, err := p.bufferedReader.ReadString('\n') + if errors.Is(err, io.EOF) { + receivedEOF = true + } else if err != nil { + return nil, fmt.Errorf("parse raw commit: %w", err) + } + bytesRemaining -= int64(len(line)) + + // If the line only consists of a newline, we can skip + // the state to commit body. + if line == "\n" { + state = parseCommitStateBody + } + + switch state { + case parseCommitStateHeader: + key, value, ok := strings.Cut(line, " ") + if !ok { + // TODO: Current tests allow empty commits, we might want + // to change this behavior. + goto loopEnd + } + + // For headers, we trim the newline to make it easier + // to parse. + value = strings.TrimSuffix(value, "\n") + + switch key { + case "parent": + commit.ParentIds = append(commit.ParentIds, value) + case "author": + commit.Author = parseCommitAuthor(value) + case "committer": + commit.Committer = parseCommitAuthor(value) + case "tree": + commit.TreeId = value + case "encoding": + commit.Encoding = value + case gpgSignaturePrefix, gpgSignaturePrefixSha256: + // Since Git only considers the first signature, we only + // capture the first signature's type. + commit.SignatureType = detectSignatureType(value) + + state = parseCommitStateSignature + signatures = append(signatures, []byte(value+"\n")) + + goto loopEnd + } + + payload = append(payload, []byte(line)...) + + case parseCommitStateSignature: + if after, ok := strings.CutPrefix(line, " "); ok { + // All signature lines, must start with a ' ' (space). + signatures[currentSignatureIndex] = append(signatures[currentSignatureIndex], []byte(after)...) + goto loopEnd + } else { + currentSignatureIndex++ + + // Multiple signatures might be present in the commit. + if key, value, ok := strings.Cut(line, " "); ok { + if key == gpgSignaturePrefix || key == gpgSignaturePrefixSha256 { + signatures = append(signatures, []byte(value)) + goto loopEnd + } + } + + // If there is no ' ' (space), it means there is some unexpected + // data. + // + // Note that we don't go back to parsing headers. This is because + // any headers which are present after the signature are not parsed + // by Git as information. But, they still constitute to the signature + // payload. So any data after the signature and before the commit body + // is considered unexpected. + state = parseCommitStateUnexpected + } + + fallthrough + + case parseCommitStateUnexpected: + // If the line is only a newline, that means we have reached + // the commit body. If not, we keep looping till we do. + if line != "\n" { + payload = append(payload, []byte(line)...) + goto loopEnd + } + + fallthrough + + case parseCommitStateBody: + payload = append(payload, []byte(line)...) + + body := make([]byte, bytesRemaining) + if _, err := io.ReadFull(p.bufferedReader, body); err != nil { + return nil, fmt.Errorf("reading commit message: %w", err) + } + + // After we have copied the body, we must make sure that there really is no + // additional data. For once, this is to detect bugs in our implementation where we + // would accidentally have truncated the commit message. On the other hand, we also + // need to do this such that we observe the EOF, which we must observe in order to + // unblock reading the next object. + // + // This all feels a bit complicated, where it would be much easier to just read into + // a preallocated `bytes.Buffer`. But this complexity is indeed required to optimize + // allocations. So if you want to change this, please make sure to execute the + // `BenchmarkListAllCommits` benchmark. + if n, err := io.Copy(io.Discard, p.bufferedReader); err != nil { + return nil, fmt.Errorf("reading commit message: %w", err) + } else if n != 0 { + return nil, fmt.Errorf( + "commit message exceeds expected length %v by %v bytes", + object.ObjectSize(), n, + ) + } + + if len(body) > 0 { + commit.Subject = subjectFromBody(body) + commit.BodySize = int64(len(body)) + commit.Body = body + if max := helper.MaxCommitOrTagMessageSize; len(body) > max { + commit.Body = commit.Body[:max] + } + payload = append(payload, body...) + } + + state = parseCommitStateEnd + } + + loopEnd: + if receivedEOF { + state = parseCommitStateEnd + } + } + + for i, signature := range signatures { + signatures[i] = bytes.TrimSuffix(signature, []byte("\n")) + } + + return &Commit{ + GitCommit: commit, + SignatureData: SignatureData{Signatures: signatures, Payload: payload}, + }, nil +} diff --git a/internal/git/catfile/parse_commit_test.go b/internal/git/catfile/parse_commit_test.go new file mode 100644 index 000000000..2e80dc38f --- /dev/null +++ b/internal/git/catfile/parse_commit_test.go @@ -0,0 +1,531 @@ +package catfile + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" + "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + pgpSignature = `-----BEGIN PGP SIGNATURE----- +Version: ObjectivePGP +Comment: https://www.objectivepgp.com +Charset: UTF-8 + +wsFcBAABCgAGBQJecon1AAoJEDYMjTn1G2THmSsP/At/jskLdF0i7p0nKf4JLjeeqRJ4k2IUg87U +ZwV6mbLo5XFm8Sq7CJBAGAhlOZE4BAwKALuawmgs5XMEZwK2z6AIgosGTVpmxDTTI11bXt4XIOdz +qF7c/gUrJOZzjFXOqDsd5UuPRupwznC5eKlLbfImR+NYxKryo8JGdF5t52ph4kChcQsKlSkXuYNI ++9UgbaMclEjb0OLm+mcP9QxW+Cs9JS2Jb4Jh6XONWW1nDN3ZTDDskguIqqF47UxIgSImrmpMcEj9 +YSNU0oMoHM4+1DoXp1t99EGPoAMvO+a5g8gd1jouCIrI6KOX+GeG/TFFM0mQwg/d/N9LR049m8ed +vgqg/lMiWUxQGL2IPpYPcgiUEqfn7ete+NMzQV5zstxF/q7Yj2BhM2L7FPHxKaoy/w5Q/DcAO4wN +5gxVmIvbCDk5JOx8I+boIS8ZxSvIlJ5IWaPrcjg5Mc40it+WHvMqxVnCzH0c6KcXaJ2SibVb59HR +pdRhEXXw/hRN65l/xwyM8sklQalAGu755gNJZ4k9ApBVUssZyiu+te2+bDirAcmK8/x1jvMQY6bn +DFxBE7bMHDp24IFPaVID84Ryt3vSSBEkrUGm7OkyDESTpHCr4sfD5o3LCUCIibTqv/CAhe59mhbB +2AXL7X+EzylKy6C1N5KUUiMTW94AuF6f8FqBoxnf +=U6zM +-----END PGP SIGNATURE-----` + + sshSignature = `-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgtc+Qk8jhMwVZk/jFEFCM16LNQb +30q5kK30bbetfjyTMAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 +AAAAQADE1oOMKxqQu86XUQbhCoWx8GnnYHQ/i3mHdA0zPycIlDv8N6BRVDS6b0ja2Avj+s +uNvjRqSEGQJ4q6vhKOnQw= +-----END SSH SIGNATURE-----` +) + +func TestParseCommits(t *testing.T) { + t.Parallel() + + type setupData struct { + content string + oid git.ObjectID + expectedCommit *Commit + expectedErr error + } + + // Valid-but-interesting commits should be test at the FindCommit level. + // Invalid objects (that Git would complain about during fsck) can be + // tested here. + // + // Once a repository contains a pathological object it can be hard to get + // rid of it. Because of this I think it's nicer to ignore such objects + // than to throw hard errors. + for _, tc := range []struct { + desc string + setup func(t *testing.T) setupData + }{ + { + desc: "empty commit object", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{Id: gittest.DefaultObjectHash.EmptyTreeOID.String()}, + SignatureData: SignatureData{Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "no email", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Jane Doe", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{Name: []byte("Jane Doe")}, + }, + SignatureData: SignatureData{Payload: []byte("author Jane Doe"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "normal author", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Au Thor <au.thor@example.com> 1625121079 +0000", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Au Thor"), + Email: []byte("au.thor@example.com"), + Date: timestamppb.New(time.Unix(1625121079, 0)), + Timezone: []byte("+0000"), + }, + }, + SignatureData: SignatureData{Payload: []byte("author Au Thor <au.thor@example.com> 1625121079 +0000"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "author with missing mail", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Au Thor <> 1625121079 +0000", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Au Thor"), + Date: timestamppb.New(time.Unix(1625121079, 0)), + Timezone: []byte("+0000"), + }, + }, + SignatureData: SignatureData{Payload: []byte("author Au Thor <> 1625121079 +0000"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "author with missing date", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Au Thor <au.thor@example.com>", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Au Thor"), + Email: []byte("au.thor@example.com"), + }, + }, + SignatureData: SignatureData{Payload: []byte("author Au Thor <au.thor@example.com>"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "unmatched <", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Jane Doe <janedoe@example.com", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{Name: []byte("Jane Doe")}, + }, + SignatureData: SignatureData{Payload: []byte("author Jane Doe <janedoe@example.com"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "unmatched >", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Jane Doe janedoe@example.com>", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{Name: []byte("Jane Doe janedoe@example.com>")}, + }, + SignatureData: SignatureData{Payload: []byte("author Jane Doe janedoe@example.com>"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "date too high", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Jane Doe <janedoe@example.com> 9007199254740993 +0200", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Jane Doe"), + Email: []byte("janedoe@example.com"), + Date: ×tamppb.Timestamp{Seconds: 9223371974719179007}, + Timezone: []byte("+0200"), + }, + }, + SignatureData: SignatureData{Payload: []byte("author Jane Doe <janedoe@example.com> 9007199254740993 +0200"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "date negative", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "author Jane Doe <janedoe@example.com> -1 +0200", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Jane Doe"), + Email: []byte("janedoe@example.com"), + Date: ×tamppb.Timestamp{Seconds: 9223371974719179007}, + Timezone: []byte("+0200"), + }, + }, + SignatureData: SignatureData{Payload: []byte("author Jane Doe <janedoe@example.com> -1 +0200"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "huge", + setup: func(_ *testing.T) setupData { + repeat := strings.Repeat("A", 100000) + content := "author " + repeat + + return setupData{ + content: content, + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte(repeat), + }, + }, + SignatureData: SignatureData{Payload: []byte(content), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "has encoding", + setup: func(_ *testing.T) setupData { + return setupData{ + content: "encoding Windows-1251", + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Encoding: "Windows-1251", + }, + SignatureData: SignatureData{Payload: []byte("encoding Windows-1251"), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "PGP signed commit", + setup: func(_ *testing.T) setupData { + commitData, signedCommitData := createSignedCommitData(gpgSignaturePrefix, pgpSignature, "random commit message") + + return setupData{ + content: signedCommitData, + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + Committer: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + SignatureType: gitalypb.SignatureType_PGP, + TreeId: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Subject: []byte("random commit message"), + Body: []byte("random commit message\n"), + BodySize: 22, + }, + SignatureData: SignatureData{Payload: []byte(commitData), Signatures: [][]byte{[]byte(pgpSignature)}}, + }, + } + }, + }, + { + desc: "PGP SHA256-signed signed commit", + setup: func(_ *testing.T) setupData { + commitData, signedCommitData := createSignedCommitData(gpgSignaturePrefixSha256, pgpSignature, "random commit message") + + return setupData{ + content: signedCommitData, + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + Committer: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + SignatureType: gitalypb.SignatureType_PGP, + TreeId: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Subject: []byte("random commit message"), + Body: []byte("random commit message\n"), + BodySize: 22, + }, + SignatureData: SignatureData{Payload: []byte(commitData), Signatures: [][]byte{[]byte(pgpSignature)}}, + }, + } + }, + }, + { + desc: "SSH signed commit", + setup: func(_ *testing.T) setupData { + commitData, signedCommitData := createSignedCommitData(gpgSignaturePrefix, sshSignature, "random commit message") + + return setupData{ + content: signedCommitData, + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + Committer: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + SignatureType: gitalypb.SignatureType_SSH, + TreeId: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Subject: []byte("random commit message"), + Body: []byte("random commit message\n"), + BodySize: 22, + }, + SignatureData: SignatureData{Payload: []byte(commitData), Signatures: [][]byte{[]byte(sshSignature)}}, + }, + } + }, + }, + { + desc: "garbage signed commit", + setup: func(_ *testing.T) setupData { + _, signedCommitData := createSignedCommitData("gpgsig-garbage", sshSignature, "garbage-signed commit message") + + return setupData{ + content: signedCommitData, + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + Committer: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + TreeId: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Subject: []byte("garbage-signed commit message"), + Body: []byte("garbage-signed commit message\n"), + BodySize: 30, + }, + SignatureData: SignatureData{Payload: []byte(signedCommitData), Signatures: [][]byte{}}, + }, + } + }, + }, + { + desc: "commits with multiple signatures", + setup: func(_ *testing.T) setupData { + commitData, signedCommitData := createSignedCommitData("gpgsig", pgpSignature, "commit message") + + signatureLines := strings.Split(sshSignature, "\n") + for i, signatureLine := range signatureLines { + signatureLines[i] = " " + signatureLine + } + + signedCommitData = strings.Replace(signedCommitData, "\n\n", fmt.Sprintf("\n%s%s\n\n", "gpgsig-sha256", strings.Join(signatureLines, "\n")), 1) + + return setupData{ + content: signedCommitData, + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + Committer: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + SignatureType: gitalypb.SignatureType_PGP, + TreeId: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Subject: []byte("commit message"), + Body: []byte("commit message\n"), + BodySize: 15, + }, + SignatureData: SignatureData{Payload: []byte(commitData), Signatures: [][]byte{[]byte(pgpSignature), []byte(sshSignature)}}, + }, + } + }, + }, + { + desc: "PGP signed commit with headers after the signature", + setup: func(_ *testing.T) setupData { + commitMessage := "random commit message" + commitData, signedCommitData := createSignedCommitData(gpgSignaturePrefix, pgpSignature, "random commit message") + + // Headers after the signature shouldn't be ignored and should be + // part of the commit data. If ignored, malicious users can draft a + // commit similar to a previously signed commit but with additional + // headers and the new commit would still show as verified since we + // won't add the additional headers to commit data. + postSignatureHeader := fmt.Sprintf("parent %s", gittest.DefaultObjectHash.EmptyTreeOID) + modifyCommitData := func(data string) string { + return strings.Replace( + data, + fmt.Sprintf("\n%s", commitMessage), + fmt.Sprintf("%s\n\n%s", postSignatureHeader, commitMessage), + 1, + ) + } + + // We expect that these post signature headers are added to the commit data, + // that way any modified commit will fail verification. + signedCommitData = modifyCommitData(signedCommitData) + commitData = modifyCommitData(commitData) + + return setupData{ + content: signedCommitData, + oid: gittest.DefaultObjectHash.EmptyTreeOID, + expectedCommit: &Commit{ + GitCommit: &gitalypb.GitCommit{ + Id: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Author: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + Committer: &gitalypb.CommitAuthor{ + Name: []byte("Bug Fixer"), + Email: []byte("bugfixer@email.com"), + Date: ×tamppb.Timestamp{Seconds: 1584564725}, + Timezone: []byte("+0100"), + }, + SignatureType: gitalypb.SignatureType_PGP, + TreeId: gittest.DefaultObjectHash.EmptyTreeOID.String(), + Subject: []byte("random commit message"), + Body: []byte("random commit message\n"), + BodySize: 22, + }, + SignatureData: SignatureData{Payload: []byte(commitData), Signatures: [][]byte{[]byte(pgpSignature)}}, + }, + } + }, + }, + } { + tc := tc + + t.Run(tc.desc, func(t *testing.T) { + t.Parallel() + + setup := tc.setup(t) + + commit, err := NewParser().ParseCommit(newStaticObject(setup.content, "commit", setup.oid)) + require.Equal(t, setup.expectedErr, err) + testhelper.ProtoEqual(t, setup.expectedCommit.GitCommit, commit.GitCommit) + require.Equal(t, setup.expectedCommit.SignatureData.Payload, commit.SignatureData.Payload) + require.Equal(t, setup.expectedCommit.SignatureData.Signatures, commit.SignatureData.Signatures) + }) + } +} + +func createSignedCommitData(signatureField, signature, commitMessage string) (string, string) { + commitData := fmt.Sprintf(`tree %s +author Bug Fixer <bugfixer@email.com> 1584564725 +0100 +committer Bug Fixer <bugfixer@email.com> 1584564725 +0100 + +%s +`, gittest.DefaultObjectHash.EmptyTreeOID, commitMessage) + + // Each line of the signature needs to start with a space so that Git recognizes it as a continuation of the + // field. + signatureLines := strings.Split(signature, "\n") + for i, signatureLine := range signatureLines { + signatureLines[i] = " " + signatureLine + } + + signedCommitData := strings.Replace(commitData, "\n\n", fmt.Sprintf("\n%s%s\n\n", signatureField, strings.Join(signatureLines, "\n")), 1) + + return commitData, signedCommitData +} diff --git a/internal/git/catfile/parser.go b/internal/git/catfile/parser.go index 5df14954d..b64fe16eb 100644 --- a/internal/git/catfile/parser.go +++ b/internal/git/catfile/parser.go @@ -11,14 +11,13 @@ import ( "time" "gitlab.com/gitlab-org/gitaly/v16/internal/git" - "gitlab.com/gitlab-org/gitaly/v16/internal/helper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "google.golang.org/protobuf/types/known/timestamppb" ) // Parser parses Git objects into their gitalypb representations. type Parser interface { - ParseCommit(object git.Object) (*gitalypb.GitCommit, error) + ParseCommit(object git.Object) (*Commit, error) ParseTag(object git.Object) (*gitalypb.Tag, error) } @@ -37,95 +36,6 @@ func newParser() *parser { } } -// ParseCommit parses the commit data from the Reader. -func (p *parser) ParseCommit(object git.Object) (*gitalypb.GitCommit, error) { - commit := &gitalypb.GitCommit{Id: object.ObjectID().String()} - - var lastLine bool - p.bufferedReader.Reset(object) - - bytesRemaining := object.ObjectSize() - for !lastLine { - line, err := p.bufferedReader.ReadString('\n') - if errors.Is(err, io.EOF) { - lastLine = true - } else if err != nil { - return nil, fmt.Errorf("parse raw commit: header: %w", err) - } - bytesRemaining -= int64(len(line)) - - if len(line) == 0 || line[0] == ' ' { - continue - } - // A blank line indicates the start of the commit body - if line == "\n" { - break - } - - // There might not be a final line break if there was an EOF - if line[len(line)-1] == '\n' { - line = line[:len(line)-1] - } - - key, value, ok := strings.Cut(line, " ") - if !ok { - continue - } - - switch key { - case "parent": - commit.ParentIds = append(commit.ParentIds, value) - case "author": - commit.Author = parseCommitAuthor(value) - case "committer": - commit.Committer = parseCommitAuthor(value) - case "gpgsig", "gpgsig-sha256": - commit.SignatureType = detectSignatureType(value) - case "tree": - commit.TreeId = value - case "encoding": - commit.Encoding = value - } - } - - if !lastLine { - body := make([]byte, bytesRemaining) - if _, err := io.ReadFull(p.bufferedReader, body); err != nil { - return nil, fmt.Errorf("reading commit message: %w", err) - } - - // After we have copied the body, we must make sure that there really is no - // additional data. For once, this is to detect bugs in our implementation where we - // would accidentally have truncated the commit message. On the other hand, we also - // need to do this such that we observe the EOF, which we must observe in order to - // unblock reading the next object. - // - // This all feels a bit complicated, where it would be much easier to just read into - // a preallocated `bytes.Buffer`. But this complexity is indeed required to optimize - // allocations. So if you want to change this, please make sure to execute the - // `BenchmarkListAllCommits` benchmark. - if n, err := io.Copy(io.Discard, p.bufferedReader); err != nil { - return nil, fmt.Errorf("reading commit message: %w", err) - } else if n != 0 { - return nil, fmt.Errorf( - "commit message exceeds expected length %v by %v bytes", - object.ObjectSize(), n, - ) - } - - if len(body) > 0 { - commit.Subject = subjectFromBody(body) - commit.BodySize = int64(len(body)) - commit.Body = body - if max := helper.MaxCommitOrTagMessageSize; len(body) > max { - commit.Body = commit.Body[:max] - } - } - } - - return commit, nil -} - const maxUnixCommitDate = 1 << 53 // fallbackTimeValue is the value returned in case there is a parse error. It's the maximum diff --git a/internal/git/catfile/parser_test.go b/internal/git/catfile/parser_test.go index 6d2e6d53c..b54251965 100644 --- a/internal/git/catfile/parser_test.go +++ b/internal/git/catfile/parser_test.go @@ -1,215 +1,16 @@ package catfile import ( - "bytes" "fmt" - "strings" "testing" - "time" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" - "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "google.golang.org/protobuf/types/known/timestamppb" ) -func TestParser_ParseCommit(t *testing.T) { - t.Parallel() - - info := &ObjectInfo{ - Oid: gittest.DefaultObjectHash.EmptyTreeOID, - Type: "commit", - } - - // Valid-but-interesting commits should be test at the FindCommit level. - // Invalid objects (that Git would complain about during fsck) can be - // tested here. - // - // Once a repository contains a pathological object it can be hard to get - // rid of it. Because of this I think it's nicer to ignore such objects - // than to throw hard errors. - for _, tc := range []struct { - desc string - in string - out *gitalypb.GitCommit - }{ - { - desc: "empty commit object", - in: "", - out: &gitalypb.GitCommit{Id: info.Oid.String()}, - }, - { - desc: "no email", - in: "author Jane Doe", - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Author: &gitalypb.CommitAuthor{Name: []byte("Jane Doe")}, - }, - }, - { - desc: "unmatched <", - in: "author Jane Doe <janedoe@example.com", - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Author: &gitalypb.CommitAuthor{Name: []byte("Jane Doe")}, - }, - }, - { - desc: "unmatched >", - in: "author Jane Doe janedoe@example.com>", - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Author: &gitalypb.CommitAuthor{Name: []byte("Jane Doe janedoe@example.com>")}, - }, - }, - { - desc: "missing date", - in: "author Jane Doe <janedoe@example.com> ", - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Author: &gitalypb.CommitAuthor{Name: []byte("Jane Doe"), Email: []byte("janedoe@example.com")}, - }, - }, - { - desc: "date too high", - in: "author Jane Doe <janedoe@example.com> 9007199254740993 +0200", - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Author: &gitalypb.CommitAuthor{ - Name: []byte("Jane Doe"), - Email: []byte("janedoe@example.com"), - Date: ×tamppb.Timestamp{Seconds: 9223371974719179007}, - Timezone: []byte("+0200"), - }, - }, - }, - { - desc: "date negative", - in: "author Jane Doe <janedoe@example.com> -1 +0200", - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Author: &gitalypb.CommitAuthor{ - Name: []byte("Jane Doe"), - Email: []byte("janedoe@example.com"), - Date: ×tamppb.Timestamp{Seconds: 9223371974719179007}, - Timezone: []byte("+0200"), - }, - }, - }, - { - desc: "ssh signature", - in: `gpgsig -----BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgtc+Qk8jhMwVZk/jFEFCM16LNQb -30q5kK30bbetfjyTMAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 -AAAAQLSyv010gOFwIs9QTtDvlfIEWiAw2iQL/T9usGcxHXn/W5l0cOFCd7O+WaMDg0t0nW -fF3T79iV8paT4/OfX8Ygg= ------END SSH SIGNATURE-----`, - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - SignatureType: gitalypb.SignatureType_SSH, - }, - }, - { - desc: "SHA256 signature", - in: fmt.Sprintf(`gpgsig-sha256 -----BEGIN PGP SIGNATURE----- -Version: ObjectivePGP -Comment: https://www.objectivepgp.com -Charset: UTF-8 -%c -wsFcBAABCgAGBQJecon1AAoJEDYMjTn1G2THmSsP/At/jskLdF0i7p0nKf4JLjeeqRJ4k2IUg87U -ZwV6mbLo5XFm8Sq7CJBAGAhlOZE4BAwKALuawmgs5XMEZwK2z6AIgosGTVpmxDTTI11bXt4XIOdz -qF7c/gUrJOZzjFXOqDsd5UuPRupwznC5eKlLbfImR+NYxKryo8JGdF5t52ph4kChcQsKlSkXuYNI -+9UgbaMclEjb0OLm+mcP9QxW+Cs9JS2Jb4Jh6XONWW1nDN3ZTDDskguIqqF47UxIgSImrmpMcEj9 -YSNU0oMoHM4+1DoXp1t99EGPoAMvO+a5g8gd1jouCIrI6KOX+GeG/TFFM0mQwg/d/N9LR049m8ed -vgqg/lMiWUxQGL2IPpYPcgiUEqfn7ete+NMzQV5zstxF/q7Yj2BhM2L7FPHxKaoy/w5Q/DcAO4wN -5gxVmIvbCDk5JOx8I+boIS8ZxSvIlJ5IWaPrcjg5Mc40it+WHvMqxVnCzH0c6KcXaJ2SibVb59HR -pdRhEXXw/hRN65l/xwyM8sklQalAGu755gNJZ4k9ApBVUssZyiu+te2+bDirAcmK8/x1jvMQY6bn -DFxBE7bMHDp24IFPaVID84Ryt3vSSBEkrUGm7OkyDESTpHCr4sfD5o3LCUCIibTqv/CAhe59mhbB -2AXL7X+EzylKy6C1N5KUUiMTW94AuF6f8FqBoxnf -=U6zM ------END PGP SIGNATURE-----`, ' '), - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - SignatureType: gitalypb.SignatureType_PGP, - }, - }, - { - desc: "huge", - in: "author " + strings.Repeat("A", 100000), - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Author: &gitalypb.CommitAuthor{ - Name: bytes.Repeat([]byte("A"), 100000), - }, - }, - }, - { - desc: "has encoding", - in: "encoding Windows-1251", - out: &gitalypb.GitCommit{ - Id: info.Oid.String(), - Encoding: "Windows-1251", - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - info.Size = int64(len(tc.in)) - out, err := NewParser().ParseCommit(newStaticObject(tc.in, "commit", info.Oid)) - require.NoError(t, err, "parse error") - require.Equal(t, tc.out, out) - }) - } -} - -func TestParseCommitAuthor(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - desc string - author string - expected *gitalypb.CommitAuthor - }{ - { - desc: "empty author", - author: "", - expected: &gitalypb.CommitAuthor{}, - }, - { - desc: "normal author", - author: "Au Thor <au.thor@example.com> 1625121079 +0000", - expected: &gitalypb.CommitAuthor{ - Name: []byte("Au Thor"), - Email: []byte("au.thor@example.com"), - Date: timestamppb.New(time.Unix(1625121079, 0)), - Timezone: []byte("+0000"), - }, - }, - { - desc: "author with missing mail", - author: "Au Thor <> 1625121079 +0000", - expected: &gitalypb.CommitAuthor{ - Name: []byte("Au Thor"), - Date: timestamppb.New(time.Unix(1625121079, 0)), - Timezone: []byte("+0000"), - }, - }, - { - desc: "author with missing date", - author: "Au Thor <au.thor@example.com>", - expected: &gitalypb.CommitAuthor{ - Name: []byte("Au Thor"), - Email: []byte("au.thor@example.com"), - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - testhelper.ProtoEqual(t, tc.expected, parseCommitAuthor(tc.author)) - }) - } -} - func TestParser_ParseTag(t *testing.T) { t.Parallel() diff --git a/internal/git/catfile/tag.go b/internal/git/catfile/tag.go index 0dfbe8755..afce2f26e 100644 --- a/internal/git/catfile/tag.go +++ b/internal/git/catfile/tag.go @@ -61,15 +61,17 @@ func buildAnnotatedTag(ctx context.Context, objectReader ObjectContentReader, ob switch tagged.objectType { case "commit": - tag.TargetCommit, err = GetCommit(ctx, objectReader, git.Revision(tagged.objectID)) + commit, err := GetCommit(ctx, objectReader, git.Revision(tagged.objectID)) if err != nil { return nil, fmt.Errorf("buildAnnotatedTag error when getting target commit: %w", err) } + tag.TargetCommit = commit.GitCommit case "tag": - tag.TargetCommit, err = dereferenceTag(ctx, objectReader, git.Revision(tagged.objectID)) - if err != nil { + if commit, err := dereferenceTag(ctx, objectReader, git.Revision(tagged.objectID)); err != nil { return nil, fmt.Errorf("buildAnnotatedTag error when dereferencing tag: %w", err) + } else if commit != nil { + tag.TargetCommit = commit.GitCommit } } @@ -79,7 +81,7 @@ func buildAnnotatedTag(ctx context.Context, objectReader ObjectContentReader, ob // dereferenceTag recursively dereferences annotated tags until it finds a non-tag object. If it is // a commit, then it will parse and return this commit. Otherwise, if the tagged object is not a // commit, it will simply discard the object and not return an error. -func dereferenceTag(ctx context.Context, objectReader ObjectContentReader, oid git.Revision) (*gitalypb.GitCommit, error) { +func dereferenceTag(ctx context.Context, objectReader ObjectContentReader, oid git.Revision) (*Commit, error) { object, err := objectReader.Object(ctx, oid+"^{}") if err != nil { return nil, fmt.Errorf("peeling tag: %w", err) diff --git a/internal/git/localrepo/commit.go b/internal/git/localrepo/commit.go index df5effc2a..2f77069ef 100644 --- a/internal/git/localrepo/commit.go +++ b/internal/git/localrepo/commit.go @@ -68,7 +68,10 @@ func (repo *Repo) ReadCommit(ctx context.Context, revision git.Revision, opts .. if cfg.withTrailers { commit, err = catfile.GetCommitWithTrailers(ctx, repo.gitCmdFactory, repo, objectReader, revision) } else { - commit, err = catfile.GetCommit(ctx, objectReader, revision) + var c *catfile.Commit + if c, err = catfile.GetCommit(ctx, objectReader, revision); err == nil { + commit = c.GitCommit + } } if err != nil { diff --git a/internal/git/log/last_commit.go b/internal/git/log/last_commit.go index d92251b32..eb5333668 100644 --- a/internal/git/log/last_commit.go +++ b/internal/git/log/last_commit.go @@ -21,7 +21,7 @@ func LastCommitForPath( revision git.Revision, path string, options *gitalypb.GlobalOptions, -) (*gitalypb.GitCommit, error) { +) (*catfile.Commit, error) { var stdout strings.Builder cmd, err := gitCmdFactory.New(ctx, repo, git.Command{ Name: "log", diff --git a/internal/git/log/parser.go b/internal/git/log/parser.go index 1c9e9d566..dce154770 100644 --- a/internal/git/log/parser.go +++ b/internal/git/log/parser.go @@ -55,7 +55,7 @@ func (parser *Parser) Parse(ctx context.Context) bool { return false } - parser.currentCommit = commit + parser.currentCommit = commit.GitCommit return true } diff --git a/internal/gitaly/service/commit/commit_signatures.go b/internal/gitaly/service/commit/commit_signatures.go index 9dc5a9819..122f48c45 100644 --- a/internal/gitaly/service/commit/commit_signatures.go +++ b/internal/gitaly/service/commit/commit_signatures.go @@ -1,7 +1,6 @@ package commit import ( - "bufio" "bytes" "errors" "fmt" @@ -47,6 +46,7 @@ func (s *server) GetCommitSignatures(request *gitalypb.GetCommitSignaturesReques } } + parser := catfile.NewParser() for _, commitID := range request.CommitIds { commitObj, err := objectReader.Object(ctx, git.Revision(commitID)+"^{commit}") if err != nil { @@ -56,19 +56,26 @@ func (s *server) GetCommitSignatures(request *gitalypb.GetCommitSignaturesReques return structerr.NewInternal("%w", err) } - signatureKey, commitText, err := extractSignature(commitObj) + commit, err := parser.ParseCommit(commitObj) if err != nil { return structerr.NewInternal("%w", err) } + signature := []byte{} + if len(commit.SignatureData.Signatures) > 0 { + // While there could be potentially multiple signatures in a Git + // commit, like Git, we only consider the first. + signature = commit.SignatureData.Signatures[0] + } + signer := gitalypb.GetCommitSignaturesResponse_SIGNER_USER if signingKeys != nil { - if err := signingKeys.Verify(signatureKey, commitText); err == nil { + if err := signingKeys.Verify(signature, commit.SignatureData.Payload); err == nil { signer = gitalypb.GetCommitSignaturesResponse_SIGNER_SYSTEM } } - if err = sendResponse(commitID, signatureKey, commitText, signer, stream); err != nil { + if err = sendResponse(commitID, signature, commit.SignatureData.Payload, signer, stream); err != nil { return structerr.NewInternal("%w", err) } } @@ -76,55 +83,6 @@ func (s *server) GetCommitSignatures(request *gitalypb.GetCommitSignaturesReques return nil } -func extractSignature(reader io.Reader) ([]byte, []byte, error) { - commitText := []byte{} - signatureKey := []byte{} - sawSignature := false - inSignature := false - lineBreak := []byte("\n") - whiteSpace := []byte(" ") - bufferedReader := bufio.NewReader(reader) - - for { - line, err := bufferedReader.ReadBytes('\n') - - if errors.Is(err, io.EOF) { - commitText = append(commitText, line...) - break - } - if err != nil { - return nil, nil, err - } - - if !sawSignature && !inSignature { - for _, signatureField := range [][]byte{[]byte("gpgsig "), []byte("gpgsig-sha256 ")} { - if !bytes.HasPrefix(line, signatureField) { - continue - } - - sawSignature, inSignature = true, true - line = bytes.TrimPrefix(line, signatureField) - break - } - } - - if inSignature && !bytes.Equal(line, lineBreak) { - line = bytes.TrimPrefix(line, whiteSpace) - signatureKey = append(signatureKey, line...) - } else if inSignature { - inSignature = false - commitText = append(commitText, line...) - } else { - commitText = append(commitText, line...) - } - } - - // Remove last line break from signature - signatureKey = bytes.TrimSuffix(signatureKey, lineBreak) - - return signatureKey, commitText, nil -} - func sendResponse( commitID string, signatureKey []byte, diff --git a/internal/gitaly/service/commit/find_commits.go b/internal/gitaly/service/commit/find_commits.go index e2d717b25..15425330c 100644 --- a/internal/gitaly/service/commit/find_commits.go +++ b/internal/gitaly/service/commit/find_commits.go @@ -195,7 +195,7 @@ func (g *GetCommits) Commit(ctx context.Context, trailers, shortStat, refs bool) } } - return commit, nil + return commit.GitCommit, nil } func streamCommits(getCommits *GetCommits, stream gitalypb.CommitService_FindCommitsServer, trailers, shortStat bool, refs bool) error { diff --git a/internal/gitaly/service/commit/last_commit_for_path.go b/internal/gitaly/service/commit/last_commit_for_path.go index e0f69a97c..555a34e77 100644 --- a/internal/gitaly/service/commit/last_commit_for_path.go +++ b/internal/gitaly/service/commit/last_commit_for_path.go @@ -57,7 +57,7 @@ func (s *server) lastCommitForPath(ctx context.Context, in *gitalypb.LastCommitF return &gitalypb.LastCommitForPathResponse{}, nil } - return &gitalypb.LastCommitForPathResponse{Commit: commit}, err + return &gitalypb.LastCommitForPathResponse{Commit: commit.GitCommit}, err } func validateLastCommitForPathRequest(locator storage.Locator, in *gitalypb.LastCommitForPathRequest) error { diff --git a/internal/gitaly/service/commit/list_all_commits.go b/internal/gitaly/service/commit/list_all_commits.go index 0ee326c23..62633d6e5 100644 --- a/internal/gitaly/service/commit/list_all_commits.go +++ b/internal/gitaly/service/commit/list_all_commits.go @@ -79,7 +79,7 @@ func (s *server) ListAllCommits( return structerr.NewInternal("parsing commit: %w", err) } - if err := chunker.Send(commit); err != nil { + if err := chunker.Send(commit.GitCommit); err != nil { return structerr.NewInternal("sending commit: %w", err) } } diff --git a/internal/gitaly/service/commit/list_commits.go b/internal/gitaly/service/commit/list_commits.go index 1a16158a5..09f627873 100644 --- a/internal/gitaly/service/commit/list_commits.go +++ b/internal/gitaly/service/commit/list_commits.go @@ -139,7 +139,7 @@ func (s *server) ListCommits( return structerr.NewInternal("parsing commit: %w", err) } - if err := chunker.Send(commit); err != nil { + if err := chunker.Send(commit.GitCommit); err != nil { return structerr.NewInternal("sending commit: %w", err) } } diff --git a/internal/gitaly/service/commit/list_commits_by_oid.go b/internal/gitaly/service/commit/list_commits_by_oid.go index 3175c4307..f97c2aca5 100644 --- a/internal/gitaly/service/commit/list_commits_by_oid.go +++ b/internal/gitaly/service/commit/list_commits_by_oid.go @@ -50,7 +50,7 @@ func (s *server) ListCommitsByOid(in *gitalypb.ListCommitsByOidRequest, stream g return err } - if err := sender.Send(commit); err != nil { + if err := sender.Send(commit.GitCommit); err != nil { return err } } diff --git a/internal/gitaly/service/commit/list_commits_by_ref_name.go b/internal/gitaly/service/commit/list_commits_by_ref_name.go index e77c9f916..6c6d25b07 100644 --- a/internal/gitaly/service/commit/list_commits_by_ref_name.go +++ b/internal/gitaly/service/commit/list_commits_by_ref_name.go @@ -37,7 +37,7 @@ func (s *server) ListCommitsByRefName(in *gitalypb.ListCommitsByRefNameRequest, } commitByRef := &gitalypb.ListCommitsByRefNameResponse_CommitForRef{ - Commit: commit, RefName: refName, + Commit: commit.GitCommit, RefName: refName, } if err := sender.Send(commitByRef); err != nil { diff --git a/internal/gitaly/service/commit/list_last_commits_for_tree.go b/internal/gitaly/service/commit/list_last_commits_for_tree.go index fa7e7d0f7..85a5d2a69 100644 --- a/internal/gitaly/service/commit/list_last_commits_for_tree.go +++ b/internal/gitaly/service/commit/list_last_commits_for_tree.go @@ -74,7 +74,7 @@ func (s *server) listLastCommitsForTree(in *gitalypb.ListLastCommitsForTreeReque commitForTree := &gitalypb.ListLastCommitsForTreeResponse_CommitForTree{ PathBytes: []byte(entry.Path), - Commit: commit, + Commit: commit.GitCommit, } batch = append(batch, commitForTree) diff --git a/internal/gitaly/service/operations/revert.go b/internal/gitaly/service/operations/revert.go index 72e45dc8f..90d03a7dd 100644 --- a/internal/gitaly/service/operations/revert.go +++ b/internal/gitaly/service/operations/revert.go @@ -6,7 +6,6 @@ import ( "fmt" "time" - "gitlab.com/gitlab-org/gitaly/v16/internal/featureflag" "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/git/remoterepo" @@ -88,46 +87,22 @@ func (s *Server) UserRevert(ctx context.Context, req *gitalypb.UserRevertRequest if err != nil { var conflictErr *localrepo.MergeTreeConflictError if errors.As(err, &conflictErr) { - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - conflictingFiles := make([][]byte, 0, len(conflictErr.ConflictingFileInfo)) - for _, conflictingFileInfo := range conflictErr.ConflictingFileInfo { - conflictingFiles = append(conflictingFiles, []byte(conflictingFileInfo.FileName)) - } - return nil, structerr.NewFailedPrecondition("revert: there are conflicting files").WithDetail( - &gitalypb.UserRevertError{ - Error: &gitalypb.UserRevertError_MergeConflict{ - MergeConflict: &gitalypb.MergeConflictError{ - ConflictingFiles: conflictingFiles, - }, - }, - }) - } else { - return &gitalypb.UserRevertResponse{ - // it's better that this error matches the git2go for now - CreateTreeError: "revert: could not apply due to conflicts", - CreateTreeErrorCode: gitalypb.UserRevertResponse_CONFLICT, - }, nil - } + return &gitalypb.UserRevertResponse{ + // it's better that this error matches the git2go for now + CreateTreeError: "revert: could not apply due to conflicts", + CreateTreeErrorCode: gitalypb.UserRevertResponse_CONFLICT, + }, nil } return nil, structerr.NewInternal("merge-tree: %w", err) } if oursCommit.TreeId == treeOID.String() { - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - return nil, structerr.NewFailedPrecondition("revert: could not apply because the result was empty").WithDetail( - &gitalypb.UserRevertError{ - Error: &gitalypb.UserRevertError_ChangesAlreadyApplied{ - ChangesAlreadyApplied: &gitalypb.ChangesAlreadyAppliedError{}, - }, - }) - } else { - return &gitalypb.UserRevertResponse{ - // it's better that this error matches the git2go for now - CreateTreeError: "revert: could not apply because the result was empty", - CreateTreeErrorCode: gitalypb.UserRevertResponse_EMPTY, - }, nil - } + return &gitalypb.UserRevertResponse{ + // it's better that this error matches the git2go for now + CreateTreeError: "revert: could not apply because the result was empty", + CreateTreeErrorCode: gitalypb.UserRevertResponse_EMPTY, + }, nil } newrev, err = quarantineRepo.WriteCommit( @@ -191,39 +166,18 @@ func (s *Server) UserRevert(ctx context.Context, req *gitalypb.UserRevertRequest return nil, structerr.NewInternal("checking for ancestry: %w", err) } if !ancestor { - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - return nil, structerr.NewFailedPrecondition("revert: branch diverged").WithDetail( - &gitalypb.UserRevertError{ - Error: &gitalypb.UserRevertError_NotAncestor{ - NotAncestor: &gitalypb.NotAncestorError{ - ParentRevision: []byte(oldrev.Revision()), - ChildRevision: []byte(newrev.Revision()), - }, - }, - }) - } else { - return &gitalypb.UserRevertResponse{ - CommitError: "Branch diverged", - }, nil - } + return &gitalypb.UserRevertResponse{ + CommitError: "Branch diverged", + }, nil } } if err := s.updateReferenceWithHooks(ctx, req.GetRepository(), req.User, quarantineDir, referenceName, newrev, oldrev); err != nil { var customHookErr updateref.CustomHookError if errors.As(err, &customHookErr) { - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - return nil, structerr.NewPermissionDenied("revert: custom hook error").WithDetail( - &gitalypb.UserRevertError{ - Error: &gitalypb.UserRevertError_CustomHook{ - CustomHook: customHookErr.Proto(), - }, - }) - } else { - return &gitalypb.UserRevertResponse{ - PreReceiveError: customHookErr.Error(), - }, nil - } + return &gitalypb.UserRevertResponse{ + PreReceiveError: customHookErr.Error(), + }, nil } return nil, fmt.Errorf("update reference with hooks: %w", err) diff --git a/internal/gitaly/service/operations/revert_test.go b/internal/gitaly/service/operations/revert_test.go index 754bf0748..225669662 100644 --- a/internal/gitaly/service/operations/revert_test.go +++ b/internal/gitaly/service/operations/revert_test.go @@ -19,8 +19,6 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -429,7 +427,6 @@ func TestServer_UserRevert_quarantine(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertQuarantine) } @@ -471,22 +468,9 @@ func testServerUserRevertQuarantine(t *testing.T, ctx context.Context) { Message: []byte("Reverting " + revertedCommit.Id), Timestamp: ×tamppb.Timestamp{Seconds: 12345}, }) - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - expectedError := structerr.NewPermissionDenied("revert: custom hook error").WithDetail( - &gitalypb.UserRevertError{ - Error: &gitalypb.UserRevertError_CustomHook{ - CustomHook: &gitalypb.CustomHookError{ - HookType: gitalypb.CustomHookError_HOOK_TYPE_PRERECEIVE, - }, - }, - }) - testhelper.RequireGrpcError(t, expectedError, err) - } else { - require.NoError(t, err) - require.NotNil(t, response) - require.NotEmpty(t, response.PreReceiveError) - - } + require.NoError(t, err) + require.NotNil(t, response) + require.NotEmpty(t, response.PreReceiveError) objectHash, err := repo.ObjectHash(ctx) require.NoError(t, err) @@ -615,7 +599,6 @@ func TestServer_UserRevert_stableID(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertStableID) } @@ -669,10 +652,8 @@ func testServerUserRevertStableID(t *testing.T, ctx context.Context) { "sha256": "28b57208e72bc2317143571997b9cfc444a51b52a43dde1c0282633a2b60de71", }), }, response.BranchUpdate) - if !featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - require.Empty(t, response.CreateTreeError) - require.Empty(t, response.CreateTreeErrorCode) - } + require.Empty(t, response.CreateTreeError) + require.Empty(t, response.CreateTreeErrorCode) // headCommit is pointed commit after revert headCommit, err := repo.ReadCommit(ctx, git.Revision(git.DefaultBranch)) @@ -714,7 +695,6 @@ func TestServer_UserRevert_successfulIntoEmptyRepo(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertSuccessfulIntoEmptyRepo) } @@ -772,10 +752,8 @@ func testServerUserRevertSuccessfulIntoEmptyRepo(t *testing.T, ctx context.Conte } require.Equal(t, expectedBranchUpdate, response.BranchUpdate) - if !featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - require.Empty(t, response.CreateTreeError) - require.Empty(t, response.CreateTreeErrorCode) - } + require.Empty(t, response.CreateTreeError) + require.Empty(t, response.CreateTreeErrorCode) require.Equal(t, request.Message, headCommit.Subject) require.Equal(t, revertedCommit.Id, headCommit.ParentIds[0]) gittest.RequireTree(t, cfg, repoPath, response.BranchUpdate.CommitId, @@ -789,7 +767,6 @@ func TestServer_UserRevert_successfulGitHooks(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertSuccessfulGitHooks) } @@ -829,9 +806,7 @@ func testServerUserRevertSuccessfulGitHooks(t *testing.T, ctx context.Context) { response, err := client.UserRevert(ctx, request) require.NoError(t, err) - if !featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - require.Empty(t, response.PreReceiveError) - } + require.Empty(t, response.PreReceiveError) headCommit, err := repo.ReadCommit(ctx, git.Revision(destinationBranch)) require.NoError(t, err) gittest.RequireTree(t, cfg, repoPath, headCommit.Id, nil) @@ -847,7 +822,6 @@ func TestServer_UserRevert_failedDueToPreReceiveError(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertFailedDueToPreReceiveError) } @@ -885,19 +859,9 @@ func testServerUserRevertFailedDueToPreReceiveError(t *testing.T, ctx context.Co t.Run(hookName, func(t *testing.T) { gittest.WriteCustomHook(t, repoPath, hookName, hookContent) - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - _, err := client.UserRevert(ctx, request) - actualStatus, _ := status.FromError(err) - require.Equal(t, actualStatus.Code(), codes.PermissionDenied) - require.Equal(t, actualStatus.Message(), "revert: custom hook error") - revertError, ok := actualStatus.Details()[0].(*gitalypb.UserRevertError) - require.True(t, ok) - require.Contains(t, revertError.GetCustomHook().String(), "GL_ID="+gittest.TestUser.GlId) - } else { - response, err := client.UserRevert(ctx, request) - require.NoError(t, err) - require.Contains(t, response.PreReceiveError, "GL_ID="+gittest.TestUser.GlId) - } + response, err := client.UserRevert(ctx, request) + require.NoError(t, err) + require.Contains(t, response.PreReceiveError, "GL_ID="+gittest.TestUser.GlId) }) } } @@ -907,7 +871,6 @@ func TestServer_UserRevert_failedDueToCreateTreeErrorConflict(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertFailedDueToCreateTreeErrorConflict) } @@ -954,20 +917,10 @@ func testServerUserRevertFailedDueToCreateTreeErrorConflict(t *testing.T, ctx co Message: []byte("Reverting " + revertedCommit.Id), } - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - _, err = client.UserRevert(ctx, request) - actualStatus, _ := status.FromError(err) - require.Equal(t, actualStatus.Code(), codes.FailedPrecondition) - require.Equal(t, actualStatus.Message(), "revert: there are conflicting files") - revertError, ok := actualStatus.Details()[0].(*gitalypb.UserRevertError) - require.True(t, ok) - require.NotNil(t, revertError.GetMergeConflict()) - } else { - response, err := client.UserRevert(ctx, request) - require.NoError(t, err) - require.NotEmpty(t, response.CreateTreeError) - require.Equal(t, gitalypb.UserRevertResponse_CONFLICT, response.CreateTreeErrorCode) - } + response, err := client.UserRevert(ctx, request) + require.NoError(t, err) + require.NotEmpty(t, response.CreateTreeError) + require.Equal(t, gitalypb.UserRevertResponse_CONFLICT, response.CreateTreeErrorCode) } func TestServer_UserRevert_failedDueToCreateTreeErrorEmpty(t *testing.T) { @@ -975,7 +928,6 @@ func TestServer_UserRevert_failedDueToCreateTreeErrorEmpty(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertFailedDueToCreateTreeErrorEmpty) } @@ -1037,25 +989,13 @@ func testServerUserRevertFailedDueToCreateTreeErrorEmpty(t *testing.T, ctx conte response, err := client.UserRevert(ctx, request) require.NoError(t, err) + require.Empty(t, response.CreateTreeError) + require.Equal(t, gitalypb.UserRevertResponse_NONE, response.CreateTreeErrorCode) - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - _, err = client.UserRevert(ctx, request) - - expectedError := structerr.NewFailedPrecondition("revert: could not apply because the result was empty").WithDetail( - &gitalypb.UserRevertError{ - Error: &gitalypb.UserRevertError_ChangesAlreadyApplied{}, - }) - testhelper.RequireGrpcError(t, expectedError, err) - } else { - require.NoError(t, err) - require.Empty(t, response.CreateTreeError) - require.Equal(t, gitalypb.UserRevertResponse_NONE, response.CreateTreeErrorCode) - - response, err = client.UserRevert(ctx, request) - require.NoError(t, err) - require.NotEmpty(t, response.CreateTreeError) - require.Equal(t, gitalypb.UserRevertResponse_EMPTY, response.CreateTreeErrorCode) - } + response, err = client.UserRevert(ctx, request) + require.NoError(t, err) + require.NotEmpty(t, response.CreateTreeError) + require.Equal(t, gitalypb.UserRevertResponse_EMPTY, response.CreateTreeErrorCode) } func TestServer_UserRevert_failedDueToCommitError(t *testing.T) { @@ -1063,7 +1003,6 @@ func TestServer_UserRevert_failedDueToCommitError(t *testing.T) { testhelper.NewFeatureSets( featureflag.GPGSigning, - featureflag.ReturnStructuredErrorsInUserRevert, ).Run(t, testServerUserRevertFailedDueToCommitError) } @@ -1106,17 +1045,8 @@ func testServerUserRevertFailedDueToCommitError(t *testing.T, ctx context.Contex Message: []byte("Reverting " + revertedCommit.Id), StartBranchName: []byte(sourceBranch), } - response, err := client.UserRevert(ctx, request) - if featureflag.ReturnStructuredErrorsInUserRevert.IsEnabled(ctx) { - actualStatus, _ := status.FromError(err) - require.Equal(t, actualStatus.Code(), codes.FailedPrecondition) - require.Equal(t, actualStatus.Message(), "revert: branch diverged") - revertError, ok := actualStatus.Details()[0].(*gitalypb.UserRevertError) - require.True(t, ok) - require.NotNil(t, revertError.GetNotAncestor()) - } else { - require.NoError(t, err) - require.Equal(t, "Branch diverged", response.CommitError) - } + response, err := client.UserRevert(ctx, request) + require.NoError(t, err) + require.Equal(t, "Branch diverged", response.CommitError) } diff --git a/internal/gitaly/service/operations/tags.go b/internal/gitaly/service/operations/tags.go index 83b2d7b1f..bc78ca810 100644 --- a/internal/gitaly/service/operations/tags.go +++ b/internal/gitaly/service/operations/tags.go @@ -331,7 +331,7 @@ func (s *Server) createTag( if err != nil { return nil, "", structerr.NewInternal("getting commit: %w", err) } - tagObject.TargetCommit = peeledTargetCommit + tagObject.TargetCommit = peeledTargetCommit.GitCommit } return tagObject, refObjectID, nil diff --git a/internal/gitaly/service/ref/find_all_tags.go b/internal/gitaly/service/ref/find_all_tags.go index 2091b0011..e58917c15 100644 --- a/internal/gitaly/service/ref/find_all_tags.go +++ b/internal/gitaly/service/ref/find_all_tags.go @@ -100,10 +100,11 @@ func (s *server) findAllTags(ctx context.Context, repo *localrepo.Repo, sortFiel // which refers to a commit object. Otherwise, we discard the object's // contents. if peeledTag.ObjectType() == "commit" { - result.TargetCommit, err = parser.ParseCommit(peeledTag) + commit, err := parser.ParseCommit(peeledTag) if err != nil { return fmt.Errorf("parsing tagged commit: %w", err) } + result.TargetCommit = commit.GitCommit } else { if _, err := io.Copy(io.Discard, peeledTag); err != nil { return fmt.Errorf("discarding tagged object contents: %w", err) @@ -117,7 +118,7 @@ func (s *server) findAllTags(ctx context.Context, repo *localrepo.Repo, sortFiel result = &gitalypb.Tag{ Id: tag.ObjectID().String(), - TargetCommit: commit, + TargetCommit: commit.GitCommit, } default: if _, err := io.Copy(io.Discard, tag); err != nil { diff --git a/internal/gitaly/service/ref/find_tag.go b/internal/gitaly/service/ref/find_tag.go index 69f3d93f8..1c700bd65 100644 --- a/internal/gitaly/service/ref/find_tag.go +++ b/internal/gitaly/service/ref/find_tag.go @@ -57,7 +57,7 @@ func parseTagLine(ctx context.Context, objectReader catfile.ObjectContentReader, if err != nil { return nil, fmt.Errorf("getting commit catfile: %w", err) } - tag.TargetCommit = commit + tag.TargetCommit = commit.GitCommit return tag, nil default: return tag, nil diff --git a/internal/gitaly/service/ref/util.go b/internal/gitaly/service/ref/util.go index 4f90c3b0d..144d83308 100644 --- a/internal/gitaly/service/ref/util.go +++ b/internal/gitaly/service/ref/util.go @@ -35,7 +35,7 @@ func buildAllBranchesBranch(ctx context.Context, objectReader catfile.ObjectCont return &gitalypb.FindAllBranchesResponse_Branch{ Name: elements[0], - Target: target, + Target: target.GitCommit, }, nil } @@ -47,7 +47,7 @@ func buildBranch(ctx context.Context, objectReader catfile.ObjectContentReader, return &gitalypb.Branch{ Name: elements[0], - TargetCommit: target, + TargetCommit: target.GitCommit, }, nil } diff --git a/internal/gitaly/service/repository/remove_all_test.go b/internal/gitaly/service/repository/remove_all_test.go index fd913523a..785f54b01 100644 --- a/internal/gitaly/service/repository/remove_all_test.go +++ b/internal/gitaly/service/repository/remove_all_test.go @@ -28,7 +28,6 @@ Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) require.DirExists(t, repo1Path) require.DirExists(t, repo1Path) - //nolint:staticcheck _, err := client.RemoveAll(ctx, &gitalypb.RemoveAllRequest{ StorageName: cfg.Storages[0].Name, }) diff --git a/internal/praefect/datastore/repository_store.go b/internal/praefect/datastore/repository_store.go index 4925fcb50..77dce6ba0 100644 --- a/internal/praefect/datastore/repository_store.go +++ b/internal/praefect/datastore/repository_store.go @@ -111,8 +111,6 @@ type RepositoryStore interface { MarkVirtualStorageUnverified(ctx context.Context, virtualStorage string) (int64, error) // MarkStorageUnverified marsk all replicas on the storage as unverified. MarkStorageUnverified(ctx context.Context, virtualStorage, storage string) (int64, error) - // ListRepositoryPaths retrieves the relative path for all repositories present on the given virtual storage. - ListRepositoryPaths(ctx context.Context, virtualStorage string) ([]string, error) } // PostgresRepositoryStore is a Postgres implementation of RepositoryStore. @@ -918,28 +916,3 @@ func (rs *PostgresRepositoryStore) GetReplicaPath(ctx context.Context, repositor return replicaPath, nil } - -// ListRepositoryPaths retrieves the relative path for all repositories present on the given virtual storage. -func (rs *PostgresRepositoryStore) ListRepositoryPaths(ctx context.Context, virtualStorage string) ([]string, error) { - rows, err := rs.db.QueryContext(ctx, ` -SELECT relative_path -FROM repositories -WHERE virtual_storage = $1 -`, virtualStorage) - if err != nil { - return nil, fmt.Errorf("query: %w", err) - } - defer rows.Close() - - var relativePaths []string - for rows.Next() { - var relativePath string - if err := rows.Scan(&relativePath); err != nil { - return nil, fmt.Errorf("scan: %w", err) - } - - relativePaths = append(relativePaths, relativePath) - } - - return relativePaths, rows.Err() -} diff --git a/internal/praefect/remove_all.go b/internal/praefect/remove_all.go index 9c383cd0e..9fa08206f 100644 --- a/internal/praefect/remove_all.go +++ b/internal/praefect/remove_all.go @@ -32,7 +32,6 @@ func RemoveAllHandler(rs datastore.RepositoryStore, conns Connections) grpc.Stre conn := conn group.Go(func() error { - //nolint:staticcheck _, err := gitalypb.NewRepositoryServiceClient(conn).RemoveAll(ctx, &gitalypb.RemoveAllRequest{ StorageName: rewrittenStorage, }) diff --git a/internal/praefect/remove_all_test.go b/internal/praefect/remove_all_test.go index 6b5e6f848..965ffb95b 100644 --- a/internal/praefect/remove_all_test.go +++ b/internal/praefect/remove_all_test.go @@ -96,7 +96,6 @@ Issue: https://gitlab.com/gitlab-org/gitaly/-/issues/5269`) _, err = client.RepositorySize(ctx, &gitalypb.RepositorySizeRequest{Repository: &gitalypb.Repository{}}) testhelper.RequireGrpcError(t, errServedByGitaly, err) - //nolint:staticcheck resp, err := client.RemoveAll(ctx, &gitalypb.RemoveAllRequest{StorageName: virtualStorage}) require.NoError(t, err) diff --git a/internal/praefect/server.go b/internal/praefect/server.go index c52b160f5..54cbee079 100644 --- a/internal/praefect/server.go +++ b/internal/praefect/server.go @@ -195,9 +195,6 @@ func NewGRPCServer( "DeleteObjectPool": DeleteObjectPoolHandler(deps.RepositoryStore, deps.Logger, deps.Conns), "GetObjectPool": GetObjectPoolHandler(deps.RepositoryStore, deps.Router), }) - proxy.RegisterStreamHandlers(srv, "gitaly.InternalGitaly", map[string]grpc.StreamHandler{ - "WalkRepos": WalkReposHandler(deps.RepositoryStore), - }) } return srv diff --git a/internal/praefect/walkrepos.go b/internal/praefect/walkrepos.go deleted file mode 100644 index 1f321a4c7..000000000 --- a/internal/praefect/walkrepos.go +++ /dev/null @@ -1,47 +0,0 @@ -package praefect - -import ( - "fmt" - - "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" - "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" - "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" - "google.golang.org/grpc" -) - -// WalkReposHandler implements an interceptor for the WalkRepos RPC, invoked when calling -// through Praefect. Instead of walking the storage directory in the filesystem, this Praefect -// implementation queries the database for all known repositories in the given virtual storage. -// As a consequence, the modification_time parameter can't be populated in the response. -func WalkReposHandler(rs datastore.RepositoryStore) grpc.StreamHandler { - return func(srv interface{}, stream grpc.ServerStream) error { - sendRepo := func(relPath string) error { - return stream.SendMsg(&gitalypb.WalkReposResponse{ - RelativePath: relPath, - }) - } - - var req gitalypb.WalkReposRequest - if err := stream.RecvMsg(&req); err != nil { - return fmt.Errorf("receive request: %w", err) - } - - if req.StorageName == "" { - return structerr.NewInvalidArgument("%w", storage.ErrStorageNotSet) - } - - repos, err := rs.ListRepositoryPaths(stream.Context(), req.StorageName) - if err != nil { - return structerr.NewInternal("list repository paths: %w", err) - } - - for _, repo := range repos { - if err := sendRepo(repo); err != nil { - return structerr.NewInternal("send repository path: %w", err) - } - } - - return nil - } -} diff --git a/internal/praefect/walkrepos_test.go b/internal/praefect/walkrepos_test.go deleted file mode 100644 index 63301caf5..000000000 --- a/internal/praefect/walkrepos_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package praefect - -import ( - "net" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" - "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/protoregistry" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/config" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" - "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" - "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" - "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testdb" - "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -func TestWalkReposHandler(t *testing.T) { - t.Parallel() - - db := testdb.New(t) - for _, tc := range []struct { - desc string - request *gitalypb.WalkReposRequest - responses []*gitalypb.WalkReposResponse - expectedErr error - }{ - { - desc: "missing storage name", - request: &gitalypb.WalkReposRequest{}, - expectedErr: structerr.NewInvalidArgument("%w", storage.ErrStorageNotSet), - }, - { - desc: "repositories found", - request: &gitalypb.WalkReposRequest{StorageName: "virtual-storage"}, - responses: []*gitalypb.WalkReposResponse{ - {RelativePath: "relative-path"}, - {RelativePath: "relative-path-2"}, - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - db.TruncateAll(t) - rs := datastore.NewPostgresRepositoryStore(db, map[string][]string{"virtual-storage": {"storage"}}) - ctx := testhelper.Context(t) - - require.NoError(t, rs.CreateRepository(ctx, 0, "virtual-storage", "relative-path", "relative-path", "storage", nil, nil, false, false)) - require.NoError(t, rs.CreateRepository(ctx, 1, "virtual-storage", "relative-path-2", "relative-path-2", "storage", nil, nil, false, false)) - - tmp := testhelper.TempDir(t) - - ln, err := net.Listen("unix", filepath.Join(tmp, "praefect")) - require.NoError(t, err) - - srv := NewGRPCServer(&Dependencies{ - Config: config.Config{Failover: config.Failover{ElectionStrategy: config.ElectionStrategyPerRepository}}, - Logger: testhelper.SharedLogger(t), - RepositoryStore: rs, - Registry: protoregistry.GitalyProtoPreregistered, - }, nil) - defer srv.Stop() - - go testhelper.MustServe(t, srv, ln) - - clientConn, err := grpc.DialContext(ctx, "unix://"+ln.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) - require.NoError(t, err) - defer testhelper.MustClose(t, clientConn) - - client := gitalypb.NewInternalGitalyClient(clientConn) - - stream, err := client.WalkRepos(ctx, tc.request) - if tc.expectedErr != nil { - // Consume the first message and test for errors only if we're expecting an error. - _, err = stream.Recv() - testhelper.RequireGrpcError(t, tc.expectedErr, err) - return - } - require.NoError(t, err) - - actualRepos, err := testhelper.Receive(stream.Recv) - require.NoError(t, err) - testhelper.ProtoEqual(t, tc.responses, actualRepos) - }) - } -} diff --git a/proto/go/gitalypb/operations.pb.go b/proto/go/gitalypb/operations.pb.go index f0a62bf94..ce8526742 100644 --- a/proto/go/gitalypb/operations.pb.go +++ b/proto/go/gitalypb/operations.pb.go @@ -138,7 +138,7 @@ func (x UserCommitFilesActionHeader_ActionType) Number() protoreflect.EnumNumber // Deprecated: Use UserCommitFilesActionHeader_ActionType.Descriptor instead. func (UserCommitFilesActionHeader_ActionType) EnumDescriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{29, 0} + return file_operations_proto_rawDescGZIP(), []int{28, 0} } // UserCreateBranchRequest is a request for the UserCreateBranch RPC. @@ -2538,120 +2538,6 @@ func (x *UserRevertResponse) GetCreateTreeErrorCode() UserRevertResponse_CreateT return UserRevertResponse_NONE } -// UserRevertError is an error returned by the UserRevert RPC. -type UserRevertError struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Error: - // - // *UserRevertError_MergeConflict - // *UserRevertError_ChangesAlreadyApplied - // *UserRevertError_CustomHook - // *UserRevertError_NotAncestor - Error isUserRevertError_Error `protobuf_oneof:"error"` -} - -func (x *UserRevertError) Reset() { - *x = UserRevertError{} - if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UserRevertError) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UserRevertError) ProtoMessage() {} - -func (x *UserRevertError) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[28] - 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 UserRevertError.ProtoReflect.Descriptor instead. -func (*UserRevertError) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{28} -} - -func (m *UserRevertError) GetError() isUserRevertError_Error { - if m != nil { - return m.Error - } - return nil -} - -func (x *UserRevertError) GetMergeConflict() *MergeConflictError { - if x, ok := x.GetError().(*UserRevertError_MergeConflict); ok { - return x.MergeConflict - } - return nil -} - -func (x *UserRevertError) GetChangesAlreadyApplied() *ChangesAlreadyAppliedError { - if x, ok := x.GetError().(*UserRevertError_ChangesAlreadyApplied); ok { - return x.ChangesAlreadyApplied - } - return nil -} - -func (x *UserRevertError) GetCustomHook() *CustomHookError { - if x, ok := x.GetError().(*UserRevertError_CustomHook); ok { - return x.CustomHook - } - return nil -} - -func (x *UserRevertError) GetNotAncestor() *NotAncestorError { - if x, ok := x.GetError().(*UserRevertError_NotAncestor); ok { - return x.NotAncestor - } - return nil -} - -type isUserRevertError_Error interface { - isUserRevertError_Error() -} - -type UserRevertError_MergeConflict struct { - // merge_conflict is returned if there is a conflict when applying the revert. - MergeConflict *MergeConflictError `protobuf:"bytes,1,opt,name=merge_conflict,json=mergeConflict,proto3,oneof"` -} - -type UserRevertError_ChangesAlreadyApplied struct { - // changes_already_applied is returned if the result after applying the revert is empty. - ChangesAlreadyApplied *ChangesAlreadyAppliedError `protobuf:"bytes,2,opt,name=changes_already_applied,json=changesAlreadyApplied,proto3,oneof"` -} - -type UserRevertError_CustomHook struct { - // custom_hook contains the error message if the pre-receive hook failed. - CustomHook *CustomHookError `protobuf:"bytes,3,opt,name=custom_hook,json=customHook,proto3,oneof"` -} - -type UserRevertError_NotAncestor struct { - // not_ancestor is returned if the old tip of the target branch is not an ancestor of the new commit. - NotAncestor *NotAncestorError `protobuf:"bytes,4,opt,name=not_ancestor,json=notAncestor,proto3,oneof"` -} - -func (*UserRevertError_MergeConflict) isUserRevertError_Error() {} - -func (*UserRevertError_ChangesAlreadyApplied) isUserRevertError_Error() {} - -func (*UserRevertError_CustomHook) isUserRevertError_Error() {} - -func (*UserRevertError_NotAncestor) isUserRevertError_Error() {} - // UserCommitFilesActionHeader contains the details of the action to be performed. type UserCommitFilesActionHeader struct { state protoimpl.MessageState @@ -2688,7 +2574,7 @@ type UserCommitFilesActionHeader struct { func (x *UserCommitFilesActionHeader) Reset() { *x = UserCommitFilesActionHeader{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[29] + mi := &file_operations_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2701,7 +2587,7 @@ func (x *UserCommitFilesActionHeader) String() string { func (*UserCommitFilesActionHeader) ProtoMessage() {} func (x *UserCommitFilesActionHeader) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[29] + mi := &file_operations_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2714,7 +2600,7 @@ func (x *UserCommitFilesActionHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use UserCommitFilesActionHeader.ProtoReflect.Descriptor instead. func (*UserCommitFilesActionHeader) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{29} + return file_operations_proto_rawDescGZIP(), []int{28} } func (x *UserCommitFilesActionHeader) GetAction() UserCommitFilesActionHeader_ActionType { @@ -2775,7 +2661,7 @@ type UserCommitFilesAction struct { func (x *UserCommitFilesAction) Reset() { *x = UserCommitFilesAction{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[30] + mi := &file_operations_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2788,7 +2674,7 @@ func (x *UserCommitFilesAction) String() string { func (*UserCommitFilesAction) ProtoMessage() {} func (x *UserCommitFilesAction) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[30] + mi := &file_operations_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2801,7 +2687,7 @@ func (x *UserCommitFilesAction) ProtoReflect() protoreflect.Message { // Deprecated: Use UserCommitFilesAction.ProtoReflect.Descriptor instead. func (*UserCommitFilesAction) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{30} + return file_operations_proto_rawDescGZIP(), []int{29} } func (m *UserCommitFilesAction) GetUserCommitFilesActionPayload() isUserCommitFilesAction_UserCommitFilesActionPayload { @@ -2898,7 +2784,7 @@ type UserCommitFilesRequestHeader struct { func (x *UserCommitFilesRequestHeader) Reset() { *x = UserCommitFilesRequestHeader{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[31] + mi := &file_operations_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2911,7 +2797,7 @@ func (x *UserCommitFilesRequestHeader) String() string { func (*UserCommitFilesRequestHeader) ProtoMessage() {} func (x *UserCommitFilesRequestHeader) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[31] + mi := &file_operations_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2924,7 +2810,7 @@ func (x *UserCommitFilesRequestHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use UserCommitFilesRequestHeader.ProtoReflect.Descriptor instead. func (*UserCommitFilesRequestHeader) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{31} + return file_operations_proto_rawDescGZIP(), []int{30} } func (x *UserCommitFilesRequestHeader) GetRepository() *Repository { @@ -3027,7 +2913,7 @@ type UserCommitFilesRequest struct { func (x *UserCommitFilesRequest) Reset() { *x = UserCommitFilesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[32] + mi := &file_operations_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3040,7 +2926,7 @@ func (x *UserCommitFilesRequest) String() string { func (*UserCommitFilesRequest) ProtoMessage() {} func (x *UserCommitFilesRequest) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[32] + mi := &file_operations_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3053,7 +2939,7 @@ func (x *UserCommitFilesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UserCommitFilesRequest.ProtoReflect.Descriptor instead. func (*UserCommitFilesRequest) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{32} + return file_operations_proto_rawDescGZIP(), []int{31} } func (m *UserCommitFilesRequest) GetUserCommitFilesRequestPayload() isUserCommitFilesRequest_UserCommitFilesRequestPayload { @@ -3114,7 +3000,7 @@ type UserCommitFilesResponse struct { func (x *UserCommitFilesResponse) Reset() { *x = UserCommitFilesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[33] + mi := &file_operations_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3127,7 +3013,7 @@ func (x *UserCommitFilesResponse) String() string { func (*UserCommitFilesResponse) ProtoMessage() {} func (x *UserCommitFilesResponse) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[33] + mi := &file_operations_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3140,7 +3026,7 @@ func (x *UserCommitFilesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UserCommitFilesResponse.ProtoReflect.Descriptor instead. func (*UserCommitFilesResponse) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{33} + return file_operations_proto_rawDescGZIP(), []int{32} } func (x *UserCommitFilesResponse) GetBranchUpdate() *OperationBranchUpdate { @@ -3182,7 +3068,7 @@ type UserCommitFilesError struct { func (x *UserCommitFilesError) Reset() { *x = UserCommitFilesError{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[34] + mi := &file_operations_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3195,7 +3081,7 @@ func (x *UserCommitFilesError) String() string { func (*UserCommitFilesError) ProtoMessage() {} func (x *UserCommitFilesError) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[34] + mi := &file_operations_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3208,7 +3094,7 @@ func (x *UserCommitFilesError) ProtoReflect() protoreflect.Message { // Deprecated: Use UserCommitFilesError.ProtoReflect.Descriptor instead. func (*UserCommitFilesError) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{34} + return file_operations_proto_rawDescGZIP(), []int{33} } func (m *UserCommitFilesError) GetError() isUserCommitFilesError_Error { @@ -3282,7 +3168,7 @@ type UserRebaseConfirmableRequest struct { func (x *UserRebaseConfirmableRequest) Reset() { *x = UserRebaseConfirmableRequest{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[35] + mi := &file_operations_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3295,7 +3181,7 @@ func (x *UserRebaseConfirmableRequest) String() string { func (*UserRebaseConfirmableRequest) ProtoMessage() {} func (x *UserRebaseConfirmableRequest) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[35] + mi := &file_operations_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3308,7 +3194,7 @@ func (x *UserRebaseConfirmableRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UserRebaseConfirmableRequest.ProtoReflect.Descriptor instead. func (*UserRebaseConfirmableRequest) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{35} + return file_operations_proto_rawDescGZIP(), []int{34} } func (m *UserRebaseConfirmableRequest) GetUserRebaseConfirmableRequestPayload() isUserRebaseConfirmableRequest_UserRebaseConfirmableRequestPayload { @@ -3370,7 +3256,7 @@ type UserRebaseConfirmableResponse struct { func (x *UserRebaseConfirmableResponse) Reset() { *x = UserRebaseConfirmableResponse{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[36] + mi := &file_operations_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3383,7 +3269,7 @@ func (x *UserRebaseConfirmableResponse) String() string { func (*UserRebaseConfirmableResponse) ProtoMessage() {} func (x *UserRebaseConfirmableResponse) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[36] + mi := &file_operations_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3396,7 +3282,7 @@ func (x *UserRebaseConfirmableResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UserRebaseConfirmableResponse.ProtoReflect.Descriptor instead. func (*UserRebaseConfirmableResponse) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{36} + return file_operations_proto_rawDescGZIP(), []int{35} } func (m *UserRebaseConfirmableResponse) GetUserRebaseConfirmableResponsePayload() isUserRebaseConfirmableResponse_UserRebaseConfirmableResponsePayload { @@ -3472,7 +3358,7 @@ type UserSquashRequest struct { func (x *UserSquashRequest) Reset() { *x = UserSquashRequest{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[37] + mi := &file_operations_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3485,7 +3371,7 @@ func (x *UserSquashRequest) String() string { func (*UserSquashRequest) ProtoMessage() {} func (x *UserSquashRequest) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[37] + mi := &file_operations_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3498,7 +3384,7 @@ func (x *UserSquashRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSquashRequest.ProtoReflect.Descriptor instead. func (*UserSquashRequest) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{37} + return file_operations_proto_rawDescGZIP(), []int{36} } func (x *UserSquashRequest) GetRepository() *Repository { @@ -3563,7 +3449,7 @@ type UserSquashResponse struct { func (x *UserSquashResponse) Reset() { *x = UserSquashResponse{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[38] + mi := &file_operations_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3576,7 +3462,7 @@ func (x *UserSquashResponse) String() string { func (*UserSquashResponse) ProtoMessage() {} func (x *UserSquashResponse) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[38] + mi := &file_operations_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3589,7 +3475,7 @@ func (x *UserSquashResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSquashResponse.ProtoReflect.Descriptor instead. func (*UserSquashResponse) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{38} + return file_operations_proto_rawDescGZIP(), []int{37} } func (x *UserSquashResponse) GetSquashSha() string { @@ -3615,7 +3501,7 @@ type UserRebaseConfirmableError struct { func (x *UserRebaseConfirmableError) Reset() { *x = UserRebaseConfirmableError{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[39] + mi := &file_operations_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3628,7 +3514,7 @@ func (x *UserRebaseConfirmableError) String() string { func (*UserRebaseConfirmableError) ProtoMessage() {} func (x *UserRebaseConfirmableError) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[39] + mi := &file_operations_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3641,7 +3527,7 @@ func (x *UserRebaseConfirmableError) ProtoReflect() protoreflect.Message { // Deprecated: Use UserRebaseConfirmableError.ProtoReflect.Descriptor instead. func (*UserRebaseConfirmableError) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{39} + return file_operations_proto_rawDescGZIP(), []int{38} } func (m *UserRebaseConfirmableError) GetError() isUserRebaseConfirmableError_Error { @@ -3702,7 +3588,7 @@ type UserSquashError struct { func (x *UserSquashError) Reset() { *x = UserSquashError{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[40] + mi := &file_operations_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3715,7 +3601,7 @@ func (x *UserSquashError) String() string { func (*UserSquashError) ProtoMessage() {} func (x *UserSquashError) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[40] + mi := &file_operations_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3728,7 +3614,7 @@ func (x *UserSquashError) ProtoReflect() protoreflect.Message { // Deprecated: Use UserSquashError.ProtoReflect.Descriptor instead. func (*UserSquashError) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{40} + return file_operations_proto_rawDescGZIP(), []int{39} } func (m *UserSquashError) GetError() isUserSquashError_Error { @@ -3788,7 +3674,7 @@ type UserApplyPatchRequest struct { func (x *UserApplyPatchRequest) Reset() { *x = UserApplyPatchRequest{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[41] + mi := &file_operations_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3801,7 +3687,7 @@ func (x *UserApplyPatchRequest) String() string { func (*UserApplyPatchRequest) ProtoMessage() {} func (x *UserApplyPatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[41] + mi := &file_operations_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3814,7 +3700,7 @@ func (x *UserApplyPatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UserApplyPatchRequest.ProtoReflect.Descriptor instead. func (*UserApplyPatchRequest) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{41} + return file_operations_proto_rawDescGZIP(), []int{40} } func (m *UserApplyPatchRequest) GetUserApplyPatchRequestPayload() isUserApplyPatchRequest_UserApplyPatchRequestPayload { @@ -3870,7 +3756,7 @@ type UserApplyPatchResponse struct { func (x *UserApplyPatchResponse) Reset() { *x = UserApplyPatchResponse{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[42] + mi := &file_operations_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3883,7 +3769,7 @@ func (x *UserApplyPatchResponse) String() string { func (*UserApplyPatchResponse) ProtoMessage() {} func (x *UserApplyPatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[42] + mi := &file_operations_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3896,7 +3782,7 @@ func (x *UserApplyPatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UserApplyPatchResponse.ProtoReflect.Descriptor instead. func (*UserApplyPatchResponse) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{42} + return file_operations_proto_rawDescGZIP(), []int{41} } func (x *UserApplyPatchResponse) GetBranchUpdate() *OperationBranchUpdate { @@ -3944,7 +3830,7 @@ type UserUpdateSubmoduleRequest struct { func (x *UserUpdateSubmoduleRequest) Reset() { *x = UserUpdateSubmoduleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[43] + mi := &file_operations_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3957,7 +3843,7 @@ func (x *UserUpdateSubmoduleRequest) String() string { func (*UserUpdateSubmoduleRequest) ProtoMessage() {} func (x *UserUpdateSubmoduleRequest) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[43] + mi := &file_operations_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3970,7 +3856,7 @@ func (x *UserUpdateSubmoduleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UserUpdateSubmoduleRequest.ProtoReflect.Descriptor instead. func (*UserUpdateSubmoduleRequest) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{43} + return file_operations_proto_rawDescGZIP(), []int{42} } func (x *UserUpdateSubmoduleRequest) GetRepository() *Repository { @@ -4047,7 +3933,7 @@ type UserUpdateSubmoduleResponse struct { func (x *UserUpdateSubmoduleResponse) Reset() { *x = UserUpdateSubmoduleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[44] + mi := &file_operations_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4060,7 +3946,7 @@ func (x *UserUpdateSubmoduleResponse) String() string { func (*UserUpdateSubmoduleResponse) ProtoMessage() {} func (x *UserUpdateSubmoduleResponse) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[44] + mi := &file_operations_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4073,7 +3959,7 @@ func (x *UserUpdateSubmoduleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UserUpdateSubmoduleResponse.ProtoReflect.Descriptor instead. func (*UserUpdateSubmoduleResponse) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{44} + return file_operations_proto_rawDescGZIP(), []int{43} } func (x *UserUpdateSubmoduleResponse) GetBranchUpdate() *OperationBranchUpdate { @@ -4137,7 +4023,7 @@ type UserRebaseConfirmableRequest_Header struct { func (x *UserRebaseConfirmableRequest_Header) Reset() { *x = UserRebaseConfirmableRequest_Header{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[45] + mi := &file_operations_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4150,7 +4036,7 @@ func (x *UserRebaseConfirmableRequest_Header) String() string { func (*UserRebaseConfirmableRequest_Header) ProtoMessage() {} func (x *UserRebaseConfirmableRequest_Header) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[45] + mi := &file_operations_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4163,7 +4049,7 @@ func (x *UserRebaseConfirmableRequest_Header) ProtoReflect() protoreflect.Messag // Deprecated: Use UserRebaseConfirmableRequest_Header.ProtoReflect.Descriptor instead. func (*UserRebaseConfirmableRequest_Header) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{35, 0} + return file_operations_proto_rawDescGZIP(), []int{34, 0} } func (x *UserRebaseConfirmableRequest_Header) GetRepository() *Repository { @@ -4260,7 +4146,7 @@ type UserApplyPatchRequest_Header struct { func (x *UserApplyPatchRequest_Header) Reset() { *x = UserApplyPatchRequest_Header{} if protoimpl.UnsafeEnabled { - mi := &file_operations_proto_msgTypes[46] + mi := &file_operations_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4273,7 +4159,7 @@ func (x *UserApplyPatchRequest_Header) String() string { func (*UserApplyPatchRequest_Header) ProtoMessage() {} func (x *UserApplyPatchRequest_Header) ProtoReflect() protoreflect.Message { - mi := &file_operations_proto_msgTypes[46] + mi := &file_operations_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4286,7 +4172,7 @@ func (x *UserApplyPatchRequest_Header) ProtoReflect() protoreflect.Message { // Deprecated: Use UserApplyPatchRequest_Header.ProtoReflect.Descriptor instead. func (*UserApplyPatchRequest_Header) Descriptor() ([]byte, []int) { - return file_operations_proto_rawDescGZIP(), []int{41, 0} + return file_operations_proto_rawDescGZIP(), []int{40, 0} } func (x *UserApplyPatchRequest_Header) GetRepository() *Repository { @@ -4708,386 +4594,367 @@ var file_operations_proto_rawDesc = []byte{ 0x61, 0x74, 0x65, 0x54, 0x72, 0x65, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x4f, 0x4e, 0x46, 0x4c, 0x49, 0x43, 0x54, 0x10, 0x02, 0x22, - 0xb8, 0x02, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x12, 0x43, 0x0a, 0x0e, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, - 0x63, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x12, 0x5c, 0x0a, 0x17, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x5f, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x61, 0x70, 0x70, 0x6c, - 0x69, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, - 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, - 0x15, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x41, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x41, - 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x0b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x5f, 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, - 0x6f, 0x6b, 0x12, 0x3d, 0x0a, 0x0c, 0x6e, 0x6f, 0x74, 0x5f, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x74, - 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x4e, 0x6f, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x6e, 0x6f, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, - 0x72, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xf5, 0x02, 0x0a, 0x1b, 0x55, - 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x06, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x62, 0x61, - 0x73, 0x65, 0x36, 0x34, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x46, 0x69, - 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x66, 0x65, 0x72, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, - 0x6e, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x0a, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45, - 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, - 0x44, 0x49, 0x52, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, - 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4f, 0x56, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x48, 0x4d, 0x4f, 0x44, - 0x10, 0x05, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x06, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x22, 0x0a, 0x20, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xa2, 0x04, 0x0a, 0x1c, - 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x0a, + 0xf5, 0x02, 0x0a, 0x1b, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x46, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x2e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x72, 0x65, + 0x76, 0x69, 0x6f, 0x75, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x73, + 0x65, 0x36, 0x34, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, + 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, + 0x6e, 0x66, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x22, 0x55, 0x0a, 0x0a, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, + 0x0a, 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x52, + 0x45, 0x41, 0x54, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x50, + 0x44, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4f, 0x56, 0x45, 0x10, 0x03, + 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, + 0x43, 0x48, 0x4d, 0x4f, 0x44, 0x10, 0x05, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x3d, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 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, 0x22, 0x0a, 0x20, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x22, 0xa2, 0x04, 0x0a, 0x1c, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, + 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, + 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, + 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x11, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, + 0x61, 0x69, 0x6c, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x62, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x3d, 0x0a, 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0f, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x68, + 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, + 0x61, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x65, + 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6c, 0x64, 0x5f, 0x6f, 0x69, 0x64, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4f, + 0x6c, 0x64, 0x4f, 0x69, 0x64, 0x22, 0xb6, 0x01, 0x0a, 0x16, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x3e, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x37, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, + 0x00, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x23, 0x0a, 0x21, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xaa, + 0x01, 0x0a, 0x17, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x52, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xd3, 0x01, 0x0a, 0x14, + 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x12, 0x3d, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x12, 0x37, 0x0a, 0x0c, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, + 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0b, + 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, + 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x22, 0xb1, 0x04, 0x0a, 0x1c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x45, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, + 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x05, 0x61, 0x70, 0x70, + 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, + 0x79, 0x1a, 0x86, 0x03, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x62, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, - 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, - 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x2a, - 0x0a, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x10, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, - 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x12, 0x38, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x09, 0x72, 0x65, 0x62, 0x61, + 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, + 0x08, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x73, 0x68, 0x61, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x53, 0x68, 0x61, + 0x12, 0x3f, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, + 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x69, 0x74, 0x5f, 0x70, 0x75, + 0x73, 0x68, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0e, 0x67, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x29, 0x0a, 0x27, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, + 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xbf, 0x01, 0x0a, 0x1d, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x72, 0x65, 0x62, 0x61, 0x73, + 0x65, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x72, + 0x65, 0x62, 0x61, 0x73, 0x65, 0x53, 0x68, 0x61, 0x12, 0x27, 0x0a, 0x0e, 0x72, 0x65, 0x62, 0x61, + 0x73, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x00, 0x52, 0x0d, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, + 0x64, 0x42, 0x2a, 0x0a, 0x28, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4a, 0x04, 0x08, + 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x11, 0x70, 0x72, 0x65, 0x5f, 0x72, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x09, 0x67, 0x69, + 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xc3, 0x02, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, + 0x53, 0x71, 0x75, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, + 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x68, + 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x64, 0x53, 0x68, 0x61, 0x12, + 0x24, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x06, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x5f, 0x6f, 0x6c, 0x64, 0x5f, 0x6f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4f, 0x6c, 0x64, 0x4f, 0x69, 0x64, - 0x22, 0xb6, 0x01, 0x0a, 0x16, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x06, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x06, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x23, 0x0a, 0x21, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xaa, 0x01, 0x0a, 0x17, 0x55, 0x73, - 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x62, 0x72, 0x61, - 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, - 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xd3, 0x01, 0x0a, 0x14, 0x55, 0x73, 0x65, 0x72, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, - 0x3d, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, - 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x37, - 0x0a, 0x0c, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0b, 0x63, 0x75, 0x73, 0x74, 0x6f, - 0x6d, 0x5f, 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, - 0x6f, 0x6f, 0x6b, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xb1, 0x04, 0x0a, - 0x1c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, - 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x1a, 0x86, 0x03, 0x0a, - 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, - 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x09, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x08, 0x72, 0x65, 0x62, 0x61, - 0x73, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1d, 0x0a, 0x0a, - 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x53, 0x68, 0x61, 0x12, 0x3f, 0x0a, 0x11, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x10, 0x72, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x0d, - 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, - 0x68, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x69, 0x74, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x67, 0x69, 0x74, - 0x50, 0x75, 0x73, 0x68, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, + 0x10, 0x05, 0x52, 0x09, 0x73, 0x71, 0x75, 0x61, 0x73, 0x68, 0x5f, 0x69, 0x64, 0x22, 0x5d, 0x0a, + 0x12, 0x55, 0x73, 0x65, 0x72, 0x53, 0x71, 0x75, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x71, 0x75, 0x61, 0x73, 0x68, 0x5f, 0x73, 0x68, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x71, 0x75, 0x61, 0x73, 0x68, 0x53, + 0x68, 0x61, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x11, + 0x70, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x52, 0x09, 0x67, 0x69, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xab, 0x01, 0x0a, + 0x1a, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x45, 0x0a, 0x0f, 0x72, + 0x65, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, 0x65, + 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, + 0x63, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xac, 0x01, 0x0a, 0x0f, 0x55, + 0x73, 0x65, 0x72, 0x53, 0x71, 0x75, 0x61, 0x73, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x49, + 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0f, 0x72, 0x65, 0x62, + 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, 0x65, 0x72, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, + 0x52, 0x0e, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, + 0x42, 0x07, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x87, 0x03, 0x0a, 0x15, 0x55, 0x73, + 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x1a, + 0xed, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x38, 0x0a, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x29, 0x0a, 0x27, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x65, - 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x22, 0xbf, 0x01, 0x0a, 0x1d, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x68, 0x61, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, - 0x53, 0x68, 0x61, 0x12, 0x27, 0x0a, 0x0e, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0d, 0x72, - 0x65, 0x62, 0x61, 0x73, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x42, 0x2a, 0x0a, 0x28, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, - 0x08, 0x04, 0x10, 0x05, 0x52, 0x11, 0x70, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x09, 0x67, 0x69, 0x74, 0x5f, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x22, 0xc3, 0x02, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x53, 0x71, 0x75, 0x61, 0x73, - 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x68, - 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, - 0x61, 0x12, 0x17, 0x0a, 0x07, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x64, 0x53, 0x68, 0x61, 0x12, 0x24, 0x0a, 0x06, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x09, 0x73, - 0x71, 0x75, 0x61, 0x73, 0x68, 0x5f, 0x69, 0x64, 0x22, 0x5d, 0x0a, 0x12, 0x55, 0x73, 0x65, 0x72, - 0x53, 0x71, 0x75, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x71, 0x75, 0x61, 0x73, 0x68, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x73, 0x71, 0x75, 0x61, 0x73, 0x68, 0x53, 0x68, 0x61, 0x4a, 0x04, 0x08, - 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x11, 0x70, 0x72, 0x65, 0x5f, 0x72, - 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x09, 0x67, 0x69, - 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xab, 0x01, 0x0a, 0x1a, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, - 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x45, 0x0a, 0x0f, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x72, - 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x12, 0x3d, 0x0a, - 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, - 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x07, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xac, 0x01, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x53, 0x71, - 0x75, 0x61, 0x73, 0x68, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x49, 0x0a, 0x10, 0x72, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0f, 0x72, 0x65, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x6c, 0x69, 0x63, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x62, - 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x87, 0x03, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, - 0x6c, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, - 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, - 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, - 0x00, 0x52, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x1a, 0xed, 0x01, 0x0a, 0x06, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, - 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, - 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, - 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6c, 0x64, - 0x5f, 0x6f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x4f, 0x6c, 0x64, 0x4f, 0x69, 0x64, 0x42, 0x22, 0x0a, 0x20, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x5c, - 0x0a, 0x16, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x62, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0c, - 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0xd8, 0x02, 0x0a, - 0x1a, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, - 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x72, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x28, 0x0a, - 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6c, 0x64, 0x5f, 0x6f, 0x69, - 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x4f, 0x6c, 0x64, 0x4f, 0x69, 0x64, 0x22, 0xc9, 0x01, 0x0a, 0x1b, 0x55, 0x73, 0x65, 0x72, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x62, 0x72, 0x61, 0x6e, 0x63, - 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x62, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x70, - 0x72, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, - 0x52, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x32, 0xc9, 0x0b, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, - 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, - 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x55, - 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x12, 0x1c, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, - 0x01, 0x12, 0x57, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, - 0x52, 0x65, 0x66, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5a, 0x0a, 0x0f, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x12, 0x1e, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, - 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, - 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, - 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5e, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, - 0x72, 0x67, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, - 0x08, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x51, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x46, 0x46, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x46, 0x46, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x46, 0x46, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x57, 0x0a, 0x0e, 0x55, 0x73, 0x65, - 0x72, 0x43, 0x68, 0x65, 0x72, 0x72, 0x79, 0x50, 0x69, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x65, 0x72, 0x72, 0x79, 0x50, - 0x69, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x65, 0x72, 0x72, 0x79, 0x50, 0x69, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, - 0x08, 0x01, 0x12, 0x5c, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, - 0x12, 0x70, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x25, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, - 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x4b, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, - 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, - 0x76, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x52, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x5f, 0x6f, 0x6c, 0x64, 0x5f, 0x6f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4f, 0x6c, 0x64, 0x4f, 0x69, 0x64, 0x42, + 0x22, 0x0a, 0x20, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x61, + 0x74, 0x63, 0x68, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x22, 0x5c, 0x0a, 0x16, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, + 0x0d, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x22, 0xd8, 0x02, 0x0a, 0x1a, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x68, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x62, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, + 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x6f, + 0x6c, 0x64, 0x5f, 0x6f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4f, 0x6c, 0x64, 0x4f, 0x69, 0x64, 0x22, 0xc9, 0x01, 0x0a, + 0x1b, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, + 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x52, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, + 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4a, + 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x72, + 0x65, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xc9, 0x0b, 0x0a, 0x10, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, + 0x10, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, + 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x55, + 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, + 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x55, 0x73, + 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, 0x12, 0x1c, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, + 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, + 0x12, 0x54, 0x0a, 0x0d, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, + 0x67, 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, + 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x57, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, + 0x72, 0x67, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, - 0x4b, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x53, 0x71, 0x75, 0x61, 0x73, 0x68, 0x12, 0x19, 0x2e, + 0x5a, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x54, 0x6f, 0x52, + 0x65, 0x66, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5e, 0x0a, 0x0f, 0x55, + 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1e, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, + 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x72, 0x67, + 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x51, 0x0a, 0x0c, 0x55, + 0x73, 0x65, 0x72, 0x46, 0x46, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1b, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x46, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x46, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x57, + 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x65, 0x72, 0x72, 0x79, 0x50, 0x69, 0x63, 0x6b, + 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, + 0x65, 0x72, 0x72, 0x79, 0x50, 0x69, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x65, + 0x72, 0x72, 0x79, 0x50, 0x69, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5c, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, + 0x02, 0x08, 0x01, 0x28, 0x01, 0x12, 0x70, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, + 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, + 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, + 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, + 0x02, 0x08, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4b, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x76, 0x65, 0x72, 0x74, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x76, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x76, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, + 0x28, 0x02, 0x08, 0x01, 0x12, 0x4b, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x53, 0x71, 0x75, 0x61, + 0x73, 0x68, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x53, 0x71, 0x75, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x71, 0x75, 0x61, 0x73, - 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x71, 0x75, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x59, 0x0a, 0x0e, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, - 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, 0x12, 0x66, 0x0a, 0x13, 0x55, 0x73, 0x65, 0x72, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x22, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x42, - 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, - 0x74, 0x6c, 0x61, 0x62, 0x2d, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, - 0x76, 0x31, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, + 0x01, 0x12, 0x59, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x61, + 0x74, 0x63, 0x68, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, 0x12, 0x66, 0x0a, 0x13, + 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, + 0x75, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, + 0x28, 0x02, 0x08, 0x01, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, + 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -5103,7 +4970,7 @@ func file_operations_proto_rawDescGZIP() []byte { } var file_operations_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_operations_proto_msgTypes = make([]protoimpl.MessageInfo, 47) +var file_operations_proto_msgTypes = make([]protoimpl.MessageInfo, 46) var file_operations_proto_goTypes = []interface{}{ (UserRevertResponse_CreateTreeError)(0), // 0: gitaly.UserRevertResponse.CreateTreeError (UserCommitFilesActionHeader_ActionType)(0), // 1: gitaly.UserCommitFilesActionHeader.ActionType @@ -5135,172 +5002,167 @@ var file_operations_proto_goTypes = []interface{}{ (*UserCherryPickError)(nil), // 27: gitaly.UserCherryPickError (*UserRevertRequest)(nil), // 28: gitaly.UserRevertRequest (*UserRevertResponse)(nil), // 29: gitaly.UserRevertResponse - (*UserRevertError)(nil), // 30: gitaly.UserRevertError - (*UserCommitFilesActionHeader)(nil), // 31: gitaly.UserCommitFilesActionHeader - (*UserCommitFilesAction)(nil), // 32: gitaly.UserCommitFilesAction - (*UserCommitFilesRequestHeader)(nil), // 33: gitaly.UserCommitFilesRequestHeader - (*UserCommitFilesRequest)(nil), // 34: gitaly.UserCommitFilesRequest - (*UserCommitFilesResponse)(nil), // 35: gitaly.UserCommitFilesResponse - (*UserCommitFilesError)(nil), // 36: gitaly.UserCommitFilesError - (*UserRebaseConfirmableRequest)(nil), // 37: gitaly.UserRebaseConfirmableRequest - (*UserRebaseConfirmableResponse)(nil), // 38: gitaly.UserRebaseConfirmableResponse - (*UserSquashRequest)(nil), // 39: gitaly.UserSquashRequest - (*UserSquashResponse)(nil), // 40: gitaly.UserSquashResponse - (*UserRebaseConfirmableError)(nil), // 41: gitaly.UserRebaseConfirmableError - (*UserSquashError)(nil), // 42: gitaly.UserSquashError - (*UserApplyPatchRequest)(nil), // 43: gitaly.UserApplyPatchRequest - (*UserApplyPatchResponse)(nil), // 44: gitaly.UserApplyPatchResponse - (*UserUpdateSubmoduleRequest)(nil), // 45: gitaly.UserUpdateSubmoduleRequest - (*UserUpdateSubmoduleResponse)(nil), // 46: gitaly.UserUpdateSubmoduleResponse - (*UserRebaseConfirmableRequest_Header)(nil), // 47: gitaly.UserRebaseConfirmableRequest.Header - (*UserApplyPatchRequest_Header)(nil), // 48: gitaly.UserApplyPatchRequest.Header - (*Repository)(nil), // 49: gitaly.Repository - (*User)(nil), // 50: gitaly.User - (*Branch)(nil), // 51: gitaly.Branch - (*CustomHookError)(nil), // 52: gitaly.CustomHookError - (*AccessCheckError)(nil), // 53: gitaly.AccessCheckError - (*ReferenceUpdateError)(nil), // 54: gitaly.ReferenceUpdateError - (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp - (*Tag)(nil), // 56: gitaly.Tag - (*ReferenceExistsError)(nil), // 57: gitaly.ReferenceExistsError - (*MergeConflictError)(nil), // 58: gitaly.MergeConflictError - (*GitCommit)(nil), // 59: gitaly.GitCommit - (*NotAncestorError)(nil), // 60: gitaly.NotAncestorError - (*ChangesAlreadyAppliedError)(nil), // 61: gitaly.ChangesAlreadyAppliedError - (*IndexError)(nil), // 62: gitaly.IndexError - (*ResolveRevisionError)(nil), // 63: gitaly.ResolveRevisionError + (*UserCommitFilesActionHeader)(nil), // 30: gitaly.UserCommitFilesActionHeader + (*UserCommitFilesAction)(nil), // 31: gitaly.UserCommitFilesAction + (*UserCommitFilesRequestHeader)(nil), // 32: gitaly.UserCommitFilesRequestHeader + (*UserCommitFilesRequest)(nil), // 33: gitaly.UserCommitFilesRequest + (*UserCommitFilesResponse)(nil), // 34: gitaly.UserCommitFilesResponse + (*UserCommitFilesError)(nil), // 35: gitaly.UserCommitFilesError + (*UserRebaseConfirmableRequest)(nil), // 36: gitaly.UserRebaseConfirmableRequest + (*UserRebaseConfirmableResponse)(nil), // 37: gitaly.UserRebaseConfirmableResponse + (*UserSquashRequest)(nil), // 38: gitaly.UserSquashRequest + (*UserSquashResponse)(nil), // 39: gitaly.UserSquashResponse + (*UserRebaseConfirmableError)(nil), // 40: gitaly.UserRebaseConfirmableError + (*UserSquashError)(nil), // 41: gitaly.UserSquashError + (*UserApplyPatchRequest)(nil), // 42: gitaly.UserApplyPatchRequest + (*UserApplyPatchResponse)(nil), // 43: gitaly.UserApplyPatchResponse + (*UserUpdateSubmoduleRequest)(nil), // 44: gitaly.UserUpdateSubmoduleRequest + (*UserUpdateSubmoduleResponse)(nil), // 45: gitaly.UserUpdateSubmoduleResponse + (*UserRebaseConfirmableRequest_Header)(nil), // 46: gitaly.UserRebaseConfirmableRequest.Header + (*UserApplyPatchRequest_Header)(nil), // 47: gitaly.UserApplyPatchRequest.Header + (*Repository)(nil), // 48: gitaly.Repository + (*User)(nil), // 49: gitaly.User + (*Branch)(nil), // 50: gitaly.Branch + (*CustomHookError)(nil), // 51: gitaly.CustomHookError + (*AccessCheckError)(nil), // 52: gitaly.AccessCheckError + (*ReferenceUpdateError)(nil), // 53: gitaly.ReferenceUpdateError + (*timestamppb.Timestamp)(nil), // 54: google.protobuf.Timestamp + (*Tag)(nil), // 55: gitaly.Tag + (*ReferenceExistsError)(nil), // 56: gitaly.ReferenceExistsError + (*MergeConflictError)(nil), // 57: gitaly.MergeConflictError + (*GitCommit)(nil), // 58: gitaly.GitCommit + (*NotAncestorError)(nil), // 59: gitaly.NotAncestorError + (*ChangesAlreadyAppliedError)(nil), // 60: gitaly.ChangesAlreadyAppliedError + (*IndexError)(nil), // 61: gitaly.IndexError + (*ResolveRevisionError)(nil), // 62: gitaly.ResolveRevisionError } var file_operations_proto_depIdxs = []int32{ - 49, // 0: gitaly.UserCreateBranchRequest.repository:type_name -> gitaly.Repository - 50, // 1: gitaly.UserCreateBranchRequest.user:type_name -> gitaly.User - 51, // 2: gitaly.UserCreateBranchResponse.branch:type_name -> gitaly.Branch - 52, // 3: gitaly.UserCreateBranchError.custom_hook:type_name -> gitaly.CustomHookError - 49, // 4: gitaly.UserUpdateBranchRequest.repository:type_name -> gitaly.Repository - 50, // 5: gitaly.UserUpdateBranchRequest.user:type_name -> gitaly.User - 49, // 6: gitaly.UserDeleteBranchRequest.repository:type_name -> gitaly.Repository - 50, // 7: gitaly.UserDeleteBranchRequest.user:type_name -> gitaly.User - 53, // 8: gitaly.UserDeleteBranchError.access_check:type_name -> gitaly.AccessCheckError - 54, // 9: gitaly.UserDeleteBranchError.reference_update:type_name -> gitaly.ReferenceUpdateError - 52, // 10: gitaly.UserDeleteBranchError.custom_hook:type_name -> gitaly.CustomHookError - 49, // 11: gitaly.UserDeleteTagRequest.repository:type_name -> gitaly.Repository - 50, // 12: gitaly.UserDeleteTagRequest.user:type_name -> gitaly.User - 49, // 13: gitaly.UserCreateTagRequest.repository:type_name -> gitaly.Repository - 50, // 14: gitaly.UserCreateTagRequest.user:type_name -> gitaly.User - 55, // 15: gitaly.UserCreateTagRequest.timestamp:type_name -> google.protobuf.Timestamp - 56, // 16: gitaly.UserCreateTagResponse.tag:type_name -> gitaly.Tag - 53, // 17: gitaly.UserCreateTagError.access_check:type_name -> gitaly.AccessCheckError - 54, // 18: gitaly.UserCreateTagError.reference_update:type_name -> gitaly.ReferenceUpdateError - 52, // 19: gitaly.UserCreateTagError.custom_hook:type_name -> gitaly.CustomHookError - 57, // 20: gitaly.UserCreateTagError.reference_exists:type_name -> gitaly.ReferenceExistsError - 49, // 21: gitaly.UserMergeBranchRequest.repository:type_name -> gitaly.Repository - 50, // 22: gitaly.UserMergeBranchRequest.user:type_name -> gitaly.User - 55, // 23: gitaly.UserMergeBranchRequest.timestamp:type_name -> google.protobuf.Timestamp + 48, // 0: gitaly.UserCreateBranchRequest.repository:type_name -> gitaly.Repository + 49, // 1: gitaly.UserCreateBranchRequest.user:type_name -> gitaly.User + 50, // 2: gitaly.UserCreateBranchResponse.branch:type_name -> gitaly.Branch + 51, // 3: gitaly.UserCreateBranchError.custom_hook:type_name -> gitaly.CustomHookError + 48, // 4: gitaly.UserUpdateBranchRequest.repository:type_name -> gitaly.Repository + 49, // 5: gitaly.UserUpdateBranchRequest.user:type_name -> gitaly.User + 48, // 6: gitaly.UserDeleteBranchRequest.repository:type_name -> gitaly.Repository + 49, // 7: gitaly.UserDeleteBranchRequest.user:type_name -> gitaly.User + 52, // 8: gitaly.UserDeleteBranchError.access_check:type_name -> gitaly.AccessCheckError + 53, // 9: gitaly.UserDeleteBranchError.reference_update:type_name -> gitaly.ReferenceUpdateError + 51, // 10: gitaly.UserDeleteBranchError.custom_hook:type_name -> gitaly.CustomHookError + 48, // 11: gitaly.UserDeleteTagRequest.repository:type_name -> gitaly.Repository + 49, // 12: gitaly.UserDeleteTagRequest.user:type_name -> gitaly.User + 48, // 13: gitaly.UserCreateTagRequest.repository:type_name -> gitaly.Repository + 49, // 14: gitaly.UserCreateTagRequest.user:type_name -> gitaly.User + 54, // 15: gitaly.UserCreateTagRequest.timestamp:type_name -> google.protobuf.Timestamp + 55, // 16: gitaly.UserCreateTagResponse.tag:type_name -> gitaly.Tag + 52, // 17: gitaly.UserCreateTagError.access_check:type_name -> gitaly.AccessCheckError + 53, // 18: gitaly.UserCreateTagError.reference_update:type_name -> gitaly.ReferenceUpdateError + 51, // 19: gitaly.UserCreateTagError.custom_hook:type_name -> gitaly.CustomHookError + 56, // 20: gitaly.UserCreateTagError.reference_exists:type_name -> gitaly.ReferenceExistsError + 48, // 21: gitaly.UserMergeBranchRequest.repository:type_name -> gitaly.Repository + 49, // 22: gitaly.UserMergeBranchRequest.user:type_name -> gitaly.User + 54, // 23: gitaly.UserMergeBranchRequest.timestamp:type_name -> google.protobuf.Timestamp 22, // 24: gitaly.UserMergeBranchResponse.branch_update:type_name -> gitaly.OperationBranchUpdate - 53, // 25: gitaly.UserMergeBranchError.access_check:type_name -> gitaly.AccessCheckError - 54, // 26: gitaly.UserMergeBranchError.reference_update:type_name -> gitaly.ReferenceUpdateError - 52, // 27: gitaly.UserMergeBranchError.custom_hook:type_name -> gitaly.CustomHookError - 58, // 28: gitaly.UserMergeBranchError.merge_conflict:type_name -> gitaly.MergeConflictError - 49, // 29: gitaly.UserMergeToRefRequest.repository:type_name -> gitaly.Repository - 50, // 30: gitaly.UserMergeToRefRequest.user:type_name -> gitaly.User - 55, // 31: gitaly.UserMergeToRefRequest.timestamp:type_name -> google.protobuf.Timestamp - 49, // 32: gitaly.UserRebaseToRefRequest.repository:type_name -> gitaly.Repository - 50, // 33: gitaly.UserRebaseToRefRequest.user:type_name -> gitaly.User - 55, // 34: gitaly.UserRebaseToRefRequest.timestamp:type_name -> google.protobuf.Timestamp - 49, // 35: gitaly.UserFFBranchRequest.repository:type_name -> gitaly.Repository - 50, // 36: gitaly.UserFFBranchRequest.user:type_name -> gitaly.User + 52, // 25: gitaly.UserMergeBranchError.access_check:type_name -> gitaly.AccessCheckError + 53, // 26: gitaly.UserMergeBranchError.reference_update:type_name -> gitaly.ReferenceUpdateError + 51, // 27: gitaly.UserMergeBranchError.custom_hook:type_name -> gitaly.CustomHookError + 57, // 28: gitaly.UserMergeBranchError.merge_conflict:type_name -> gitaly.MergeConflictError + 48, // 29: gitaly.UserMergeToRefRequest.repository:type_name -> gitaly.Repository + 49, // 30: gitaly.UserMergeToRefRequest.user:type_name -> gitaly.User + 54, // 31: gitaly.UserMergeToRefRequest.timestamp:type_name -> google.protobuf.Timestamp + 48, // 32: gitaly.UserRebaseToRefRequest.repository:type_name -> gitaly.Repository + 49, // 33: gitaly.UserRebaseToRefRequest.user:type_name -> gitaly.User + 54, // 34: gitaly.UserRebaseToRefRequest.timestamp:type_name -> google.protobuf.Timestamp + 48, // 35: gitaly.UserFFBranchRequest.repository:type_name -> gitaly.Repository + 49, // 36: gitaly.UserFFBranchRequest.user:type_name -> gitaly.User 22, // 37: gitaly.UserFFBranchResponse.branch_update:type_name -> gitaly.OperationBranchUpdate - 49, // 38: gitaly.UserCherryPickRequest.repository:type_name -> gitaly.Repository - 50, // 39: gitaly.UserCherryPickRequest.user:type_name -> gitaly.User - 59, // 40: gitaly.UserCherryPickRequest.commit:type_name -> gitaly.GitCommit - 49, // 41: gitaly.UserCherryPickRequest.start_repository:type_name -> gitaly.Repository - 55, // 42: gitaly.UserCherryPickRequest.timestamp:type_name -> google.protobuf.Timestamp + 48, // 38: gitaly.UserCherryPickRequest.repository:type_name -> gitaly.Repository + 49, // 39: gitaly.UserCherryPickRequest.user:type_name -> gitaly.User + 58, // 40: gitaly.UserCherryPickRequest.commit:type_name -> gitaly.GitCommit + 48, // 41: gitaly.UserCherryPickRequest.start_repository:type_name -> gitaly.Repository + 54, // 42: gitaly.UserCherryPickRequest.timestamp:type_name -> google.protobuf.Timestamp 22, // 43: gitaly.UserCherryPickResponse.branch_update:type_name -> gitaly.OperationBranchUpdate - 58, // 44: gitaly.UserCherryPickError.cherry_pick_conflict:type_name -> gitaly.MergeConflictError - 60, // 45: gitaly.UserCherryPickError.target_branch_diverged:type_name -> gitaly.NotAncestorError - 61, // 46: gitaly.UserCherryPickError.changes_already_applied:type_name -> gitaly.ChangesAlreadyAppliedError - 53, // 47: gitaly.UserCherryPickError.access_check:type_name -> gitaly.AccessCheckError - 49, // 48: gitaly.UserRevertRequest.repository:type_name -> gitaly.Repository - 50, // 49: gitaly.UserRevertRequest.user:type_name -> gitaly.User - 59, // 50: gitaly.UserRevertRequest.commit:type_name -> gitaly.GitCommit - 49, // 51: gitaly.UserRevertRequest.start_repository:type_name -> gitaly.Repository - 55, // 52: gitaly.UserRevertRequest.timestamp:type_name -> google.protobuf.Timestamp + 57, // 44: gitaly.UserCherryPickError.cherry_pick_conflict:type_name -> gitaly.MergeConflictError + 59, // 45: gitaly.UserCherryPickError.target_branch_diverged:type_name -> gitaly.NotAncestorError + 60, // 46: gitaly.UserCherryPickError.changes_already_applied:type_name -> gitaly.ChangesAlreadyAppliedError + 52, // 47: gitaly.UserCherryPickError.access_check:type_name -> gitaly.AccessCheckError + 48, // 48: gitaly.UserRevertRequest.repository:type_name -> gitaly.Repository + 49, // 49: gitaly.UserRevertRequest.user:type_name -> gitaly.User + 58, // 50: gitaly.UserRevertRequest.commit:type_name -> gitaly.GitCommit + 48, // 51: gitaly.UserRevertRequest.start_repository:type_name -> gitaly.Repository + 54, // 52: gitaly.UserRevertRequest.timestamp:type_name -> google.protobuf.Timestamp 22, // 53: gitaly.UserRevertResponse.branch_update:type_name -> gitaly.OperationBranchUpdate 0, // 54: gitaly.UserRevertResponse.create_tree_error_code:type_name -> gitaly.UserRevertResponse.CreateTreeError - 58, // 55: gitaly.UserRevertError.merge_conflict:type_name -> gitaly.MergeConflictError - 61, // 56: gitaly.UserRevertError.changes_already_applied:type_name -> gitaly.ChangesAlreadyAppliedError - 52, // 57: gitaly.UserRevertError.custom_hook:type_name -> gitaly.CustomHookError - 60, // 58: gitaly.UserRevertError.not_ancestor:type_name -> gitaly.NotAncestorError - 1, // 59: gitaly.UserCommitFilesActionHeader.action:type_name -> gitaly.UserCommitFilesActionHeader.ActionType - 31, // 60: gitaly.UserCommitFilesAction.header:type_name -> gitaly.UserCommitFilesActionHeader - 49, // 61: gitaly.UserCommitFilesRequestHeader.repository:type_name -> gitaly.Repository - 50, // 62: gitaly.UserCommitFilesRequestHeader.user:type_name -> gitaly.User - 49, // 63: gitaly.UserCommitFilesRequestHeader.start_repository:type_name -> gitaly.Repository - 55, // 64: gitaly.UserCommitFilesRequestHeader.timestamp:type_name -> google.protobuf.Timestamp - 33, // 65: gitaly.UserCommitFilesRequest.header:type_name -> gitaly.UserCommitFilesRequestHeader - 32, // 66: gitaly.UserCommitFilesRequest.action:type_name -> gitaly.UserCommitFilesAction - 22, // 67: gitaly.UserCommitFilesResponse.branch_update:type_name -> gitaly.OperationBranchUpdate - 53, // 68: gitaly.UserCommitFilesError.access_check:type_name -> gitaly.AccessCheckError - 62, // 69: gitaly.UserCommitFilesError.index_update:type_name -> gitaly.IndexError - 52, // 70: gitaly.UserCommitFilesError.custom_hook:type_name -> gitaly.CustomHookError - 47, // 71: gitaly.UserRebaseConfirmableRequest.header:type_name -> gitaly.UserRebaseConfirmableRequest.Header - 49, // 72: gitaly.UserSquashRequest.repository:type_name -> gitaly.Repository - 50, // 73: gitaly.UserSquashRequest.user:type_name -> gitaly.User - 50, // 74: gitaly.UserSquashRequest.author:type_name -> gitaly.User - 55, // 75: gitaly.UserSquashRequest.timestamp:type_name -> google.protobuf.Timestamp - 58, // 76: gitaly.UserRebaseConfirmableError.rebase_conflict:type_name -> gitaly.MergeConflictError - 53, // 77: gitaly.UserRebaseConfirmableError.access_check:type_name -> gitaly.AccessCheckError - 63, // 78: gitaly.UserSquashError.resolve_revision:type_name -> gitaly.ResolveRevisionError - 58, // 79: gitaly.UserSquashError.rebase_conflict:type_name -> gitaly.MergeConflictError - 48, // 80: gitaly.UserApplyPatchRequest.header:type_name -> gitaly.UserApplyPatchRequest.Header - 22, // 81: gitaly.UserApplyPatchResponse.branch_update:type_name -> gitaly.OperationBranchUpdate - 49, // 82: gitaly.UserUpdateSubmoduleRequest.repository:type_name -> gitaly.Repository - 50, // 83: gitaly.UserUpdateSubmoduleRequest.user:type_name -> gitaly.User - 55, // 84: gitaly.UserUpdateSubmoduleRequest.timestamp:type_name -> google.protobuf.Timestamp - 22, // 85: gitaly.UserUpdateSubmoduleResponse.branch_update:type_name -> gitaly.OperationBranchUpdate - 49, // 86: gitaly.UserRebaseConfirmableRequest.Header.repository:type_name -> gitaly.Repository - 50, // 87: gitaly.UserRebaseConfirmableRequest.Header.user:type_name -> gitaly.User - 49, // 88: gitaly.UserRebaseConfirmableRequest.Header.remote_repository:type_name -> gitaly.Repository - 55, // 89: gitaly.UserRebaseConfirmableRequest.Header.timestamp:type_name -> google.protobuf.Timestamp - 49, // 90: gitaly.UserApplyPatchRequest.Header.repository:type_name -> gitaly.Repository - 50, // 91: gitaly.UserApplyPatchRequest.Header.user:type_name -> gitaly.User - 55, // 92: gitaly.UserApplyPatchRequest.Header.timestamp:type_name -> google.protobuf.Timestamp - 2, // 93: gitaly.OperationService.UserCreateBranch:input_type -> gitaly.UserCreateBranchRequest - 5, // 94: gitaly.OperationService.UserUpdateBranch:input_type -> gitaly.UserUpdateBranchRequest - 7, // 95: gitaly.OperationService.UserDeleteBranch:input_type -> gitaly.UserDeleteBranchRequest - 12, // 96: gitaly.OperationService.UserCreateTag:input_type -> gitaly.UserCreateTagRequest - 10, // 97: gitaly.OperationService.UserDeleteTag:input_type -> gitaly.UserDeleteTagRequest - 18, // 98: gitaly.OperationService.UserMergeToRef:input_type -> gitaly.UserMergeToRefRequest - 20, // 99: gitaly.OperationService.UserRebaseToRef:input_type -> gitaly.UserRebaseToRefRequest - 15, // 100: gitaly.OperationService.UserMergeBranch:input_type -> gitaly.UserMergeBranchRequest - 23, // 101: gitaly.OperationService.UserFFBranch:input_type -> gitaly.UserFFBranchRequest - 25, // 102: gitaly.OperationService.UserCherryPick:input_type -> gitaly.UserCherryPickRequest - 34, // 103: gitaly.OperationService.UserCommitFiles:input_type -> gitaly.UserCommitFilesRequest - 37, // 104: gitaly.OperationService.UserRebaseConfirmable:input_type -> gitaly.UserRebaseConfirmableRequest - 28, // 105: gitaly.OperationService.UserRevert:input_type -> gitaly.UserRevertRequest - 39, // 106: gitaly.OperationService.UserSquash:input_type -> gitaly.UserSquashRequest - 43, // 107: gitaly.OperationService.UserApplyPatch:input_type -> gitaly.UserApplyPatchRequest - 45, // 108: gitaly.OperationService.UserUpdateSubmodule:input_type -> gitaly.UserUpdateSubmoduleRequest - 3, // 109: gitaly.OperationService.UserCreateBranch:output_type -> gitaly.UserCreateBranchResponse - 6, // 110: gitaly.OperationService.UserUpdateBranch:output_type -> gitaly.UserUpdateBranchResponse - 8, // 111: gitaly.OperationService.UserDeleteBranch:output_type -> gitaly.UserDeleteBranchResponse - 13, // 112: gitaly.OperationService.UserCreateTag:output_type -> gitaly.UserCreateTagResponse - 11, // 113: gitaly.OperationService.UserDeleteTag:output_type -> gitaly.UserDeleteTagResponse - 19, // 114: gitaly.OperationService.UserMergeToRef:output_type -> gitaly.UserMergeToRefResponse - 21, // 115: gitaly.OperationService.UserRebaseToRef:output_type -> gitaly.UserRebaseToRefResponse - 16, // 116: gitaly.OperationService.UserMergeBranch:output_type -> gitaly.UserMergeBranchResponse - 24, // 117: gitaly.OperationService.UserFFBranch:output_type -> gitaly.UserFFBranchResponse - 26, // 118: gitaly.OperationService.UserCherryPick:output_type -> gitaly.UserCherryPickResponse - 35, // 119: gitaly.OperationService.UserCommitFiles:output_type -> gitaly.UserCommitFilesResponse - 38, // 120: gitaly.OperationService.UserRebaseConfirmable:output_type -> gitaly.UserRebaseConfirmableResponse - 29, // 121: gitaly.OperationService.UserRevert:output_type -> gitaly.UserRevertResponse - 40, // 122: gitaly.OperationService.UserSquash:output_type -> gitaly.UserSquashResponse - 44, // 123: gitaly.OperationService.UserApplyPatch:output_type -> gitaly.UserApplyPatchResponse - 46, // 124: gitaly.OperationService.UserUpdateSubmodule:output_type -> gitaly.UserUpdateSubmoduleResponse - 109, // [109:125] is the sub-list for method output_type - 93, // [93:109] is the sub-list for method input_type - 93, // [93:93] is the sub-list for extension type_name - 93, // [93:93] is the sub-list for extension extendee - 0, // [0:93] is the sub-list for field type_name + 1, // 55: gitaly.UserCommitFilesActionHeader.action:type_name -> gitaly.UserCommitFilesActionHeader.ActionType + 30, // 56: gitaly.UserCommitFilesAction.header:type_name -> gitaly.UserCommitFilesActionHeader + 48, // 57: gitaly.UserCommitFilesRequestHeader.repository:type_name -> gitaly.Repository + 49, // 58: gitaly.UserCommitFilesRequestHeader.user:type_name -> gitaly.User + 48, // 59: gitaly.UserCommitFilesRequestHeader.start_repository:type_name -> gitaly.Repository + 54, // 60: gitaly.UserCommitFilesRequestHeader.timestamp:type_name -> google.protobuf.Timestamp + 32, // 61: gitaly.UserCommitFilesRequest.header:type_name -> gitaly.UserCommitFilesRequestHeader + 31, // 62: gitaly.UserCommitFilesRequest.action:type_name -> gitaly.UserCommitFilesAction + 22, // 63: gitaly.UserCommitFilesResponse.branch_update:type_name -> gitaly.OperationBranchUpdate + 52, // 64: gitaly.UserCommitFilesError.access_check:type_name -> gitaly.AccessCheckError + 61, // 65: gitaly.UserCommitFilesError.index_update:type_name -> gitaly.IndexError + 51, // 66: gitaly.UserCommitFilesError.custom_hook:type_name -> gitaly.CustomHookError + 46, // 67: gitaly.UserRebaseConfirmableRequest.header:type_name -> gitaly.UserRebaseConfirmableRequest.Header + 48, // 68: gitaly.UserSquashRequest.repository:type_name -> gitaly.Repository + 49, // 69: gitaly.UserSquashRequest.user:type_name -> gitaly.User + 49, // 70: gitaly.UserSquashRequest.author:type_name -> gitaly.User + 54, // 71: gitaly.UserSquashRequest.timestamp:type_name -> google.protobuf.Timestamp + 57, // 72: gitaly.UserRebaseConfirmableError.rebase_conflict:type_name -> gitaly.MergeConflictError + 52, // 73: gitaly.UserRebaseConfirmableError.access_check:type_name -> gitaly.AccessCheckError + 62, // 74: gitaly.UserSquashError.resolve_revision:type_name -> gitaly.ResolveRevisionError + 57, // 75: gitaly.UserSquashError.rebase_conflict:type_name -> gitaly.MergeConflictError + 47, // 76: gitaly.UserApplyPatchRequest.header:type_name -> gitaly.UserApplyPatchRequest.Header + 22, // 77: gitaly.UserApplyPatchResponse.branch_update:type_name -> gitaly.OperationBranchUpdate + 48, // 78: gitaly.UserUpdateSubmoduleRequest.repository:type_name -> gitaly.Repository + 49, // 79: gitaly.UserUpdateSubmoduleRequest.user:type_name -> gitaly.User + 54, // 80: gitaly.UserUpdateSubmoduleRequest.timestamp:type_name -> google.protobuf.Timestamp + 22, // 81: gitaly.UserUpdateSubmoduleResponse.branch_update:type_name -> gitaly.OperationBranchUpdate + 48, // 82: gitaly.UserRebaseConfirmableRequest.Header.repository:type_name -> gitaly.Repository + 49, // 83: gitaly.UserRebaseConfirmableRequest.Header.user:type_name -> gitaly.User + 48, // 84: gitaly.UserRebaseConfirmableRequest.Header.remote_repository:type_name -> gitaly.Repository + 54, // 85: gitaly.UserRebaseConfirmableRequest.Header.timestamp:type_name -> google.protobuf.Timestamp + 48, // 86: gitaly.UserApplyPatchRequest.Header.repository:type_name -> gitaly.Repository + 49, // 87: gitaly.UserApplyPatchRequest.Header.user:type_name -> gitaly.User + 54, // 88: gitaly.UserApplyPatchRequest.Header.timestamp:type_name -> google.protobuf.Timestamp + 2, // 89: gitaly.OperationService.UserCreateBranch:input_type -> gitaly.UserCreateBranchRequest + 5, // 90: gitaly.OperationService.UserUpdateBranch:input_type -> gitaly.UserUpdateBranchRequest + 7, // 91: gitaly.OperationService.UserDeleteBranch:input_type -> gitaly.UserDeleteBranchRequest + 12, // 92: gitaly.OperationService.UserCreateTag:input_type -> gitaly.UserCreateTagRequest + 10, // 93: gitaly.OperationService.UserDeleteTag:input_type -> gitaly.UserDeleteTagRequest + 18, // 94: gitaly.OperationService.UserMergeToRef:input_type -> gitaly.UserMergeToRefRequest + 20, // 95: gitaly.OperationService.UserRebaseToRef:input_type -> gitaly.UserRebaseToRefRequest + 15, // 96: gitaly.OperationService.UserMergeBranch:input_type -> gitaly.UserMergeBranchRequest + 23, // 97: gitaly.OperationService.UserFFBranch:input_type -> gitaly.UserFFBranchRequest + 25, // 98: gitaly.OperationService.UserCherryPick:input_type -> gitaly.UserCherryPickRequest + 33, // 99: gitaly.OperationService.UserCommitFiles:input_type -> gitaly.UserCommitFilesRequest + 36, // 100: gitaly.OperationService.UserRebaseConfirmable:input_type -> gitaly.UserRebaseConfirmableRequest + 28, // 101: gitaly.OperationService.UserRevert:input_type -> gitaly.UserRevertRequest + 38, // 102: gitaly.OperationService.UserSquash:input_type -> gitaly.UserSquashRequest + 42, // 103: gitaly.OperationService.UserApplyPatch:input_type -> gitaly.UserApplyPatchRequest + 44, // 104: gitaly.OperationService.UserUpdateSubmodule:input_type -> gitaly.UserUpdateSubmoduleRequest + 3, // 105: gitaly.OperationService.UserCreateBranch:output_type -> gitaly.UserCreateBranchResponse + 6, // 106: gitaly.OperationService.UserUpdateBranch:output_type -> gitaly.UserUpdateBranchResponse + 8, // 107: gitaly.OperationService.UserDeleteBranch:output_type -> gitaly.UserDeleteBranchResponse + 13, // 108: gitaly.OperationService.UserCreateTag:output_type -> gitaly.UserCreateTagResponse + 11, // 109: gitaly.OperationService.UserDeleteTag:output_type -> gitaly.UserDeleteTagResponse + 19, // 110: gitaly.OperationService.UserMergeToRef:output_type -> gitaly.UserMergeToRefResponse + 21, // 111: gitaly.OperationService.UserRebaseToRef:output_type -> gitaly.UserRebaseToRefResponse + 16, // 112: gitaly.OperationService.UserMergeBranch:output_type -> gitaly.UserMergeBranchResponse + 24, // 113: gitaly.OperationService.UserFFBranch:output_type -> gitaly.UserFFBranchResponse + 26, // 114: gitaly.OperationService.UserCherryPick:output_type -> gitaly.UserCherryPickResponse + 34, // 115: gitaly.OperationService.UserCommitFiles:output_type -> gitaly.UserCommitFilesResponse + 37, // 116: gitaly.OperationService.UserRebaseConfirmable:output_type -> gitaly.UserRebaseConfirmableResponse + 29, // 117: gitaly.OperationService.UserRevert:output_type -> gitaly.UserRevertResponse + 39, // 118: gitaly.OperationService.UserSquash:output_type -> gitaly.UserSquashResponse + 43, // 119: gitaly.OperationService.UserApplyPatch:output_type -> gitaly.UserApplyPatchResponse + 45, // 120: gitaly.OperationService.UserUpdateSubmodule:output_type -> gitaly.UserUpdateSubmoduleResponse + 105, // [105:121] is the sub-list for method output_type + 89, // [89:105] is the sub-list for method input_type + 89, // [89:89] is the sub-list for extension type_name + 89, // [89:89] is the sub-list for extension extendee + 0, // [0:89] is the sub-list for field type_name } func init() { file_operations_proto_init() } @@ -5649,18 +5511,6 @@ func file_operations_proto_init() { } } file_operations_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UserRevertError); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_operations_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserCommitFilesActionHeader); i { case 0: return &v.state @@ -5672,7 +5522,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserCommitFilesAction); i { case 0: return &v.state @@ -5684,7 +5534,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserCommitFilesRequestHeader); i { case 0: return &v.state @@ -5696,7 +5546,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserCommitFilesRequest); i { case 0: return &v.state @@ -5708,7 +5558,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserCommitFilesResponse); i { case 0: return &v.state @@ -5720,7 +5570,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserCommitFilesError); i { case 0: return &v.state @@ -5732,7 +5582,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserRebaseConfirmableRequest); i { case 0: return &v.state @@ -5744,7 +5594,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserRebaseConfirmableResponse); i { case 0: return &v.state @@ -5756,7 +5606,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserSquashRequest); i { case 0: return &v.state @@ -5768,7 +5618,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserSquashResponse); i { case 0: return &v.state @@ -5780,7 +5630,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserRebaseConfirmableError); i { case 0: return &v.state @@ -5792,7 +5642,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserSquashError); i { case 0: return &v.state @@ -5804,7 +5654,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserApplyPatchRequest); i { case 0: return &v.state @@ -5816,7 +5666,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserApplyPatchResponse); i { case 0: return &v.state @@ -5828,7 +5678,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserUpdateSubmoduleRequest); i { case 0: return &v.state @@ -5840,7 +5690,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserUpdateSubmoduleResponse); i { case 0: return &v.state @@ -5852,7 +5702,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserRebaseConfirmableRequest_Header); i { case 0: return &v.state @@ -5864,7 +5714,7 @@ func file_operations_proto_init() { return nil } } - file_operations_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + file_operations_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UserApplyPatchRequest_Header); i { case 0: return &v.state @@ -5903,42 +5753,36 @@ func file_operations_proto_init() { (*UserCherryPickError_ChangesAlreadyApplied)(nil), (*UserCherryPickError_AccessCheck)(nil), } - file_operations_proto_msgTypes[28].OneofWrappers = []interface{}{ - (*UserRevertError_MergeConflict)(nil), - (*UserRevertError_ChangesAlreadyApplied)(nil), - (*UserRevertError_CustomHook)(nil), - (*UserRevertError_NotAncestor)(nil), - } - file_operations_proto_msgTypes[30].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[29].OneofWrappers = []interface{}{ (*UserCommitFilesAction_Header)(nil), (*UserCommitFilesAction_Content)(nil), } - file_operations_proto_msgTypes[32].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[31].OneofWrappers = []interface{}{ (*UserCommitFilesRequest_Header)(nil), (*UserCommitFilesRequest_Action)(nil), } - file_operations_proto_msgTypes[34].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[33].OneofWrappers = []interface{}{ (*UserCommitFilesError_AccessCheck)(nil), (*UserCommitFilesError_IndexUpdate)(nil), (*UserCommitFilesError_CustomHook)(nil), } - file_operations_proto_msgTypes[35].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[34].OneofWrappers = []interface{}{ (*UserRebaseConfirmableRequest_Header_)(nil), (*UserRebaseConfirmableRequest_Apply)(nil), } - file_operations_proto_msgTypes[36].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[35].OneofWrappers = []interface{}{ (*UserRebaseConfirmableResponse_RebaseSha)(nil), (*UserRebaseConfirmableResponse_RebaseApplied)(nil), } - file_operations_proto_msgTypes[39].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[38].OneofWrappers = []interface{}{ (*UserRebaseConfirmableError_RebaseConflict)(nil), (*UserRebaseConfirmableError_AccessCheck)(nil), } - file_operations_proto_msgTypes[40].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[39].OneofWrappers = []interface{}{ (*UserSquashError_ResolveRevision)(nil), (*UserSquashError_RebaseConflict)(nil), } - file_operations_proto_msgTypes[41].OneofWrappers = []interface{}{ + file_operations_proto_msgTypes[40].OneofWrappers = []interface{}{ (*UserApplyPatchRequest_Header_)(nil), (*UserApplyPatchRequest_Patches)(nil), } @@ -5948,7 +5792,7 @@ func file_operations_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_operations_proto_rawDesc, NumEnums: 2, - NumMessages: 47, + NumMessages: 46, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/go/gitalypb/repository.pb.go b/proto/go/gitalypb/repository.pb.go index bdfd812ed..ca005e2b5 100644 --- a/proto/go/gitalypb/repository.pb.go +++ b/proto/go/gitalypb/repository.pb.go @@ -6163,7 +6163,7 @@ var file_repository_proto_rawDesc = []byte{ 0x1c, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x32, 0xb2, 0x20, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x6c, 0x75, 0x65, 0x32, 0xaf, 0x20, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, @@ -6399,34 +6399,34 @@ var file_repository_proto_rawDesc = []byte{ 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x09, 0xfa, 0x97, 0x28, - 0x02, 0x08, 0x02, 0x88, 0x02, 0x01, 0x12, 0x4d, 0x0a, 0x09, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x02, 0x08, 0x02, 0x88, 0x02, 0x01, 0x12, 0x4a, 0x0a, 0x09, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x12, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x6c, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0b, 0xfa, 0x97, 0x28, 0x04, 0x08, 0x01, - 0x10, 0x02, 0x88, 0x02, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, - 0x28, 0x02, 0x08, 0x02, 0x12, 0x60, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, - 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x6c, - 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d, 0x6f, 0x72, - 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x36, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xfa, 0x97, 0x28, 0x04, 0x08, 0x01, + 0x10, 0x02, 0x12, 0x5d, 0x0a, 0x10, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, + 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, + 0x02, 0x12, 0x60, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, + 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, + 0x02, 0x08, 0x01, 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, + 0x97, 0x28, 0x02, 0x08, 0x02, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d, 0x6f, 0x72, 0x67, 0x2f, 0x67, + 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/proto/go/gitalypb/repository_grpc.pb.go b/proto/go/gitalypb/repository_grpc.pb.go index b407b948c..d5af55b94 100644 --- a/proto/go/gitalypb/repository_grpc.pb.go +++ b/proto/go/gitalypb/repository_grpc.pb.go @@ -192,9 +192,7 @@ type RepositoryServiceClient interface { // FullPath reads the "gitlab.fullpath" configuration from the repository's // gitconfig. Returns an error in case the full path has not been configured. FullPath(ctx context.Context, in *FullPathRequest, opts ...grpc.CallOption) (*FullPathResponse, error) - // Deprecated: Do not use. // RemoveAll deletes all repositories on a specified storage. - // Deprecated in favour of individually removing repositories with RemoveRepository. RemoveAll(ctx context.Context, in *RemoveAllRequest, opts ...grpc.CallOption) (*RemoveAllResponse, error) // BackupRepository creates a full or incremental backup streamed directly to // object-storage. The backup is created synchronously. The destination must @@ -959,7 +957,6 @@ func (c *repositoryServiceClient) FullPath(ctx context.Context, in *FullPathRequ return out, nil } -// Deprecated: Do not use. func (c *repositoryServiceClient) RemoveAll(ctx context.Context, in *RemoveAllRequest, opts ...grpc.CallOption) (*RemoveAllResponse, error) { out := new(RemoveAllResponse) err := c.cc.Invoke(ctx, "/gitaly.RepositoryService/RemoveAll", in, out, opts...) @@ -1170,9 +1167,7 @@ type RepositoryServiceServer interface { // FullPath reads the "gitlab.fullpath" configuration from the repository's // gitconfig. Returns an error in case the full path has not been configured. FullPath(context.Context, *FullPathRequest) (*FullPathResponse, error) - // Deprecated: Do not use. // RemoveAll deletes all repositories on a specified storage. - // Deprecated in favour of individually removing repositories with RemoveRepository. RemoveAll(context.Context, *RemoveAllRequest) (*RemoveAllResponse, error) // BackupRepository creates a full or incremental backup streamed directly to // object-storage. The backup is created synchronously. The destination must diff --git a/proto/operations.proto b/proto/operations.proto index 72df2f6d8..27a792572 100644 --- a/proto/operations.proto +++ b/proto/operations.proto @@ -745,20 +745,6 @@ message UserRevertResponse { CreateTreeError create_tree_error_code = 5; } -// UserRevertError is an error returned by the UserRevert RPC. -message UserRevertError { - oneof error { - // merge_conflict is returned if there is a conflict when applying the revert. - MergeConflictError merge_conflict = 1; - // changes_already_applied is returned if the result after applying the revert is empty. - ChangesAlreadyAppliedError changes_already_applied = 2; - // custom_hook contains the error message if the pre-receive hook failed. - CustomHookError custom_hook = 3; - // not_ancestor is returned if the old tip of the target branch is not an ancestor of the new commit. - NotAncestorError not_ancestor = 4; - } -} - // UserCommitFilesActionHeader contains the details of the action to be performed. message UserCommitFilesActionHeader { // ActionType is the type of action to perform. diff --git a/proto/repository.proto b/proto/repository.proto index 4a5d8dbf8..25d446f61 100644 --- a/proto/repository.proto +++ b/proto/repository.proto @@ -381,13 +381,11 @@ service RepositoryService { } // RemoveAll deletes all repositories on a specified storage. - // Deprecated in favour of individually removing repositories with RemoveRepository. rpc RemoveAll(RemoveAllRequest) returns (RemoveAllResponse) { option (op_type) = { op: MUTATOR scope_level: STORAGE }; - option deprecated = true; } // BackupRepository creates a full or incremental backup streamed directly to |