diff options
author | Aleksei Lipniagov <alipniagov@gitlab.com> | 2021-10-06 15:57:37 +0300 |
---|---|---|
committer | Aleksei Lipniagov <alipniagov@gitlab.com> | 2021-10-06 15:57:37 +0300 |
commit | d644b4b46f0b0634f0f16335e493e375fc8f895b (patch) | |
tree | 03e4167c0a720134dde5f11d88457e5fa74ef528 | |
parent | dae5f6807195cf72c1405290b2ed0634ec02e372 (diff) |
Revert "Merge branch 'master' into mk-grpc-1.38"mk-grpc-1.38
This reverts commit dae5f6807195cf72c1405290b2ed0634ec02e372, reversing
changes made to 56c26a7cb0000b7af89d2a069514d67b4b617daf.
121 files changed, 2623 insertions, 6744 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 68361e2d3..2e2d82caf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,5 @@ # Gitaly changelog -## 14.3.2 (2021-10-01) - -No changes. - -## 14.3.1 (2021-09-30) - -No changes. - ## 14.3.0 (2021-09-21) ### Added (6 changes) @@ -87,10 +79,6 @@ No changes. - [remote: Deprecate FetchInternalRemote RPC](gitlab-org/gitaly@c5fc4a035e8c6cd2e7b0847e5b9a10a67a762965) ([merge request](gitlab-org/gitaly!3860)) - [repository: Deprecate `SetConfig()` RPC](gitlab-org/gitaly@4d1c5cc7f927a3da7a997f48b996fbdf9579b047) ([merge request](gitlab-org/gitaly!3790)) -## 14.2.5 (2021-09-30) - -No changes. - ## 14.2.4 (2021-09-17) ### Fixed (1 change) @@ -217,16 +205,6 @@ No changes. - [Remove `praefect reconcile` subcommand](gitlab-org/gitaly@0c48ca9e3f368f03d0d78de0a31540d2fe248242) ([merge request](gitlab-org/gitaly!3667)) -## 14.1.7 (2021-09-30) - -No changes. - -## 14.1.6 (2021-09-27) - -### Fixed (1 change) - -- [Derive virtual storage's filesystem id from its name](gitlab-org/gitaly@add378c8b07a885e23c905d157e285670513352f) ([merge request](gitlab-org/gitaly!3835)) - ## 14.1.5 (2021-09-02) ### Performance (2 changes) @@ -316,12 +294,6 @@ No changes. - [Separate listenmux from backchannel](gitlab-org/gitaly@c95298c125a680a006153d5aca5d3dbb575ce352) ([merge request](gitlab-org/gitaly!3593)) - [Use upstream implementation of insecure credentials](gitlab-org/gitaly@7453f84b0bb385a958943b5e0910b8f6bb3906bb) ([merge request](gitlab-org/gitaly!3591)) -## 14.0.11 (2021-09-23) - -### Fixed (1 change) - -- [Derive virtual storage's filesystem id from its name](gitlab-org/gitaly@34cfd2c2b4964cf1c0ad1704fd9e2c25666bcf16) ([merge request](gitlab-org/gitaly!3834)) - ## 14.0.10 (2021-09-02) ### Fixed (2 changes) @@ -456,12 +428,6 @@ No changes. - [Update gitlab-labkit to 0.17.1](gitlab-org/gitaly@904af72eb7c42124978370cef53681fa561b10f5) ([merge request](gitlab-org/gitaly!3395)) -## 13.12.12 (2021-09-21) - -### Fixed (1 change) - -- [Derive virtual storage's filesystem id from its name](gitlab-org/gitaly@af62b5b5b2357419c3cde2412106b5013c2f1060) ([merge request](gitlab-org/gitaly!3833)) - ## 13.12.11 (2021-09-02) ### Added (1 change) diff --git a/client/dial.go b/client/dial.go index 352003d09..77020bf6b 100644 --- a/client/dial.go +++ b/client/dial.go @@ -4,7 +4,6 @@ import ( "context" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/client" - "gitlab.com/gitlab-org/gitaly/v14/internal/sidechannel" "google.golang.org/grpc" healthpb "google.golang.org/grpc/health/grpc_health_v1" ) @@ -31,15 +30,6 @@ func Dial(rawAddress string, connOpts []grpc.DialOption) (*grpc.ClientConn, erro return DialContext(context.Background(), rawAddress, connOpts) } -// DialSidechannel configures the dialer to establish a Gitaly -// backchannel connection instead of a regular gRPC connection. It also -// injects sr as a sidechannel registry, so that Gitaly can establish -// sidechannels back to the client. -func DialSidechannel(ctx context.Context, rawAddress string, sr *SidechannelRegistry, connOpts []grpc.DialOption) (*grpc.ClientConn, error) { - clientHandshaker := sidechannel.NewClientHandshaker(sr.logger, sr.registry) - return client.Dial(ctx, rawAddress, connOpts, clientHandshaker) -} - // FailOnNonTempDialError helps to identify if remote listener is ready to accept new connections. func FailOnNonTempDialError() []grpc.DialOption { return []grpc.DialOption{ diff --git a/client/dial_test.go b/client/dial_test.go index ca62bcfc2..5e448c78d 100644 --- a/client/dial_test.go +++ b/client/dial_test.go @@ -12,7 +12,6 @@ import ( "testing" "github.com/opentracing/opentracing-go" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/uber/jaeger-client-go" @@ -27,7 +26,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" - "google.golang.org/grpc/credentials/insecure" healthpb "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/status" ) @@ -39,11 +37,7 @@ func TestDial(t *testing.T) { t.Log("WARNING. Proxy configuration detected from environment settings. This test failure may be related to proxy configuration. Please process with caution") } - stop, connectionMap := startListeners(t, func(creds credentials.TransportCredentials) *grpc.Server { - srv := grpc.NewServer(grpc.Creds(creds)) - healthpb.RegisterHealthServer(srv, &healthServer{}) - return srv - }) + stop, connectionMap := startListeners(t) defer stop() unixSocketAbsPath := connectionMap["unix"] @@ -153,110 +147,6 @@ func TestDial(t *testing.T) { } } -func TestDialSidechannel(t *testing.T) { - if emitProxyWarning() { - t.Log("WARNING. Proxy configuration detected from environment settings. This test failure may be related to proxy configuration. Please process with caution") - } - - stop, connectionMap := startListeners(t, func(creds credentials.TransportCredentials) *grpc.Server { - return grpc.NewServer(TestSidechannelServer(newLogger(t), creds, func( - _ interface{}, - stream grpc.ServerStream, - sidechannelConn io.ReadWriteCloser, - ) error { - if method, ok := grpc.Method(stream.Context()); !ok || method != "/grpc.health.v1.Health/Check" { - return fmt.Errorf("unexpected method: %s", method) - } - - var req healthpb.HealthCheckRequest - if err := stream.RecvMsg(&req); err != nil { - return fmt.Errorf("recv msg: %w", err) - } - - if _, err := io.Copy(sidechannelConn, sidechannelConn); err != nil { - return fmt.Errorf("copy: %w", err) - } - - if err := stream.SendMsg(&healthpb.HealthCheckResponse{}); err != nil { - return fmt.Errorf("send msg: %w", err) - } - - return nil - })...) - }) - defer stop() - - unixSocketAbsPath := connectionMap["unix"] - - tempDir := testhelper.TempDir(t) - - unixSocketPath := filepath.Join(tempDir, "gitaly.socket") - require.NoError(t, os.Symlink(unixSocketAbsPath, unixSocketPath)) - - registry := NewSidechannelRegistry(newLogger(t)) - - tests := []struct { - name string - rawAddress string - envSSLCertFile string - dialOpts []grpc.DialOption - }{ - { - name: "tcp sidechannel", - rawAddress: "tcp://localhost:" + connectionMap["tcp"], // "tcp://localhost:1234" - }, - { - name: "tls sidechannel", - rawAddress: "tls://localhost:" + connectionMap["tls"], // "tls://localhost:1234" - envSSLCertFile: "./testdata/gitalycert.pem", - }, - { - name: "unix sidechannel", - rawAddress: "unix:" + unixSocketAbsPath, // "unix:/tmp/temp-socket" - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.envSSLCertFile != "" { - defer testhelper.ModifyEnvironment(t, gitalyx509.SSLCertFile, tt.envSSLCertFile)() - } - - ctx, cancel := testhelper.Context() - defer cancel() - - conn, err := DialSidechannel(ctx, tt.rawAddress, registry, tt.dialOpts) - require.NoError(t, err) - defer conn.Close() - - ctx, scw := registry.Register(ctx, func(conn SidechannelConn) error { - const message = "hello world" - if _, err := io.WriteString(conn, message); err != nil { - return err - } - if err := conn.CloseWrite(); err != nil { - return err - } - buf, err := io.ReadAll(conn) - if err != nil { - return err - } - if string(buf) != message { - return fmt.Errorf("expected %q, got %q", message, buf) - } - - return nil - }) - defer scw.Close() - - req := &healthpb.HealthCheckRequest{Service: "test sidechannel"} - _, err = healthpb.NewHealthClient(conn).Check(ctx, req) - require.NoError(t, err) - require.NoError(t, scw.Close()) - }) - } -} - type testSvc struct { proxytestdata.UnimplementedTestServiceServer PingMethod func(context.Context, *proxytestdata.PingRequest) (*proxytestdata.PingResponse, error) @@ -524,23 +414,26 @@ func TestDial_Tracing(t *testing.T) { } // healthServer provide a basic GRPC health service endpoint for testing purposes -type healthServer struct { - healthpb.UnimplementedHealthServer -} +type healthServer struct{} func (*healthServer) Check(context.Context, *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { - return &healthpb.HealthCheckResponse{}, nil + return &healthpb.HealthCheckResponse{Status: healthpb.HealthCheckResponse_SERVING}, nil +} + +func (*healthServer) Watch(*healthpb.HealthCheckRequest, healthpb.Health_WatchServer) error { + return status.Errorf(codes.Unimplemented, "Not implemented") } // startTCPListener will start a insecure TCP listener on a random unused port -func startTCPListener(t testing.TB, factory func(credentials.TransportCredentials) *grpc.Server) (func(), string) { +func startTCPListener(t testing.TB) (func(), string) { listener, err := net.Listen("tcp", "localhost:0") require.NoError(t, err) tcpPort := listener.Addr().(*net.TCPAddr).Port address := fmt.Sprintf("%d", tcpPort) - grpcServer := factory(insecure.NewCredentials()) + grpcServer := grpc.NewServer() + healthpb.RegisterHealthServer(grpcServer, &healthServer{}) go grpcServer.Serve(listener) return func() { @@ -549,13 +442,14 @@ func startTCPListener(t testing.TB, factory func(credentials.TransportCredential } // startUnixListener will start a unix socket listener using a temporary file -func startUnixListener(t testing.TB, factory func(credentials.TransportCredentials) *grpc.Server) (func(), string) { +func startUnixListener(t testing.TB) (func(), string) { serverSocketPath := testhelper.GetTemporaryGitalySocketFileName(t) listener, err := net.Listen("unix", serverSocketPath) require.NoError(t, err) - grpcServer := factory(insecure.NewCredentials()) + grpcServer := grpc.NewServer() + healthpb.RegisterHealthServer(grpcServer, &healthServer{}) go grpcServer.Serve(listener) return func() { @@ -565,7 +459,7 @@ func startUnixListener(t testing.TB, factory func(credentials.TransportCredentia // startTLSListener will start a secure TLS listener on a random unused port //go:generate openssl req -newkey rsa:4096 -new -nodes -x509 -days 3650 -out testdata/gitalycert.pem -keyout testdata/gitalykey.pem -subj "/C=US/ST=California/L=San Francisco/O=GitLab/OU=GitLab-Shell/CN=localhost" -addext "subjectAltName = IP:127.0.0.1, DNS:localhost" -func startTLSListener(t testing.TB, factory func(credentials.TransportCredentials) *grpc.Server) (func(), string) { +func startTLSListener(t testing.TB) (func(), string) { listener, err := net.Listen("tcp", "localhost:0") require.NoError(t, err) @@ -575,12 +469,11 @@ func startTLSListener(t testing.TB, factory func(credentials.TransportCredential cert, err := tls.LoadX509KeyPair("testdata/gitalycert.pem", "testdata/gitalykey.pem") require.NoError(t, err) - grpcServer := factory( - credentials.NewTLS(&tls.Config{ - Certificates: []tls.Certificate{cert}, - MinVersion: tls.VersionTLS12, - }), - ) + grpcServer := grpc.NewServer(grpc.Creds(credentials.NewTLS(&tls.Config{ + Certificates: []tls.Certificate{cert}, + MinVersion: tls.VersionTLS12, + }))) + healthpb.RegisterHealthServer(grpcServer, &healthServer{}) go grpcServer.Serve(listener) return func() { @@ -588,18 +481,18 @@ func startTLSListener(t testing.TB, factory func(credentials.TransportCredential }, address } -var listeners = map[string]func(testing.TB, func(credentials.TransportCredentials) *grpc.Server) (func(), string){ +var listeners = map[string]func(testing.TB) (func(), string){ "tcp": startTCPListener, "unix": startUnixListener, "tls": startTLSListener, } // startListeners will start all the different listeners used in this test -func startListeners(t testing.TB, factory func(credentials.TransportCredentials) *grpc.Server) (func(), map[string]string) { +func startListeners(t testing.TB) (func(), map[string]string) { var closers []func() connectionMap := map[string]string{} for k, v := range listeners { - closer, address := v(t, factory) + closer, address := v(t) closers = append(closers, closer) connectionMap[k] = address } @@ -639,5 +532,3 @@ func TestHealthCheckDialer(t *testing.T) { require.NoError(t, err) require.NoError(t, cc.Close()) } - -func newLogger(t testing.TB) *logrus.Entry { return logrus.NewEntry(testhelper.NewTestLogger(t)) } diff --git a/client/sidechannel.go b/client/sidechannel.go deleted file mode 100644 index 26729c138..000000000 --- a/client/sidechannel.go +++ /dev/null @@ -1,90 +0,0 @@ -package client - -import ( - "context" - "io" - - "github.com/sirupsen/logrus" - "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" - "gitlab.com/gitlab-org/gitaly/v14/internal/listenmux" - "gitlab.com/gitlab-org/gitaly/v14/internal/sidechannel" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" -) - -// SidechannelRegistry associates sidechannel callbacks with outbound -// gRPC calls. -type SidechannelRegistry struct { - registry *sidechannel.Registry - logger *logrus.Entry -} - -// NewSidechannelRegistry returns a new registry. -func NewSidechannelRegistry(logger *logrus.Entry) *SidechannelRegistry { - return &SidechannelRegistry{ - registry: sidechannel.NewRegistry(), - logger: logger, - } -} - -// Register registers a callback. It adds metadata to ctx and returns the -// new context. The caller must use the new context for the gRPC call. -// Caller must Close() the returned SidechannelWaiter to prevent resource -// leaks. -func (sr *SidechannelRegistry) Register( - ctx context.Context, - callback func(SidechannelConn) error, -) (context.Context, *SidechannelWaiter) { - ctx, waiter := sidechannel.RegisterSidechannel( - ctx, - sr.registry, - func(cc *sidechannel.ClientConn) error { return callback(cc) }, - ) - return ctx, &SidechannelWaiter{waiter: waiter} -} - -// SidechannelWaiter represents a pending sidechannel and its callback. -type SidechannelWaiter struct{ waiter *sidechannel.Waiter } - -// Close de-registers the sidechannel callback. If the callback is still -// running, Close blocks until it is done and returns the error return -// value of the callback. If the callback has not been called yet, Close -// returns an error immediately. -func (w *SidechannelWaiter) Close() error { return w.waiter.Close() } - -// SidechannelConn allows a client to read and write bytes with less -// overhead than doing so via gRPC messages. -type SidechannelConn interface { - io.ReadWriter - - // CloseWrite tells the server we won't write any more data. We can still - // read data from the server after CloseWrite(). A typical use case is in - // an RPC where the byte stream has a request/response pattern: the - // client then uses CloseWrite() to signal the end of the request body. - // When the client calls CloseWrite(), the server receives EOF. - CloseWrite() error -} - -// TestSidechannelServer allows downstream consumers of this package to -// create mock sidechannel gRPC servers. -func TestSidechannelServer( - logger *logrus.Entry, - creds credentials.TransportCredentials, - handler func(interface{}, grpc.ServerStream, io.ReadWriteCloser) error, -) []grpc.ServerOption { - lm := listenmux.New(creds) - lm.Register(backchannel.NewServerHandshaker(logger, backchannel.NewRegistry(), nil)) - - return []grpc.ServerOption{ - grpc.Creds(lm), - grpc.UnknownServiceHandler(func(srv interface{}, stream grpc.ServerStream) error { - conn, err := sidechannel.OpenSidechannel(stream.Context()) - if err != nil { - return err - } - defer conn.Close() - - return handler(srv, stream, conn) - }), - } -} diff --git a/cmd/gitaly-backup/main.go b/cmd/gitaly-backup/main.go index 641fda42c..4d4846563 100644 --- a/cmd/gitaly-backup/main.go +++ b/cmd/gitaly-backup/main.go @@ -6,7 +6,8 @@ import ( "io" "os" - "gitlab.com/gitlab-org/gitaly/v14/internal/log" + log "github.com/sirupsen/logrus" + glog "gitlab.com/gitlab-org/gitaly/v14/internal/log" ) type subcmd interface { @@ -20,21 +21,19 @@ var subcommands = map[string]subcmd{ } func main() { - log.Configure(log.Loggers, "", "") - - logger := log.Default() + glog.Configure(glog.Loggers, "", "") flags := flag.NewFlagSet("gitaly-backup", flag.ExitOnError) _ = flags.Parse(os.Args) if flags.NArg() < 2 { - logger.Fatal("missing subcommand") + log.Fatal("missing subcommand") } subcmdName := flags.Arg(1) subcmd, ok := subcommands[subcmdName] if !ok { - logger.Fatalf("unknown subcommand: %q", flags.Arg(1)) + log.Fatalf("unknown subcommand: %q", flags.Arg(1)) } subcmdFlags := flag.NewFlagSet(subcmdName, flag.ExitOnError) @@ -42,6 +41,6 @@ func main() { _ = subcmdFlags.Parse(flags.Args()[2:]) if err := subcmd.Run(context.Background(), os.Stdin, os.Stdout); err != nil { - logger.Fatalf("%s", err) + log.Fatalf("%s", err) } } diff --git a/cmd/gitaly-git2go/merge.go b/cmd/gitaly-git2go/merge.go index 316e49714..8d57cb16d 100644 --- a/cmd/gitaly-git2go/merge.go +++ b/cmd/gitaly-git2go/merge.go @@ -18,16 +18,27 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/git2go" ) -type mergeSubcommand struct{} +type mergeSubcommand struct { + request string +} func (cmd *mergeSubcommand) Flags() *flag.FlagSet { flags := flag.NewFlagSet("merge", flag.ExitOnError) + flags.StringVar(&cmd.request, "request", "", "git2go.MergeCommand") return flags } func (cmd *mergeSubcommand) Run(_ context.Context, r io.Reader, w io.Writer) error { + useGob := cmd.request == "" + + var err error var request git2go.MergeCommand - if err := gob.NewDecoder(r).Decode(&request); err != nil { + if useGob { + err = gob.NewDecoder(r).Decode(&request) + } else { + request, err = git2go.MergeCommandFromSerialized(cmd.request) + } + if err != nil { return err } @@ -35,15 +46,30 @@ func (cmd *mergeSubcommand) Run(_ context.Context, r io.Reader, w io.Writer) err request.AuthorDate = time.Now() } - commitID, err := merge(request) + commitID, err := merge(request, useGob) + if useGob { + return gob.NewEncoder(w).Encode(git2go.Result{ + CommitID: commitID, + Error: git2go.SerializableError(err), + }) + } - return gob.NewEncoder(w).Encode(git2go.Result{ + if err != nil { + return err + } + + response := git2go.MergeResult{ CommitID: commitID, - Error: git2go.SerializableError(err), - }) + } + + if err := response.SerializeTo(w); err != nil { + return err + } + + return nil } -func merge(request git2go.MergeCommand) (string, error) { +func merge(request git2go.MergeCommand, useStructuredErrors bool) (string, error) { repo, err := git2goutil.OpenRepository(request.Repository) if err != nil { return "", fmt.Errorf("could not open repository: %w", err) @@ -74,17 +100,21 @@ func merge(request git2go.MergeCommand) (string, error) { if index.HasConflicts() { if !request.AllowConflicts { - conflictingFiles, err := getConflictingFiles(index) - if err != nil { - return "", fmt.Errorf("getting conflicting files: %w", err) - } + if useStructuredErrors { + conflictingFiles, err := getConflictingFiles(index) + if err != nil { + return "", fmt.Errorf("getting conflicting files: %w", err) + } - return "", git2go.ConflictingFilesError{ - ConflictingFiles: conflictingFiles, + return "", git2go.ConflictingFilesError{ + ConflictingFiles: conflictingFiles, + } } + + return "", errors.New("could not auto-merge due to conflicts") } - if err := resolveConflicts(repo, index); err != nil { + if err := resolveConflicts(repo, index, useStructuredErrors); err != nil { return "", fmt.Errorf("could not resolve conflicts: %w", err) } } @@ -103,7 +133,7 @@ func merge(request git2go.MergeCommand) (string, error) { return commit.String(), nil } -func resolveConflicts(repo *git.Repository, index *git.Index) error { +func resolveConflicts(repo *git.Repository, index *git.Index, useStructuredErrors bool) error { // We need to get all conflicts up front as resolving conflicts as we // iterate breaks the iterator. indexConflicts, err := getConflicts(index) @@ -164,14 +194,18 @@ func resolveConflicts(repo *git.Repository, index *git.Index) error { } if index.HasConflicts() { - conflictingFiles, err := getConflictingFiles(index) - if err != nil { - return fmt.Errorf("getting conflicting files: %w", err) - } + if useStructuredErrors { + conflictingFiles, err := getConflictingFiles(index) + if err != nil { + return fmt.Errorf("getting conflicting files: %w", err) + } - return git2go.ConflictingFilesError{ - ConflictingFiles: conflictingFiles, + return git2go.ConflictingFilesError{ + ConflictingFiles: conflictingFiles, + } } + + return errors.New("index still has conflicts") } return nil diff --git a/cmd/gitaly-git2go/merge_test.go b/cmd/gitaly-git2go/merge_test.go index d12937e98..99aca86d4 100644 --- a/cmd/gitaly-git2go/merge_test.go +++ b/cmd/gitaly-git2go/merge_test.go @@ -4,6 +4,8 @@ package main import ( + "context" + "errors" "fmt" "testing" "time" @@ -16,16 +18,18 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v14/internal/git2go" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" ) -func TestMerge_missingArguments(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() +func TestMergeFailsWithMissingArguments(t *testing.T) { + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testMergeFailsWithMissingArguments) +} +func testMergeFailsWithMissingArguments(t *testing.T, ctx context.Context) { cfg, repo, repoPath := testcfg.BuildWithRepo(t) executor := git2go.NewExecutor(cfg, config.NewLocator(cfg)) @@ -79,12 +83,13 @@ func TestMerge_missingArguments(t *testing.T) { } } -func TestMerge_invalidRepositoryPath(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() +func TestMergeFailsWithInvalidRepositoryPath(t *testing.T) { + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testMergeFailsWithInvalidRepositoryPath) +} +func testMergeFailsWithInvalidRepositoryPath(t *testing.T, ctx context.Context) { cfg, repo, _ := testcfg.BuildWithRepo(t) testhelper.BuildGitalyGit2Go(t, cfg) executor := git2go.NewExecutor(cfg, config.NewLocator(cfg)) @@ -96,20 +101,22 @@ func TestMerge_invalidRepositoryPath(t *testing.T) { require.Contains(t, err.Error(), "merge: could not open repository") } -func TestMerge_trees(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() +func TestMergeTrees(t *testing.T) { + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testMergeTrees) +} +func testMergeTrees(t *testing.T, ctx context.Context) { testcases := []struct { - desc string - base map[string]string - ours map[string]string - theirs map[string]string - expected map[string]string - expectedResponse git2go.MergeResult - expectedErr error + desc string + base map[string]string + ours map[string]string + theirs map[string]string + expected map[string]string + expectedResponse git2go.MergeResult + expectedErr error + expectedErrWithoutGob error }{ { desc: "trivial merge succeeds", @@ -187,6 +194,8 @@ func TestMerge_trees(t *testing.T) { expectedErr: fmt.Errorf("merge: %w", git2go.ConflictingFilesError{ ConflictingFiles: []string{"1"}, }), + //nolint:revive + expectedErrWithoutGob: errors.New("merge: could not auto-merge due to conflicts\n"), }, } @@ -213,7 +222,11 @@ func TestMerge_trees(t *testing.T) { }) if tc.expectedErr != nil { - require.Equal(t, tc.expectedErr, err) + if featureflag.Git2GoMergeGob.IsEnabled(ctx) { + require.Equal(t, tc.expectedErr, err) + } else { + require.Equal(t, tc.expectedErrWithoutGob, err) + } return } @@ -247,11 +260,12 @@ func TestMerge_trees(t *testing.T) { } func TestMerge_recursive(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testMergeRecursive) +} +func testMergeRecursive(t *testing.T, ctx context.Context) { cfg := testcfg.Build(t) testhelper.BuildGitalyGit2Go(t, cfg) executor := git2go.NewExecutor(cfg, config.NewLocator(cfg)) @@ -318,9 +332,14 @@ func TestMerge_recursive(t *testing.T) { Ours: ours[len(ours)-1].String(), Theirs: theirs[len(theirs)-1].String(), }) - require.Equal(t, fmt.Errorf("merge: %w", git2go.ConflictingFilesError{ - ConflictingFiles: []string{"theirs"}, - }), err) + if featureflag.Git2GoMergeGob.IsEnabled(ctx) { + require.Equal(t, fmt.Errorf("merge: %w", git2go.ConflictingFilesError{ + ConflictingFiles: []string{"theirs"}, + }), err) + } else { + //nolint:revive + require.Equal(t, errors.New("merge: could not auto-merge due to conflicts\n"), err) + } // Otherwise, if we're merging an earlier criss-cross merge which has // half of the limit many criss-cross patterns, we exactly hit the diff --git a/cmd/gitaly-wrapper/main.go b/cmd/gitaly-wrapper/main.go index 3eeb55ad5..3fc315b3c 100644 --- a/cmd/gitaly-wrapper/main.go +++ b/cmd/gitaly-wrapper/main.go @@ -23,58 +23,55 @@ const ( ) func main() { - var logFormat string if jsonLogging() { - logFormat = "json" + logrus.SetFormatter(&logrus.JSONFormatter{TimestampFormat: log.LogTimestampFormat}) } - log.Configure(log.Loggers, logFormat, "") - if len(os.Args) < 2 { logrus.Fatalf("usage: %s forking_binary [args]", os.Args[0]) } gitalyBin, gitalyArgs := os.Args[1], os.Args[2:] - logger := log.Default().WithField("wrapper", os.Getpid()) - logger.Info("Wrapper started") + log := logrus.WithField("wrapper", os.Getpid()) + log.Info("Wrapper started") if pidFile() == "" { - logger.Fatalf("missing pid file ENV variable %q", bootstrap.EnvPidFile) + log.Fatalf("missing pid file ENV variable %q", bootstrap.EnvPidFile) } - logger.WithField("pid_file", pidFile()).Info("finding gitaly") + log.WithField("pid_file", pidFile()).Info("finding gitaly") gitaly, err := findGitaly() if err != nil && !isRecoverable(err) { - logger.WithError(err).Fatal("find gitaly") + log.WithError(err).Fatal("find gitaly") } else if err != nil { - logger.WithError(err).Error("find gitaly") + log.WithError(err).Error("find gitaly") } if gitaly != nil && isGitaly(gitaly, gitalyBin) { - logger.Info("adopting a process") + log.Info("adopting a process") } else { - logger.Info("spawning a process") + log.Info("spawning a process") proc, err := spawnGitaly(gitalyBin, gitalyArgs) if err != nil { - logger.WithError(err).Fatal("spawn gitaly") + log.WithError(err).Fatal("spawn gitaly") } gitaly = proc } - logger = logger.WithField("gitaly", gitaly.Pid) - logger.Info("monitoring gitaly") + log = log.WithField("gitaly", gitaly.Pid) + log.Info("monitoring gitaly") - forwardSignals(gitaly, logger) + forwardSignals(gitaly, log) // wait for isAlive(gitaly) { time.Sleep(1 * time.Second) } - logger.Error("wrapper for gitaly shutting down") + log.Error("wrapper for gitaly shutting down") } func isRecoverable(err error) bool { diff --git a/cmd/praefect/main.go b/cmd/praefect/main.go index 65328d49e..ed908551c 100644 --- a/cmd/praefect/main.go +++ b/cmd/praefect/main.go @@ -84,7 +84,6 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/nodes/tracker" "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/protoregistry" "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/reconciler" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/repocleaner" "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/service/transaction" "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/transactions" "gitlab.com/gitlab-org/gitaly/v14/internal/version" @@ -301,10 +300,6 @@ func run(cfgs []starter.Config, conf config.Config) error { }() healthChecker = hm - // Wait for the first health check to complete so the Praefect doesn't start serving RPC - // before the router is ready with the health status of the nodes. - <-hm.Updated() - elector := nodes.NewPerRepositoryElector(db) primaryGetter = elector @@ -356,7 +351,7 @@ func run(cfgs []starter.Config, conf config.Config) error { repl = praefect.NewReplMgr( logger, - conf.StorageNames(), + conf.VirtualStorageNames(), queue, rs, healthChecker, @@ -364,7 +359,6 @@ func run(cfgs []starter.Config, conf config.Config) error { praefect.WithDelayMetric(delayMetric), praefect.WithLatencyMetric(latencyMetric), praefect.WithDequeueBatchSize(conf.Replication.BatchSize), - praefect.WithParallelStorageProcessingWorkers(conf.Replication.ParallelStorageProcessingWorkers), ) srvFactory = praefect.NewServerFactory( conf, @@ -427,7 +421,7 @@ func run(cfgs []starter.Config, conf config.Config) error { return fmt.Errorf("unable to start the bootstrap: %v", err) } - go repl.ProcessBacklog(ctx, praefect.ExpBackoffFactory{Start: time.Second, Max: 5 * time.Second}) + go repl.ProcessBacklog(ctx, praefect.ExpBackoffFunc(1*time.Second, 5*time.Second)) logger.Info("background started: processing of the replication events") repl.ProcessStale(ctx, 30*time.Second, time.Minute) logger.Info("background started: processing of the stale replication events") @@ -448,29 +442,6 @@ func run(cfgs []starter.Config, conf config.Config) error { } } - if interval := conf.RepositoriesCleanup.RunInterval.Duration(); interval > 0 { - if db != nil { - go func() { - storageSync := datastore.NewStorageCleanup(db) - cfg := repocleaner.Cfg{ - RunInterval: conf.RepositoriesCleanup.RunInterval.Duration(), - LivenessInterval: 30 * time.Second, - RepositoriesInBatch: conf.RepositoriesCleanup.RepositoriesInBatch, - } - repoCleaner := repocleaner.NewRunner(cfg, logger, healthChecker, nodeSet.Connections(), storageSync, storageSync, repocleaner.NewLogWarnAction(logger)) - if err := repoCleaner.Run(ctx, helper.NewTimerTicker(conf.RepositoriesCleanup.CheckInterval.Duration())); err != nil && !errors.Is(context.Canceled, err) { - logger.WithError(err).Error("repository cleaner finished execution") - } else { - logger.Info("repository cleaner finished execution") - } - }() - } else { - logger.Warn("Repository cleanup background task disabled as there is no database connection configured.") - } - } else { - logger.Warn(`Repository cleanup background task disabled as "repositories_cleanup.run_interval" is not set or 0.`) - } - return b.Wait(conf.GracefulStopTimeout.Duration()) } diff --git a/cmd/praefect/subcmd.go b/cmd/praefect/subcmd.go index 70721aa92..ca11658fe 100644 --- a/cmd/praefect/subcmd.go +++ b/cmd/praefect/subcmd.go @@ -33,7 +33,6 @@ var subcommands = map[string]subcmd{ "accept-dataloss": &acceptDatalossSubcommand{}, "set-replication-factor": newSetReplicatioFactorSubcommand(os.Stdout), removeRepositoryCmdName: newRemoveRepository(logger), - trackRepositoryCmdName: newTrackRepository(logger), } // subCommand returns an exit code, to be fed into os.Exit. diff --git a/cmd/praefect/subcmd_track_repository.go b/cmd/praefect/subcmd_track_repository.go deleted file mode 100644 index 0be14d778..000000000 --- a/cmd/praefect/subcmd_track_repository.go +++ /dev/null @@ -1,230 +0,0 @@ -package main - -import ( - "context" - "database/sql" - "errors" - "flag" - "fmt" - "math/rand" - "time" - - "github.com/sirupsen/logrus" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/commonerr" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore/glsql" - "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" - "gitlab.com/gitlab-org/labkit/correlation" - "google.golang.org/grpc/metadata" -) - -const ( - trackRepositoryCmdName = "track-repository" -) - -type trackRepository struct { - logger logrus.FieldLogger - virtualStorage string - relativePath string - authoritativeStorage string -} - -var errAuthoritativeRepositoryNotExist = errors.New("authoritative repository does not exist") - -func newTrackRepository(logger logrus.FieldLogger) *trackRepository { - return &trackRepository{logger: logger} -} - -func (cmd *trackRepository) FlagSet() *flag.FlagSet { - fs := flag.NewFlagSet(trackRepositoryCmdName, flag.ExitOnError) - fs.StringVar(&cmd.virtualStorage, paramVirtualStorage, "", "name of the repository's virtual storage") - fs.StringVar(&cmd.relativePath, paramRelativePath, "", "relative path to the repository") - fs.StringVar(&cmd.authoritativeStorage, paramAuthoritativeStorage, "", "storage with the repository to consider as authoritative") - fs.Usage = func() { - _, _ = printfErr("Description:\n" + - " This command adds a given repository to be tracked by Praefect.\n" + - " It checks if the repository exists on disk on the authoritative storage, " + - " and whether database records are absent from tracking the repository.") - fs.PrintDefaults() - } - return fs -} - -func (cmd trackRepository) Exec(flags *flag.FlagSet, cfg config.Config) error { - switch { - case flags.NArg() > 0: - return unexpectedPositionalArgsError{Command: flags.Name()} - case cmd.virtualStorage == "": - return requiredParameterError(paramVirtualStorage) - case cmd.relativePath == "": - return requiredParameterError(paramRelativePath) - case cmd.authoritativeStorage == "": - if cfg.Failover.ElectionStrategy == config.ElectionStrategyPerRepository { - return requiredParameterError(paramAuthoritativeStorage) - } - } - - db, err := glsql.OpenDB(cfg.DB) - if err != nil { - return fmt.Errorf("connect to database: %w", err) - } - defer func() { _ = db.Close() }() - - ctx := correlation.ContextWithCorrelation(context.Background(), correlation.SafeRandomID()) - logger := cmd.logger.WithField("correlation_id", correlation.ExtractFromContext(ctx)) - - return cmd.exec(ctx, logger, db, cfg) -} - -const trackRepoErrorPrefix = "attempting to track repository in praefect database" - -func (cmd *trackRepository) exec(ctx context.Context, logger logrus.FieldLogger, db *sql.DB, cfg config.Config) error { - logger.WithFields(logrus.Fields{ - "virtual_storage": cmd.virtualStorage, - "relative_path": cmd.relativePath, - "authoritative_storage": cmd.authoritativeStorage, - }).Debug("track repository") - - var primary string - var secondaries []string - var variableReplicationFactorEnabled, savePrimary bool - if cfg.Failover.ElectionStrategy == config.ElectionStrategyPerRepository { - savePrimary = true - primary = cmd.authoritativeStorage - - for _, vs := range cfg.VirtualStorages { - if vs.Name == cmd.virtualStorage { - for _, node := range vs.Nodes { - if node.Storage == cmd.authoritativeStorage { - continue - } - secondaries = append(secondaries, node.Storage) - } - } - } - - r := rand.New(rand.NewSource(time.Now().UnixNano())) - replicationFactor := cfg.DefaultReplicationFactors()[cmd.virtualStorage] - - if replicationFactor > 0 { - variableReplicationFactorEnabled = true - // Select random secondaries according to the default replication factor. - r.Shuffle(len(secondaries), func(i, j int) { - secondaries[i], secondaries[j] = secondaries[j], secondaries[i] - }) - - secondaries = secondaries[:replicationFactor-1] - } - } else { - savePrimary = false - if err := db.QueryRowContext(ctx, `SELECT node_name FROM shard_primaries WHERE shard_name = $1 AND demoted = 'false'`, cmd.virtualStorage).Scan(&primary); err != nil { - if errors.Is(err, sql.ErrNoRows) { - return fmt.Errorf("%s: no primaries found", trackRepoErrorPrefix) - } - return fmt.Errorf("%s: %w", trackRepoErrorPrefix, err) - } - } - - authoritativeRepoExists, err := cmd.authoritativeRepositoryExists(ctx, cfg, primary) - if err != nil { - return fmt.Errorf("%s: %w", trackRepoErrorPrefix, err) - } - - if !authoritativeRepoExists { - return fmt.Errorf("%s: %w", trackRepoErrorPrefix, errAuthoritativeRepositoryNotExist) - } - - if err := cmd.trackRepository( - ctx, - datastore.NewPostgresRepositoryStore(db, cfg.StorageNames()), - primary, - secondaries, - savePrimary, - variableReplicationFactorEnabled, - ); err != nil { - return fmt.Errorf("%s: %w", trackRepoErrorPrefix, err) - } - - logger.Debug("finished adding new repository to be tracked in praefect database.") - - return nil -} - -func (cmd *trackRepository) trackRepository( - ctx context.Context, - ds *datastore.PostgresRepositoryStore, - primary string, - secondaries []string, - savePrimary bool, - variableReplicationFactorEnabled bool, -) error { - repositoryID, err := ds.ReserveRepositoryID(ctx, cmd.virtualStorage, cmd.relativePath) - if err != nil { - if errors.Is(err, commonerr.ErrRepositoryAlreadyExists) { - cmd.logger.Print("repository is already tracked in praefect database") - return nil - } - - return fmt.Errorf("ReserveRepositoryID: %w", err) - } - - if err := ds.CreateRepository( - ctx, - repositoryID, - cmd.virtualStorage, - cmd.relativePath, - primary, - nil, - secondaries, - savePrimary, - variableReplicationFactorEnabled, - ); err != nil { - return fmt.Errorf("CreateRepository: %w", err) - } - - return nil -} - -func (cmd *trackRepository) repositoryExists(ctx context.Context, repo *gitalypb.Repository, addr, token string) (bool, error) { - conn, err := subCmdDial(addr, token) - if err != nil { - return false, fmt.Errorf("error dialing: %w", err) - } - defer func() { _ = conn.Close() }() - - ctx = metadata.AppendToOutgoingContext(ctx, "client_name", trackRepositoryCmdName) - repositoryClient := gitalypb.NewRepositoryServiceClient(conn) - res, err := repositoryClient.RepositoryExists(ctx, &gitalypb.RepositoryExistsRequest{Repository: repo}) - if err != nil { - return false, err - } - - return res.GetExists(), nil -} - -func (cmd *trackRepository) authoritativeRepositoryExists(ctx context.Context, cfg config.Config, nodeName string) (bool, error) { - for _, vs := range cfg.VirtualStorages { - if vs.Name != cmd.virtualStorage { - continue - } - - for _, node := range vs.Nodes { - if node.Storage == nodeName { - logger.Debugf("check if repository %q exists on gitaly %q at %q", cmd.relativePath, node.Storage, node.Address) - repo := &gitalypb.Repository{ - StorageName: node.Storage, - RelativePath: cmd.relativePath, - } - exists, err := cmd.repositoryExists(ctx, repo, node.Address, node.Token) - if err != nil { - logger.WithError(err).Warnf("checking if repository exists %q, %q", node.Storage, cmd.relativePath) - return false, nil - } - return exists, nil - } - } - return false, fmt.Errorf("node %q not found", cmd.authoritativeStorage) - } - return false, fmt.Errorf("virtual storage %q not found", cmd.virtualStorage) -} diff --git a/cmd/praefect/subcmd_track_repository_test.go b/cmd/praefect/subcmd_track_repository_test.go deleted file mode 100644 index 9c6c5e2d0..000000000 --- a/cmd/praefect/subcmd_track_repository_test.go +++ /dev/null @@ -1,233 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "path/filepath" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/client" - "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/setup" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore/glsql" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/nodes" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/protoregistry" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/promtest" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testserver" - "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" -) - -func TestAddRepository_FlagSet(t *testing.T) { - t.Parallel() - cmd := &trackRepository{} - fs := cmd.FlagSet() - require.NoError(t, fs.Parse([]string{"--virtual-storage", "vs", "--repository", "repo", "--authoritative-storage", "storage-0"})) - require.Equal(t, "vs", cmd.virtualStorage) - require.Equal(t, "repo", cmd.relativePath) - require.Equal(t, "storage-0", cmd.authoritativeStorage) -} - -func TestAddRepository_Exec_invalidArgs(t *testing.T) { - t.Parallel() - t.Run("not all flag values processed", func(t *testing.T) { - cmd := trackRepository{} - flagSet := flag.NewFlagSet("cmd", flag.PanicOnError) - require.NoError(t, flagSet.Parse([]string{"stub"})) - err := cmd.Exec(flagSet, config.Config{}) - require.EqualError(t, err, "cmd doesn't accept positional arguments") - }) - - t.Run("virtual-storage is not set", func(t *testing.T) { - cmd := trackRepository{} - err := cmd.Exec(flag.NewFlagSet("", flag.PanicOnError), config.Config{}) - require.EqualError(t, err, `"virtual-storage" is a required parameter`) - }) - - t.Run("repository is not set", func(t *testing.T) { - cmd := trackRepository{virtualStorage: "stub"} - err := cmd.Exec(flag.NewFlagSet("", flag.PanicOnError), config.Config{}) - require.EqualError(t, err, `"repository" is a required parameter`) - }) - - t.Run("authoritative-storage is not set", func(t *testing.T) { - cmd := trackRepository{virtualStorage: "stub", relativePath: "path/to/repo"} - err := cmd.Exec(flag.NewFlagSet("", flag.PanicOnError), config.Config{Failover: config.Failover{ElectionStrategy: config.ElectionStrategyPerRepository}}) - require.EqualError(t, err, `"authoritative-storage" is a required parameter`) - }) - - t.Run("db connection error", func(t *testing.T) { - cmd := trackRepository{virtualStorage: "stub", relativePath: "stub", authoritativeStorage: "storage-0"} - cfg := config.Config{DB: config.DB{Host: "stub", SSLMode: "disable"}} - err := cmd.Exec(flag.NewFlagSet("", flag.PanicOnError), cfg) - require.Error(t, err) - require.Contains(t, err.Error(), "connect to database: dial tcp: lookup stub") - }) -} - -func TestAddRepository_Exec(t *testing.T) { - t.Parallel() - g1Cfg := testcfg.Build(t, testcfg.WithStorages("gitaly-1")) - g2Cfg := testcfg.Build(t, testcfg.WithStorages("gitaly-2")) - - g1Srv := testserver.StartGitalyServer(t, g1Cfg, nil, setup.RegisterAll, testserver.WithDisablePraefect()) - g2Srv := testserver.StartGitalyServer(t, g2Cfg, nil, setup.RegisterAll, testserver.WithDisablePraefect()) - defer g2Srv.Shutdown() - defer g1Srv.Shutdown() - - g1Addr := g1Srv.Address() - - db := glsql.NewDB(t) - var database string - require.NoError(t, db.QueryRow(`SELECT current_database()`).Scan(&database)) - dbConf := glsql.GetDBConfig(t, database) - - virtualStorageName := "praefect" - conf := config.Config{ - AllowLegacyElectors: true, - SocketPath: testhelper.GetTemporaryGitalySocketFileName(t), - VirtualStorages: []*config.VirtualStorage{ - { - Name: virtualStorageName, - Nodes: []*config.Node{ - {Storage: g1Cfg.Storages[0].Name, Address: g1Addr}, - {Storage: g2Cfg.Storages[0].Name, Address: g2Srv.Address()}, - }, - DefaultReplicationFactor: 2, - }, - }, - DB: dbConf, - } - - gitalyCC, err := client.Dial(g1Addr, nil) - require.NoError(t, err) - defer func() { require.NoError(t, gitalyCC.Close()) }() - ctx, cancel := testhelper.Context() - defer cancel() - - gitaly1RepositoryClient := gitalypb.NewRepositoryServiceClient(gitalyCC) - - createRepoThroughGitaly1 := func(relativePath string) error { - _, err := gitaly1RepositoryClient.CreateRepository( - ctx, - &gitalypb.CreateRepositoryRequest{ - Repository: &gitalypb.Repository{ - StorageName: g1Cfg.Storages[0].Name, - RelativePath: relativePath, - }, - }) - return err - } - - testCases := map[string]struct { - failoverConfig config.Failover - authoritativeStorage string - }{ - "sql election": { - failoverConfig: config.Failover{ - Enabled: true, - ElectionStrategy: config.ElectionStrategySQL, - }, - authoritativeStorage: "", - }, - "per repository election": { - failoverConfig: config.Failover{ - Enabled: true, - ElectionStrategy: config.ElectionStrategyPerRepository, - }, - authoritativeStorage: g1Cfg.Storages[0].Name, - }, - } - - logger := testhelper.NewTestLogger(t) - for tn, tc := range testCases { - t.Run(tn, func(t *testing.T) { - addCmdConf := conf - addCmdConf.Failover = tc.failoverConfig - - t.Run("ok", func(t *testing.T) { - nodeMgr, err := nodes.NewManager(testhelper.DiscardTestEntry(t), addCmdConf, db.DB, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil) - require.NoError(t, err) - nodeMgr.Start(0, time.Hour) - - relativePath := fmt.Sprintf("path/to/test/repo_%s", tn) - repoDS := datastore.NewPostgresRepositoryStore(db, conf.StorageNames()) - - require.NoError(t, createRepoThroughGitaly1(relativePath)) - - rmRepoCmd := &removeRepository{ - logger: logger, - virtualStorage: virtualStorageName, - relativePath: relativePath, - } - - require.NoError(t, rmRepoCmd.Exec(flag.NewFlagSet("", flag.PanicOnError), conf)) - - // create the repo on Gitaly without Praefect knowing - require.NoError(t, createRepoThroughGitaly1(relativePath)) - require.DirExists(t, filepath.Join(g1Cfg.Storages[0].Path, relativePath)) - require.NoDirExists(t, filepath.Join(g2Cfg.Storages[0].Path, relativePath)) - - addRepoCmd := &trackRepository{ - logger: logger, - virtualStorage: virtualStorageName, - relativePath: relativePath, - authoritativeStorage: tc.authoritativeStorage, - } - - require.NoError(t, addRepoCmd.Exec(flag.NewFlagSet("", flag.PanicOnError), addCmdConf)) - as := datastore.NewAssignmentStore(db, conf.StorageNames()) - - assignments, err := as.GetHostAssignments(ctx, virtualStorageName, relativePath) - require.NoError(t, err) - require.Len(t, assignments, 2) - assert.Contains(t, assignments, g1Cfg.Storages[0].Name) - assert.Contains(t, assignments, g2Cfg.Storages[0].Name) - - exists, err := repoDS.RepositoryExists(ctx, virtualStorageName, relativePath) - require.NoError(t, err) - assert.True(t, exists) - }) - - t.Run("repository does not exist", func(t *testing.T) { - relativePath := fmt.Sprintf("path/to/test/repo_1_%s", tn) - - cmd := &trackRepository{ - logger: testhelper.NewTestLogger(t), - virtualStorage: "praefect", - relativePath: relativePath, - authoritativeStorage: tc.authoritativeStorage, - } - - assert.ErrorIs(t, cmd.Exec(flag.NewFlagSet("", flag.PanicOnError), addCmdConf), errAuthoritativeRepositoryNotExist) - }) - - t.Run("records already exist", func(t *testing.T) { - relativePath := fmt.Sprintf("path/to/test/repo_2_%s", tn) - - require.NoError(t, createRepoThroughGitaly1(relativePath)) - require.DirExists(t, filepath.Join(g1Cfg.Storages[0].Path, relativePath)) - require.NoDirExists(t, filepath.Join(g2Cfg.Storages[0].Path, relativePath)) - - ds := datastore.NewPostgresRepositoryStore(db, conf.StorageNames()) - id, err := ds.ReserveRepositoryID(ctx, virtualStorageName, relativePath) - require.NoError(t, err) - require.NoError(t, ds.CreateRepository(ctx, id, virtualStorageName, relativePath, g1Cfg.Storages[0].Name, nil, nil, true, true)) - - cmd := &trackRepository{ - logger: testhelper.NewTestLogger(t), - virtualStorage: virtualStorageName, - relativePath: relativePath, - authoritativeStorage: tc.authoritativeStorage, - } - - assert.NoError(t, cmd.Exec(flag.NewFlagSet("", flag.PanicOnError), addCmdConf)) - }) - }) - } -} diff --git a/internal/backup/backup.go b/internal/backup/backup.go index c59591b59..70a9b6d91 100644 --- a/internal/backup/backup.go +++ b/internal/backup/backup.go @@ -38,20 +38,10 @@ type Sink interface { GetReader(ctx context.Context, relativePath string) (io.ReadCloser, error) } -// Backup represents all the information needed to restore a backup for a repository -type Backup struct { - // Steps are the ordered list of steps required to restore this backup - Steps []Step -} - -// Step represents an incremental step that makes up a complete backup for a repository -type Step struct { +// Full represents all paths required for a full backup +type Full struct { // BundlePath is the path of the bundle BundlePath string - // SkippableOnNotFound defines if the bundle can be skipped when it does - // not exist. This allows us to maintain legacy behaviour where we always - // check a specific location for a bundle without knowing if it exists. - SkippableOnNotFound bool // RefPath is the path of the ref file RefPath string // CustomHooksPath is the path of the custom hooks archive @@ -60,14 +50,14 @@ type Step struct { // Locator finds sink backup paths for repositories type Locator interface { - // BeginFull returns a tentative first step needed to create a new full backup. - BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Step + // BeginFull returns paths for a new full backup + BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Full - // CommitFull marks the step returned by `BeginFull` as the latest backup. - CommitFull(ctx context.Context, step *Step) error + // CommitFull persists the paths for a new backup so that it can be looked up by FindLatestFull + CommitFull(ctx context.Context, full *Full) error - // FindLatest returns the latest backup that was written by CommitFull - FindLatest(ctx context.Context, repo *gitalypb.Repository) (*Backup, error) + // FindLatestFull returns the paths committed by the latest call to CommitFull + FindLatestFull(ctx context.Context, repo *gitalypb.Repository) (*Full, error) } // ResolveSink returns a sink implementation based on the provided path. @@ -182,40 +172,38 @@ func (mgr *Manager) Restore(ctx context.Context, req *RestoreRequest) error { return fmt.Errorf("manager: %w", err) } - backup, err := mgr.locator.FindLatest(ctx, req.Repository) + full, err := mgr.locator.FindLatestFull(ctx, req.Repository) if err != nil { - return fmt.Errorf("manager: %w", err) + return mgr.checkRestoreSkip(ctx, err, req) } - if err := mgr.createRepository(ctx, req.Server, req.Repository); err != nil { + if err := mgr.restoreBundle(ctx, full.BundlePath, req.Server, req.Repository); err != nil { + return mgr.checkRestoreSkip(ctx, err, req) + } + if err := mgr.restoreCustomHooks(ctx, full.CustomHooksPath, req.Server, req.Repository); err != nil { return fmt.Errorf("manager: %w", err) } + return nil +} - for _, step := range backup.Steps { - if err := mgr.restoreBundle(ctx, step.BundlePath, req.Server, req.Repository); err != nil { - if step.SkippableOnNotFound && errors.Is(err, ErrDoesntExist) { - // For compatibility with existing backups we need to make sure the - // repository exists even if there's no bundle for project - // repositories (not wiki or snippet repositories). Gitaly does - // not know which repository is which type so here we accept a - // parameter to tell us to employ this behaviour. Since the - // repository has already been created, we simply skip cleaning up. - if req.AlwaysCreate { - return nil - } - - if err := mgr.removeRepository(ctx, req.Server, req.Repository); err != nil { - return fmt.Errorf("manager: remove on skipped: %w", err) - } - - return fmt.Errorf("manager: %w: %s", ErrSkipped, err.Error()) +func (mgr *Manager) checkRestoreSkip(ctx context.Context, err error, req *RestoreRequest) error { + if errors.Is(err, ErrDoesntExist) { + // For compatibility with existing backups we need to always create the + // repository even if there's no bundle for project repositories + // (not wiki or snippet repositories). Gitaly does not know which + // repository is which type so here we accept a parameter to tell us + // to employ this behaviour. + if req.AlwaysCreate { + if err := mgr.createRepository(ctx, req.Server, req.Repository); err != nil { + return fmt.Errorf("manager: %w", err) } + return nil } - if err := mgr.restoreCustomHooks(ctx, step.CustomHooksPath, req.Server, req.Repository); err != nil { - return fmt.Errorf("manager: %w", err) - } + + return fmt.Errorf("manager: %w: %s", ErrSkipped, err.Error()) } - return nil + + return fmt.Errorf("manager: %w", err) } func (mgr *Manager) isEmpty(ctx context.Context, server storage.ServerInfo, repo *gitalypb.Repository) (bool, error) { @@ -329,11 +317,11 @@ func (mgr *Manager) restoreBundle(ctx context.Context, path string, server stora if err != nil { return fmt.Errorf("restore bundle: %q: %w", path, err) } - stream, err := repoClient.FetchBundle(ctx) + stream, err := repoClient.CreateRepositoryFromBundle(ctx) if err != nil { return fmt.Errorf("restore bundle: %q: %w", path, err) } - request := &gitalypb.FetchBundleRequest{Repository: repo} + request := &gitalypb.CreateRepositoryFromBundleRequest{Repository: repo} bundle := streamio.NewWriter(func(p []byte) error { request.Data = p if err := stream.Send(request); err != nil { @@ -341,7 +329,7 @@ func (mgr *Manager) restoreBundle(ctx context.Context, path string, server stora } // Only set `Repository` on the first `Send` of the stream - request = &gitalypb.FetchBundleRequest{} + request = &gitalypb.CreateRepositoryFromBundleRequest{} return nil }) diff --git a/internal/backup/backup_test.go b/internal/backup/backup_test.go index ab8304965..fd1dd04d8 100644 --- a/internal/backup/backup_test.go +++ b/internal/backup/backup_test.go @@ -2,6 +2,7 @@ package backup import ( "context" + "errors" "fmt" "os" "os/exec" @@ -202,8 +203,7 @@ func testManagerRestore(t *testing.T, cfg config.Cfg, gitalyAddr string) { cc, err := client.Dial(gitalyAddr, nil) require.NoError(t, err) - defer testhelper.MustClose(t, cc) - + defer func() { require.NoError(t, cc.Close()) }() repoClient := gitalypb.NewRepositoryServiceClient(cc) createRepo := func(t testing.TB, relativePath string) *gitalypb.Repository { @@ -211,7 +211,7 @@ func testManagerRestore(t *testing.T, cfg config.Cfg, gitalyAddr string) { repo := &gitalypb.Repository{ StorageName: "default", - RelativePath: gittest.NewRepositoryName(t, false) + relativePath, + RelativePath: relativePath, } for i := 0; true; i++ { @@ -230,158 +230,90 @@ func testManagerRestore(t *testing.T, cfg config.Cfg, gitalyAddr string) { path := testhelper.TempDir(t) + existingRepo := createRepo(t, "existing") + require.NoError(t, os.MkdirAll(filepath.Join(path, existingRepo.RelativePath), os.ModePerm)) + existingRepoBundlePath := filepath.Join(path, existingRepo.RelativePath+".bundle") + gittest.BundleTestRepo(t, cfg, "gitlab-test.git", existingRepoBundlePath) + + existingRepoHooks := createRepo(t, "existing_hooks") + existingRepoHooksBundlePath := filepath.Join(path, existingRepoHooks.RelativePath+".bundle") + existingRepoHooksCustomHooksPath := filepath.Join(path, existingRepoHooks.RelativePath, "custom_hooks.tar") + require.NoError(t, os.MkdirAll(filepath.Join(path, existingRepoHooks.RelativePath), os.ModePerm)) + testhelper.CopyFile(t, existingRepoBundlePath, existingRepoHooksBundlePath) + testhelper.CopyFile(t, "../gitaly/service/repository/testdata/custom_hooks.tar", existingRepoHooksCustomHooksPath) + + missingBundleRepo := createRepo(t, "missing_bundle") + missingBundleRepoAlwaysCreate := createRepo(t, "missing_bundle_always_create") + + nonexistentRepo := &gitalypb.Repository{ + StorageName: "default", + RelativePath: "nonexistent", + } + nonexistentRepoBundlePath := filepath.Join(path, nonexistentRepo.RelativePath+".bundle") + testhelper.CopyFile(t, existingRepoBundlePath, nonexistentRepoBundlePath) + for _, tc := range []struct { desc string - locators []string - setup func(t testing.TB) (repo *gitalypb.Repository, bundles []string) + repo *gitalypb.Repository alwaysCreate bool - expectExists bool expectedPaths []string expectedErrAs error + expectVerify bool }{ { - desc: "existing repo, without hooks", - locators: []string{"legacy", "pointer"}, - setup: func(t testing.TB) (repo *gitalypb.Repository, bundles []string) { - existingRepo := createRepo(t, "existing") - require.NoError(t, os.MkdirAll(filepath.Join(path, existingRepo.RelativePath), os.ModePerm)) - existingRepoBundlePath := filepath.Join(path, existingRepo.RelativePath+".bundle") - gittest.BundleTestRepo(t, cfg, "gitlab-test.git", existingRepoBundlePath) - return existingRepo, []string{existingRepoBundlePath} - }, - expectExists: true, + desc: "existing repo, without hooks", + repo: existingRepo, + expectVerify: true, }, { - desc: "existing repo, with hooks", - locators: []string{"legacy", "pointer"}, - setup: func(t testing.TB) (repo *gitalypb.Repository, bundles []string) { - existingRepoHooks := createRepo(t, "existing_hooks") - existingRepoHooksBundlePath := filepath.Join(path, existingRepoHooks.RelativePath+".bundle") - existingRepoHooksCustomHooksPath := filepath.Join(path, existingRepoHooks.RelativePath, "custom_hooks.tar") - require.NoError(t, os.MkdirAll(filepath.Join(path, existingRepoHooks.RelativePath), os.ModePerm)) - gittest.BundleTestRepo(t, cfg, "gitlab-test.git", existingRepoHooksBundlePath) - testhelper.CopyFile(t, "../gitaly/service/repository/testdata/custom_hooks.tar", existingRepoHooksCustomHooksPath) - return existingRepoHooks, []string{existingRepoHooksBundlePath} - }, + desc: "existing repo, with hooks", + repo: existingRepoHooks, expectedPaths: []string{ "custom_hooks/pre-commit.sample", "custom_hooks/prepare-commit-msg.sample", "custom_hooks/pre-push.sample", }, - expectExists: true, + expectVerify: true, }, { - desc: "missing bundle", - locators: []string{"legacy", "pointer"}, - setup: func(t testing.TB) (repo *gitalypb.Repository, bundles []string) { - missingBundleRepo := createRepo(t, "missing_bundle") - return missingBundleRepo, nil - }, + desc: "missing bundle", + repo: missingBundleRepo, expectedErrAs: ErrSkipped, }, { - desc: "missing bundle, always create", - locators: []string{"legacy", "pointer"}, - setup: func(t testing.TB) (repo *gitalypb.Repository, bundles []string) { - missingBundleRepoAlwaysCreate := createRepo(t, "missing_bundle_always_create") - return missingBundleRepoAlwaysCreate, nil - }, + desc: "missing bundle, always create", + repo: missingBundleRepoAlwaysCreate, alwaysCreate: true, - expectExists: true, - }, - { - desc: "nonexistent repo", - locators: []string{"legacy", "pointer"}, - setup: func(t testing.TB) (repo *gitalypb.Repository, bundles []string) { - nonexistentRepo := &gitalypb.Repository{ - StorageName: "default", - RelativePath: "nonexistent", - } - nonexistentRepoBundlePath := filepath.Join(path, nonexistentRepo.RelativePath+".bundle") - gittest.BundleTestRepo(t, cfg, "gitlab-test.git", nonexistentRepoBundlePath) - return nonexistentRepo, []string{nonexistentRepoBundlePath} - }, - expectExists: true, - }, - { - desc: "single incremental", - locators: []string{"pointer"}, - setup: func(t testing.TB) (*gitalypb.Repository, []string) { - const backupID = "abc123" - repo := createRepo(t, "incremental") - repoBackupPath := filepath.Join(path, repo.RelativePath) - backupPath := filepath.Join(repoBackupPath, backupID) - require.NoError(t, os.MkdirAll(backupPath, os.ModePerm)) - require.NoError(t, os.WriteFile(filepath.Join(repoBackupPath, "LATEST"), []byte(backupID), os.ModePerm)) - require.NoError(t, os.WriteFile(filepath.Join(backupPath, "LATEST"), []byte("001"), os.ModePerm)) - bundlePath := filepath.Join(backupPath, "001.bundle") - gittest.BundleTestRepo(t, cfg, "gitlab-test.git", bundlePath) - return repo, []string{bundlePath} - }, - expectExists: true, }, { - desc: "many incrementals", - locators: []string{"pointer"}, - setup: func(t testing.TB) (*gitalypb.Repository, []string) { - const backupID = "abc123" - repo := createRepo(t, "incremental") - repoBackupPath := filepath.Join(path, repo.RelativePath) - backupPath := filepath.Join(repoBackupPath, backupID) - require.NoError(t, os.MkdirAll(backupPath, os.ModePerm)) - require.NoError(t, os.WriteFile(filepath.Join(repoBackupPath, "LATEST"), []byte(backupID), os.ModePerm)) - require.NoError(t, os.WriteFile(filepath.Join(backupPath, "LATEST"), []byte("002"), os.ModePerm)) - - bundlePath1 := filepath.Join(backupPath, "001.bundle") - gittest.BundleTestRepo(t, cfg, "gitlab-test.git", bundlePath1, "master") - - bundlePath2 := filepath.Join(backupPath, "002.bundle") - gittest.BundleTestRepo(t, cfg, "gitlab-test.git", bundlePath2, "feature") - - return repo, []string{bundlePath1, bundlePath2} - }, - expectExists: true, + desc: "nonexistent repo", + repo: nonexistentRepo, + expectVerify: true, }, } { t.Run(tc.desc, func(t *testing.T) { - require.GreaterOrEqual(t, len(tc.locators), 1, "each test case must specify a locator") - - for _, locatorName := range tc.locators { - t.Run(locatorName, func(t *testing.T) { - repo, bundles := tc.setup(t) - repoPath := filepath.Join(cfg.Storages[0].Path, repo.RelativePath) - - sink := NewFilesystemSink(path) - locator, err := ResolveLocator(locatorName, sink) - require.NoError(t, err) - - fsBackup := NewManager(sink, locator) - err = fsBackup.Restore(ctx, &RestoreRequest{ - Server: storage.ServerInfo{Address: gitalyAddr, Token: cfg.Auth.Token}, - Repository: repo, - AlwaysCreate: tc.alwaysCreate, - }) - if tc.expectedErrAs != nil { - require.ErrorAs(t, err, &tc.expectedErrAs) - } else { - require.NoError(t, err) - } - - exists, err := repoClient.RepositoryExists(ctx, &gitalypb.RepositoryExistsRequest{ - Repository: repo, - }) - require.NoError(t, err) - require.Equal(t, tc.expectExists, exists.Exists, "repository exists") - - for _, bundlePath := range bundles { - output := gittest.Exec(t, cfg, "-C", repoPath, "bundle", "verify", bundlePath) - require.Contains(t, string(output), "The bundle records a complete history") - } - - for _, p := range tc.expectedPaths { - require.FileExists(t, filepath.Join(repoPath, p)) - } - }) + repoPath := filepath.Join(cfg.Storages[0].Path, tc.repo.RelativePath) + bundlePath := filepath.Join(path, tc.repo.RelativePath+".bundle") + + fsBackup := NewManager(NewFilesystemSink(path), LegacyLocator{}) + err := fsBackup.Restore(ctx, &RestoreRequest{ + Server: storage.ServerInfo{Address: gitalyAddr, Token: cfg.Auth.Token}, + Repository: tc.repo, + AlwaysCreate: tc.alwaysCreate, + }) + if tc.expectedErrAs != nil { + require.True(t, errors.Is(err, tc.expectedErrAs), err.Error()) + } else { + require.NoError(t, err) + } + + if tc.expectVerify { + output := gittest.Exec(t, cfg, "-C", repoPath, "bundle", "verify", bundlePath) + require.Contains(t, string(output), "The bundle records a complete history") + } + + for _, p := range tc.expectedPaths { + require.FileExists(t, filepath.Join(repoPath, p)) } }) } diff --git a/internal/backup/locator.go b/internal/backup/locator.go index 81e53dcb1..6110240b9 100644 --- a/internal/backup/locator.go +++ b/internal/backup/locator.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "path/filepath" - "strconv" "strings" "gitlab.com/gitlab-org/gitaly/v14/internal/helper/text" @@ -26,32 +25,27 @@ import ( type LegacyLocator struct{} // BeginFull returns the static paths for a legacy repository backup -func (l LegacyLocator) BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Step { +func (l LegacyLocator) BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Full { return l.newFull(repo) } // CommitFull is unused as the locations are static -func (l LegacyLocator) CommitFull(ctx context.Context, full *Step) error { +func (l LegacyLocator) CommitFull(ctx context.Context, full *Full) error { return nil } -// FindLatest returns the static paths for a legacy repository backup -func (l LegacyLocator) FindLatest(ctx context.Context, repo *gitalypb.Repository) (*Backup, error) { - return &Backup{ - Steps: []Step{ - *l.newFull(repo), - }, - }, nil +// FindLatestFull returns the static paths for a legacy repository backup +func (l LegacyLocator) FindLatestFull(ctx context.Context, repo *gitalypb.Repository) (*Full, error) { + return l.newFull(repo), nil } -func (l LegacyLocator) newFull(repo *gitalypb.Repository) *Step { +func (l LegacyLocator) newFull(repo *gitalypb.Repository) *Full { backupPath := strings.TrimSuffix(repo.RelativePath, ".git") - return &Step{ - SkippableOnNotFound: true, - BundlePath: backupPath + ".bundle", - RefPath: backupPath + ".refs", - CustomHooksPath: filepath.Join(backupPath, "custom_hooks.tar"), + return &Full{ + BundlePath: backupPath + ".bundle", + RefPath: backupPath + ".refs", + CustomHooksPath: filepath.Join(backupPath, "custom_hooks.tar"), } } @@ -60,78 +54,53 @@ func (l LegacyLocator) newFull(repo *gitalypb.Repository) *Step { // file named LATEST. // // Structure: +// <repo relative path>/<backup id>/full.bundle +// <repo relative path>/<backup id>/full.refs +// <repo relative path>/<backup id>/custom_hooks.tar // <repo relative path>/LATEST -// <repo relative path>/<backup id>/LATEST -// <repo relative path>/<backup id>/<nnn>.bundle -// <repo relative path>/<backup id>/<nnn>.refs -// <repo relative path>/<backup id>/<nnn>.custom_hooks.tar type PointerLocator struct { Sink Sink Fallback Locator } // BeginFull returns paths for a new full backup -func (l PointerLocator) BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Step { +func (l PointerLocator) BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Full { backupPath := strings.TrimSuffix(repo.RelativePath, ".git") - return &Step{ - BundlePath: filepath.Join(backupPath, backupID, "001.bundle"), - RefPath: filepath.Join(backupPath, backupID, "001.refs"), - CustomHooksPath: filepath.Join(backupPath, backupID, "001.custom_hooks.tar"), + return &Full{ + BundlePath: filepath.Join(backupPath, backupID, "full.bundle"), + RefPath: filepath.Join(backupPath, backupID, "full.refs"), + CustomHooksPath: filepath.Join(backupPath, backupID, "custom_hooks.tar"), } } -// CommitFull persists the paths for a new backup so that it can be looked up by FindLatest -func (l PointerLocator) CommitFull(ctx context.Context, full *Step) error { +// CommitFull persists the paths for a new backup so that it can be looked up by FindLatestFull +func (l PointerLocator) CommitFull(ctx context.Context, full *Full) error { bundleDir := filepath.Dir(full.BundlePath) backupID := filepath.Base(bundleDir) backupPath := filepath.Dir(bundleDir) - if err := l.writeLatest(ctx, bundleDir, "001"); err != nil { - return err - } - if err := l.writeLatest(ctx, backupPath, backupID); err != nil { - return err - } - return nil + return l.commitLatestID(ctx, backupPath, backupID) } -// FindLatest returns the paths committed by the latest call to CommitFull. +// FindLatestFull returns the paths committed by the latest call to CommitFull. // // If there is no `LATEST` file, the result of the `Fallback` is used. -func (l PointerLocator) FindLatest(ctx context.Context, repo *gitalypb.Repository) (*Backup, error) { - repoPath := strings.TrimSuffix(repo.RelativePath, ".git") +func (l PointerLocator) FindLatestFull(ctx context.Context, repo *gitalypb.Repository) (*Full, error) { + backupPath := strings.TrimSuffix(repo.RelativePath, ".git") - backupID, err := l.findLatestID(ctx, repoPath) + latest, err := l.findLatestID(ctx, backupPath) if err != nil { if l.Fallback != nil && errors.Is(err, ErrDoesntExist) { - return l.Fallback.FindLatest(ctx, repo) + return l.Fallback.FindLatestFull(ctx, repo) } - return nil, fmt.Errorf("pointer locator: backup: %w", err) - } - - backupPath := filepath.Join(repoPath, backupID) - - latestIncrementID, err := l.findLatestID(ctx, backupPath) - if err != nil { - return nil, fmt.Errorf("pointer locator: latest incremental: %w", err) - } - - max, err := strconv.Atoi(latestIncrementID) - if err != nil { - return nil, fmt.Errorf("pointer locator: latest incremental: %w", err) + return nil, fmt.Errorf("pointer locator: %w", err) } - var backup Backup - - for i := 1; i <= max; i++ { - backup.Steps = append(backup.Steps, Step{ - BundlePath: filepath.Join(backupPath, fmt.Sprintf("%03d.bundle", i)), - RefPath: filepath.Join(backupPath, fmt.Sprintf("%03d.refs", i)), - CustomHooksPath: filepath.Join(backupPath, fmt.Sprintf("%03d.custom_hooks.tar", i)), - }) - } - - return &backup, nil + return &Full{ + BundlePath: filepath.Join(backupPath, latest, "full.bundle"), + RefPath: filepath.Join(backupPath, latest, "full.refs"), + CustomHooksPath: filepath.Join(backupPath, latest, "custom_hooks.tar"), + }, nil } func (l PointerLocator) findLatestID(ctx context.Context, backupPath string) (string, error) { @@ -149,10 +118,10 @@ func (l PointerLocator) findLatestID(ctx context.Context, backupPath string) (st return text.ChompBytes(latest), nil } -func (l PointerLocator) writeLatest(ctx context.Context, path, target string) error { - latest := strings.NewReader(target) - if err := l.Sink.Write(ctx, filepath.Join(path, "LATEST"), latest); err != nil { - return fmt.Errorf("write latest: %w", err) +func (l PointerLocator) commitLatestID(ctx context.Context, backupPath, backupID string) error { + latest := strings.NewReader(backupID) + if err := l.Sink.Write(ctx, filepath.Join(backupPath, "LATEST"), latest); err != nil { + return fmt.Errorf("commit latest ID: %w", err) } return nil } diff --git a/internal/backup/locator_test.go b/internal/backup/locator_test.go index 7bd3b48d7..f8e97a2e5 100644 --- a/internal/backup/locator_test.go +++ b/internal/backup/locator_test.go @@ -19,11 +19,10 @@ func TestLegacyLocator(t *testing.T) { ctx, cancel := testhelper.Context() defer cancel() - expected := &Step{ - SkippableOnNotFound: true, - BundlePath: repo.RelativePath + ".bundle", - RefPath: repo.RelativePath + ".refs", - CustomHooksPath: filepath.Join(repo.RelativePath, "custom_hooks.tar"), + expected := &Full{ + BundlePath: repo.RelativePath + ".bundle", + RefPath: repo.RelativePath + ".refs", + CustomHooksPath: filepath.Join(repo.RelativePath, "custom_hooks.tar"), } full := l.BeginFull(ctx, repo, "abc123") @@ -32,22 +31,17 @@ func TestLegacyLocator(t *testing.T) { require.NoError(t, l.CommitFull(ctx, full)) }) - t.Run("FindLatest", func(t *testing.T) { + t.Run("FindLatestFull", func(t *testing.T) { ctx, cancel := testhelper.Context() defer cancel() - expected := &Backup{ - Steps: []Step{ - { - SkippableOnNotFound: true, - BundlePath: repo.RelativePath + ".bundle", - RefPath: repo.RelativePath + ".refs", - CustomHooksPath: filepath.Join(repo.RelativePath, "custom_hooks.tar"), - }, - }, + expected := &Full{ + BundlePath: repo.RelativePath + ".bundle", + RefPath: repo.RelativePath + ".refs", + CustomHooksPath: filepath.Join(repo.RelativePath, "custom_hooks.tar"), } - full, err := l.FindLatest(ctx, repo) + full, err := l.FindLatestFull(ctx, repo) require.NoError(t, err) assert.Equal(t, expected, full) @@ -68,11 +62,10 @@ func TestPointerLocator(t *testing.T) { ctx, cancel := testhelper.Context() defer cancel() - const expectedIncrement = "001" - expected := &Step{ - BundlePath: filepath.Join(repo.RelativePath, backupID, expectedIncrement+".bundle"), - RefPath: filepath.Join(repo.RelativePath, backupID, expectedIncrement+".refs"), - CustomHooksPath: filepath.Join(repo.RelativePath, backupID, expectedIncrement+".custom_hooks.tar"), + expected := &Full{ + BundlePath: filepath.Join(repo.RelativePath, backupID, "full.bundle"), + RefPath: filepath.Join(repo.RelativePath, backupID, "full.refs"), + CustomHooksPath: filepath.Join(repo.RelativePath, backupID, "custom_hooks.tar"), } full := l.BeginFull(ctx, repo, backupID) @@ -80,14 +73,11 @@ func TestPointerLocator(t *testing.T) { require.NoError(t, l.CommitFull(ctx, full)) - backupPointer := testhelper.MustReadFile(t, filepath.Join(backupPath, repo.RelativePath, "LATEST")) - require.Equal(t, backupID, string(backupPointer)) - - incrementPointer := testhelper.MustReadFile(t, filepath.Join(backupPath, repo.RelativePath, backupID, "LATEST")) - require.Equal(t, expectedIncrement, string(incrementPointer)) + pointer := testhelper.MustReadFile(t, filepath.Join(backupPath, repo.RelativePath, "LATEST")) + require.Equal(t, backupID, string(pointer)) }) - t.Run("FindLatest", func(t *testing.T) { + t.Run("FindLatestFull", func(t *testing.T) { t.Run("no fallback", func(t *testing.T) { backupPath := testhelper.TempDir(t) var l Locator = PointerLocator{ @@ -97,33 +87,18 @@ func TestPointerLocator(t *testing.T) { ctx, cancel := testhelper.Context() defer cancel() - _, err := l.FindLatest(ctx, repo) + _, err := l.FindLatestFull(ctx, repo) require.ErrorIs(t, err, ErrDoesntExist) - require.NoError(t, os.MkdirAll(filepath.Join(backupPath, repo.RelativePath, backupID), 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(backupPath, repo.RelativePath), 0o755)) require.NoError(t, os.WriteFile(filepath.Join(backupPath, repo.RelativePath, "LATEST"), []byte(backupID), 0o644)) - require.NoError(t, os.WriteFile(filepath.Join(backupPath, repo.RelativePath, backupID, "LATEST"), []byte("003"), 0o644)) - expected := &Backup{ - Steps: []Step{ - { - BundlePath: filepath.Join(repo.RelativePath, backupID, "001.bundle"), - RefPath: filepath.Join(repo.RelativePath, backupID, "001.refs"), - CustomHooksPath: filepath.Join(repo.RelativePath, backupID, "001.custom_hooks.tar"), - }, - { - BundlePath: filepath.Join(repo.RelativePath, backupID, "002.bundle"), - RefPath: filepath.Join(repo.RelativePath, backupID, "002.refs"), - CustomHooksPath: filepath.Join(repo.RelativePath, backupID, "002.custom_hooks.tar"), - }, - { - BundlePath: filepath.Join(repo.RelativePath, backupID, "003.bundle"), - RefPath: filepath.Join(repo.RelativePath, backupID, "003.refs"), - CustomHooksPath: filepath.Join(repo.RelativePath, backupID, "003.custom_hooks.tar"), - }, - }, + expected := &Full{ + BundlePath: filepath.Join(repo.RelativePath, backupID, "full.bundle"), + RefPath: filepath.Join(repo.RelativePath, backupID, "full.refs"), + CustomHooksPath: filepath.Join(repo.RelativePath, backupID, "custom_hooks.tar"), } - full, err := l.FindLatest(ctx, repo) + full, err := l.FindLatestFull(ctx, repo) require.NoError(t, err) require.Equal(t, expected, full) }) @@ -138,75 +113,27 @@ func TestPointerLocator(t *testing.T) { ctx, cancel := testhelper.Context() defer cancel() - expectedFallback := &Backup{ - Steps: []Step{ - { - SkippableOnNotFound: true, - BundlePath: repo.RelativePath + ".bundle", - RefPath: repo.RelativePath + ".refs", - CustomHooksPath: filepath.Join(repo.RelativePath, "custom_hooks.tar"), - }, - }, + expectedFallback := &Full{ + BundlePath: repo.RelativePath + ".bundle", + RefPath: repo.RelativePath + ".refs", + CustomHooksPath: filepath.Join(repo.RelativePath, "custom_hooks.tar"), } - fallbackFull, err := l.FindLatest(ctx, repo) + fallbackFull, err := l.FindLatestFull(ctx, repo) require.NoError(t, err) require.Equal(t, expectedFallback, fallbackFull) - require.NoError(t, os.MkdirAll(filepath.Join(backupPath, repo.RelativePath, backupID), 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(backupPath, repo.RelativePath), 0o755)) require.NoError(t, os.WriteFile(filepath.Join(backupPath, repo.RelativePath, "LATEST"), []byte(backupID), 0o644)) - require.NoError(t, os.WriteFile(filepath.Join(backupPath, repo.RelativePath, backupID, "LATEST"), []byte("001"), 0o644)) - expected := &Backup{ - Steps: []Step{ - { - BundlePath: filepath.Join(repo.RelativePath, backupID, "001.bundle"), - RefPath: filepath.Join(repo.RelativePath, backupID, "001.refs"), - CustomHooksPath: filepath.Join(repo.RelativePath, backupID, "001.custom_hooks.tar"), - }, - }, + expected := &Full{ + BundlePath: filepath.Join(repo.RelativePath, backupID, "full.bundle"), + RefPath: filepath.Join(repo.RelativePath, backupID, "full.refs"), + CustomHooksPath: filepath.Join(repo.RelativePath, backupID, "custom_hooks.tar"), } - full, err := l.FindLatest(ctx, repo) + full, err := l.FindLatestFull(ctx, repo) require.NoError(t, err) require.Equal(t, expected, full) }) - - t.Run("invalid backup LATEST", func(t *testing.T) { - backupPath := testhelper.TempDir(t) - var l Locator = PointerLocator{ - Sink: NewFilesystemSink(backupPath), - } - - ctx, cancel := testhelper.Context() - defer cancel() - - _, err := l.FindLatest(ctx, repo) - require.ErrorIs(t, err, ErrDoesntExist) - - require.NoError(t, os.MkdirAll(filepath.Join(backupPath, repo.RelativePath), 0o755)) - require.NoError(t, os.WriteFile(filepath.Join(backupPath, repo.RelativePath, "LATEST"), []byte("invalid"), 0o644)) - _, err = l.FindLatest(ctx, repo) - require.EqualError(t, err, "pointer locator: latest incremental: find latest ID: filesystem sink: get reader for \"TestPointerLocator/invalid/LATEST\": doesn't exist") - }) - - t.Run("invalid incremental LATEST", func(t *testing.T) { - backupPath := testhelper.TempDir(t) - var l Locator = PointerLocator{ - Sink: NewFilesystemSink(backupPath), - } - - ctx, cancel := testhelper.Context() - defer cancel() - - _, err := l.FindLatest(ctx, repo) - require.ErrorIs(t, err, ErrDoesntExist) - - require.NoError(t, os.MkdirAll(filepath.Join(backupPath, repo.RelativePath, backupID), 0o755)) - require.NoError(t, os.WriteFile(filepath.Join(backupPath, repo.RelativePath, "LATEST"), []byte(backupID), 0o644)) - require.NoError(t, os.WriteFile(filepath.Join(backupPath, repo.RelativePath, backupID, "LATEST"), []byte("invalid"), 0o644)) - - _, err = l.FindLatest(ctx, repo) - require.EqualError(t, err, "pointer locator: latest incremental: strconv.Atoi: parsing \"invalid\": invalid syntax") - }) }) } diff --git a/internal/blackbox/blackbox.go b/internal/blackbox/blackbox.go index 82f2e707c..5a77ff69d 100644 --- a/internal/blackbox/blackbox.go +++ b/internal/blackbox/blackbox.go @@ -8,9 +8,9 @@ import ( "time" "github.com/prometheus/client_golang/prometheus" + log "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/git/stats" - "gitlab.com/gitlab-org/gitaly/v14/internal/log" "gitlab.com/gitlab-org/gitaly/v14/internal/version" "gitlab.com/gitlab-org/labkit/monitoring" ) @@ -140,7 +140,7 @@ func (b Blackbox) Run() error { func (b Blackbox) runProbes() { for ; ; time.Sleep(b.cfg.sleepDuration) { for _, probe := range b.cfg.Probes { - entry := log.Default().WithFields(map[string]interface{}{ + entry := log.WithFields(map[string]interface{}{ "probe": probe.Name, "type": probe.Type, }) diff --git a/internal/command/command.go b/internal/command/command.go index 858c72642..d1db84cd1 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -324,7 +324,6 @@ func (c *Command) logProcessComplete() { "command.exitCode": exitCode, "command.system_time_ms": systemTime.Seconds() * 1000, "command.user_time_ms": userTime.Seconds() * 1000, - "command.cpu_time_ms": (systemTime.Seconds() + userTime.Seconds()) * 1000, "command.real_time_ms": realTime.Seconds() * 1000, }) @@ -346,7 +345,6 @@ func (c *Command) logProcessComplete() { stats.RecordSum("command.count", 1) stats.RecordSum("command.system_time_ms", int(systemTime.Seconds()*1000)) stats.RecordSum("command.user_time_ms", int(userTime.Seconds()*1000)) - stats.RecordSum("command.cpu_time_ms", int((systemTime.Seconds()+userTime.Seconds())*1000)) stats.RecordSum("command.real_time_ms", int(realTime.Seconds()*1000)) if ok { diff --git a/internal/git/catfile/batch_cache.go b/internal/git/catfile/batch_cache.go index 6444e8fbc..b8e1f966a 100644 --- a/internal/git/catfile/batch_cache.go +++ b/internal/git/catfile/batch_cache.go @@ -60,7 +60,6 @@ type entry struct { key value *batch expiry time.Time - cancel func() } // BatchCache entries always get added to the back of the list. If the @@ -186,7 +185,6 @@ func (bc *BatchCache) BatchProcess(ctx context.Context, repo git.RepositoryExecu panic("empty ctx.Done() in catfile.Batch.New()") } - var cancel func() cacheKey, isCacheable := newCacheKey(metadata.GetValue(ctx, SessionIDField), repo) if isCacheable { // We only try to look up cached batch processes in case it is cacheable, which @@ -195,9 +193,9 @@ func (bc *BatchCache) BatchProcess(ctx context.Context, repo git.RepositoryExecu // disallow trivial denial of service attacks against other users in case it is // possible to poison the cache with broken git-cat-file(1) processes. - if entry, ok := bc.checkout(cacheKey); ok { - go bc.returnWhenDone(requestDone, cacheKey, entry.value, entry.cancel) - return entry.value, nil + if c, ok := bc.checkout(cacheKey); ok { + go bc.returnWhenDone(requestDone, cacheKey, c) + return c, nil } // We have not found any cached process, so we need to create a new one. In this @@ -205,6 +203,7 @@ func (bc *BatchCache) BatchProcess(ctx context.Context, repo git.RepositoryExecu // not get killed when the current context is done. Note that while we explicitly // `Close()` processes in case this function fails, we must have a cancellable // context or otherwise our `command` package will panic. + var cancel func() ctx, cancel = context.WithCancel(context.Background()) defer func() { if returnedErr != nil { @@ -240,13 +239,13 @@ func (bc *BatchCache) BatchProcess(ctx context.Context, repo git.RepositoryExecu if isCacheable { // If the process is cacheable, then we want to put the process into the cache when // the current outer context is done. - go bc.returnWhenDone(requestDone, cacheKey, c, cancel) + go bc.returnWhenDone(requestDone, cacheKey, c) } return c, nil } -func (bc *BatchCache) returnWhenDone(done <-chan struct{}, cacheKey key, c *batch, cancel func()) { +func (bc *BatchCache) returnWhenDone(done <-chan struct{}, cacheKey key, c *batch) { <-done if bc.cachedProcessDone != nil { @@ -256,23 +255,21 @@ func (bc *BatchCache) returnWhenDone(done <-chan struct{}, cacheKey key, c *batc } if c == nil || c.isClosed() { - cancel() return } if c.hasUnreadData() { - cancel() bc.catfileCacheCounter.WithLabelValues("dirty").Inc() c.Close() return } - bc.add(cacheKey, c, cancel) + bc.add(cacheKey, c) } // add adds a key, value pair to bc. If there are too many keys in bc // already add will evict old keys until the length is OK again. -func (bc *BatchCache) add(k key, b *batch, cancel func()) { +func (bc *BatchCache) add(k key, b *batch) { bc.entriesMutex.Lock() defer bc.entriesMutex.Unlock() @@ -281,12 +278,7 @@ func (bc *BatchCache) add(k key, b *batch, cancel func()) { bc.delete(i, true) } - ent := &entry{ - key: k, - value: b, - expiry: time.Now().Add(bc.ttl), - cancel: cancel, - } + ent := &entry{key: k, value: b, expiry: time.Now().Add(bc.ttl)} bc.entries = append(bc.entries, ent) for bc.len() > bc.maxLen { @@ -301,7 +293,7 @@ func (bc *BatchCache) evictHead() { bc.delete(0, true) } func (bc *BatchCache) len() int { return len(bc.entries) } // checkout removes a value from bc. After use the caller can re-add the value with bc.Add. -func (bc *BatchCache) checkout(k key) (*entry, bool) { +func (bc *BatchCache) checkout(k key) (*batch, bool) { bc.entriesMutex.Lock() defer bc.entriesMutex.Unlock() @@ -313,9 +305,9 @@ func (bc *BatchCache) checkout(k key) (*entry, bool) { bc.catfileCacheCounter.WithLabelValues("hit").Inc() - entry := bc.entries[i] + ent := bc.entries[i] bc.delete(i, false) - return entry, true + return ent.value, true } // enforceTTL evicts all entries older than now, assuming the entry @@ -354,7 +346,6 @@ func (bc *BatchCache) delete(i int, wantClose bool) { if wantClose { ent.value.Close() - ent.cancel() } bc.entries = append(bc.entries[:i], bc.entries[i+1:]...) diff --git a/internal/git/catfile/batch_cache_test.go b/internal/git/catfile/batch_cache_test.go index 273f455c7..9816c0d7d 100644 --- a/internal/git/catfile/batch_cache_test.go +++ b/internal/git/catfile/batch_cache_test.go @@ -21,30 +21,26 @@ import ( func TestCache_add(t *testing.T) { const maxLen = 3 bc := newCache(time.Hour, maxLen, defaultEvictionInterval) - defer bc.Stop() cfg, repo, _ := testcfg.BuildWithRepo(t) key0 := mustCreateKey(t, "0", repo) - value0, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key0, value0, cancel) + value0 := mustCreateBatch(t, cfg, repo) + bc.add(key0, value0) requireCacheValid(t, bc) key1 := mustCreateKey(t, "1", repo) - value1, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key1, value1, cancel) + bc.add(key1, mustCreateBatch(t, cfg, repo)) requireCacheValid(t, bc) key2 := mustCreateKey(t, "2", repo) - value2, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key2, value2, cancel) + bc.add(key2, mustCreateBatch(t, cfg, repo)) requireCacheValid(t, bc) // Because maxLen is 3, and key0 is oldest, we expect that adding key3 // will kick out key0. key3 := mustCreateKey(t, "3", repo) - value3, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key3, value3, cancel) + bc.add(key3, mustCreateBatch(t, cfg, repo)) requireCacheValid(t, bc) require.Equal(t, maxLen, bc.len(), "length should be maxLen") @@ -54,24 +50,23 @@ func TestCache_add(t *testing.T) { func TestCache_addTwice(t *testing.T) { bc := newCache(time.Hour, 10, defaultEvictionInterval) - defer bc.Stop() cfg, repo, _ := testcfg.BuildWithRepo(t) key0 := mustCreateKey(t, "0", repo) - value0, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key0, value0, cancel) + value0 := mustCreateBatch(t, cfg, repo) + bc.add(key0, value0) requireCacheValid(t, bc) key1 := mustCreateKey(t, "1", repo) - value1, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key1, value1, cancel) + value1 := mustCreateBatch(t, cfg, repo) + bc.add(key1, value1) requireCacheValid(t, bc) require.Equal(t, key0, bc.head().key, "key0 should be oldest key") - value2, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key0, value2, cancel) + value2 := mustCreateBatch(t, cfg, repo) + bc.add(key0, value2) requireCacheValid(t, bc) require.Equal(t, key1, bc.head().key, "key1 should be oldest key") @@ -82,62 +77,58 @@ func TestCache_addTwice(t *testing.T) { func TestCache_checkout(t *testing.T) { bc := newCache(time.Hour, 10, defaultEvictionInterval) - defer bc.Stop() cfg, repo, _ := testcfg.BuildWithRepo(t) key0 := mustCreateKey(t, "0", repo) - value0, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key0, value0, cancel) + value0 := mustCreateBatch(t, cfg, repo) + bc.add(key0, value0) - entry, ok := bc.checkout(key{sessionID: "foo"}) + v, ok := bc.checkout(key{sessionID: "foo"}) requireCacheValid(t, bc) - require.Nil(t, entry, "expect nil value when key not found") + require.Nil(t, v, "expect nil value when key not found") require.False(t, ok, "ok flag") - entry, ok = bc.checkout(key0) + v, ok = bc.checkout(key0) requireCacheValid(t, bc) - require.Equal(t, value0, entry.value) + require.Equal(t, value0, v) require.True(t, ok, "ok flag") - require.False(t, entry.value.isClosed(), "value should not be closed after checkout") + require.False(t, v.isClosed(), "value should not be closed after checkout") - entry, ok = bc.checkout(key0) + v, ok = bc.checkout(key0) require.False(t, ok, "ok flag after second checkout") - require.Nil(t, entry, "value from second checkout") + require.Nil(t, v, "value from second checkout") } func TestCache_enforceTTL(t *testing.T) { ttl := time.Hour bc := newCache(ttl, 10, defaultEvictionInterval) - defer bc.Stop() cfg, repo, _ := testcfg.BuildWithRepo(t) sleep := func() { time.Sleep(2 * time.Millisecond) } key0 := mustCreateKey(t, "0", repo) - value0, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key0, value0, cancel) + value0 := mustCreateBatch(t, cfg, repo) + bc.add(key0, value0) sleep() key1 := mustCreateKey(t, "1", repo) - value1, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key1, value1, cancel) + value1 := mustCreateBatch(t, cfg, repo) + bc.add(key1, value1) sleep() cutoff := time.Now().Add(ttl) sleep() key2 := mustCreateKey(t, "2", repo) - value2, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key2, value2, cancel) + bc.add(key2, mustCreateBatch(t, cfg, repo)) sleep() key3 := mustCreateKey(t, "3", repo) - value3, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key3, value3, cancel) + bc.add(key3, mustCreateBatch(t, cfg, repo)) sleep() requireCacheValid(t, bc) @@ -163,13 +154,12 @@ func TestCache_autoExpiry(t *testing.T) { ttl := 5 * time.Millisecond refresh := 1 * time.Millisecond bc := newCache(ttl, 10, refresh) - defer bc.Stop() cfg, repo, _ := testcfg.BuildWithRepo(t) key0 := mustCreateKey(t, "0", repo) - value0, cancel := mustCreateBatch(t, cfg, repo) - bc.add(key0, value0, cancel) + value0 := mustCreateBatch(t, cfg, repo) + bc.add(key0, value0) requireCacheValid(t, bc) require.Contains(t, keys(t, bc), key0, "key should still be in map") @@ -193,7 +183,7 @@ func TestCache_BatchProcess(t *testing.T) { repoExecutor := newRepoExecutor(t, cfg, repo) cache := newCache(time.Hour, 10, time.Hour) - defer cache.Stop() + defer cache.Evict() cache.cachedProcessDone = sync.NewCond(&sync.Mutex{}) t.Run("uncancellable", func(t *testing.T) { @@ -354,7 +344,7 @@ func requireCacheValid(t *testing.T, bc *BatchCache) { } } -func mustCreateBatch(t *testing.T, cfg config.Cfg, repo repository.GitRepo) (*batch, func()) { +func mustCreateBatch(t *testing.T, cfg config.Cfg, repo repository.GitRepo) *batch { t.Helper() ctx, cancel := testhelper.Context() @@ -363,7 +353,7 @@ func mustCreateBatch(t *testing.T, cfg config.Cfg, repo repository.GitRepo) (*ba batch, err := newBatch(ctx, newRepoExecutor(t, cfg, repo), nil) require.NoError(t, err) - return batch, cancel + return batch } func mustCreateKey(t *testing.T, sessionID string, repo repository.GitRepo) key { diff --git a/internal/git/catfile/batch_test.go b/internal/git/catfile/batch_test.go index 80af98350..95e62cb96 100644 --- a/internal/git/catfile/batch_test.go +++ b/internal/git/catfile/batch_test.go @@ -29,8 +29,6 @@ func setupBatch(t *testing.T, ctx context.Context) (config.Cfg, Batch, *gitalypb repoExecutor := newRepoExecutor(t, cfg, repo) cache := newCache(1*time.Hour, 1000, defaultEvictionInterval) - t.Cleanup(cache.Stop) - batch, err := cache.BatchProcess(ctx, repoExecutor) require.NoError(t, err) @@ -344,7 +342,6 @@ func TestSpawnFailure(t *testing.T) { } cache := newCache(1*time.Hour, 1000, defaultEvictionInterval) - defer cache.Stop() require.True( t, diff --git a/internal/git/catfile/testhelper_test.go b/internal/git/catfile/testhelper_test.go index 4479adb85..d78dc8092 100644 --- a/internal/git/catfile/testhelper_test.go +++ b/internal/git/catfile/testhelper_test.go @@ -17,11 +17,7 @@ func TestMain(m *testing.M) { } func testMain(m *testing.M) int { - defer func() { - testhelper.MustHaveNoChildProcess() - testhelper.MustHaveNoGoroutines() - }() - + defer testhelper.MustHaveNoChildProcess() cleanup := testhelper.Configure() defer cleanup() return m.Run() diff --git a/internal/git/gittest/repo.go b/internal/git/gittest/repo.go index 771549c6c..6821a38fb 100644 --- a/internal/git/gittest/repo.go +++ b/internal/git/gittest/repo.go @@ -155,15 +155,10 @@ func CloneRepo(t testing.TB, cfg config.Cfg, storage config.Storage, opts ...Clo return repo, absolutePath } -// BundleTestRepo creates a bundle of a local test repo. E.g. -// `gitlab-test.git`. `patterns` define the bundle contents as per -// `git-rev-list-args`. If there are no patterns then `--all` is assumed. -func BundleTestRepo(t testing.TB, cfg config.Cfg, sourceRepo, bundlePath string, patterns ...string) { - if len(patterns) == 0 { - patterns = []string{"--all"} - } +// BundleTestRepo creates a bundle of a local test repo. E.g. `gitlab-test.git` +func BundleTestRepo(t testing.TB, cfg config.Cfg, sourceRepo, bundlePath string) { repoPath := testRepositoryPath(t, sourceRepo) - Exec(t, cfg, append([]string{"-C", repoPath, "bundle", "create", bundlePath}, patterns...)...) + Exec(t, cfg, "-C", repoPath, "bundle", "create", bundlePath, "--all") } // testRepositoryPath returns the absolute path of local 'gitlab-org/gitlab-test.git' clone. diff --git a/internal/git/housekeeping/housekeeping_test.go b/internal/git/housekeeping/housekeeping_test.go index e62c5de6f..09b46599d 100644 --- a/internal/git/housekeeping/housekeeping_test.go +++ b/internal/git/housekeeping/housekeeping_test.go @@ -666,7 +666,7 @@ func TestPerformRepoDoesNotExist(t *testing.T) { } func TestPerform_UnsetConfiguration(t *testing.T) { - cfg, repoProto, repoPath := testcfg.BuildWithRepo(t) + cfg, repoProto, _ := testcfg.BuildWithRepo(t) repo := localrepo.NewTestRepo(t, cfg, repoProto) ctx, cancel := testhelper.Context() @@ -679,7 +679,7 @@ func TestPerform_UnsetConfiguration(t *testing.T) { "http.something.else": "untouched", "totally.unrelated": "untouched", } { - gittest.Exec(t, cfg, "-C", repoPath, "config", key, value) + require.NoError(t, repo.Config().Set(ctx, key, value)) } opts, err := repo.Config().GetRegexp(ctx, ".*", git.ConfigGetRegexpOpts{}) @@ -711,7 +711,7 @@ func testPerformUnsetConfigurationTransactional(t *testing.T, ctx context.Contex repoProto, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0]) repo := localrepo.NewTestRepo(t, cfg, repoProto) - gittest.Exec(t, cfg, "-C", repoPath, "config", "http.some.extraHeader", "value") + require.NoError(t, repo.Config().Set(ctx, "http.some.extraHeader", "value")) votes := 0 txManager := &transaction.MockManager{ diff --git a/internal/git/localrepo/config.go b/internal/git/localrepo/config.go index 49faa6cda..97f4de2e4 100644 --- a/internal/git/localrepo/config.go +++ b/internal/git/localrepo/config.go @@ -21,6 +21,37 @@ type Config struct { repo *Repo } +// Set will set a configuration value. Any preexisting values will be overwritten with the new +// value. +func (cfg Config) Set(ctx context.Context, name, value string) error { + if err := validateNotBlank(name, "name"); err != nil { + return err + } + + if err := cfg.repo.ExecAndWait(ctx, git.SubCmd{ + Name: "config", + Flags: []git.Option{ + git.Flag{Name: "--replace-all"}, + }, + Args: []string{name, value}, + }); err != nil { + // Please refer to https://git-scm.com/docs/git-config#_description + // on return codes. + switch { + case isExitWithCode(err, 1): + // section or key is invalid + return fmt.Errorf("%w: bad section or name", git.ErrInvalidArg) + case isExitWithCode(err, 2): + // no section or name was provided + return fmt.Errorf("%w: missing section or name", git.ErrInvalidArg) + } + + return err + } + + return nil +} + // GetRegexp gets all config entries which whose keys match the given regexp. func (cfg Config) GetRegexp(ctx context.Context, nameRegexp string, opts git.ConfigGetRegexpOpts) ([]git.ConfigPair, error) { if err := validateNotBlank(nameRegexp, "nameRegexp"); err != nil { diff --git a/internal/git/localrepo/config_test.go b/internal/git/localrepo/config_test.go index 15c440524..f09e525a5 100644 --- a/internal/git/localrepo/config_test.go +++ b/internal/git/localrepo/config_test.go @@ -36,6 +36,66 @@ func setupRepoConfig(t *testing.T) (Config, string) { return repo.Config(), repoPath } +func TestConfig_Set(t *testing.T) { + ctx, cancel := testhelper.Context() + defer cancel() + + repoConfig, repoPath := setupRepoConfig(t) + + t.Run("setting a new value", func(t *testing.T) { + require.NoError(t, repoConfig.Set(ctx, "key.one", "1")) + + actual := text.ChompBytes(gittest.Exec(t, repoConfig.repo.cfg, "-C", repoPath, "config", "key.one")) + require.Equal(t, "1", actual) + }) + + t.Run("overwriting an old value", func(t *testing.T) { + require.NoError(t, repoConfig.Set(ctx, "key.two", "2")) + require.NoError(t, repoConfig.Set(ctx, "key.two", "3")) + + actual := text.ChompBytes(gittest.Exec(t, repoConfig.repo.cfg, "-C", repoPath, "config", "--get-all", "key.two")) + require.Equal(t, "3", actual) + }) + + t.Run("invalid argument", func(t *testing.T) { + for _, tc := range []struct { + desc string + name string + expErr error + expMsg string + }{ + { + desc: "empty name", + name: "", + expErr: git.ErrInvalidArg, + expMsg: `"name" is blank or empty`, + }, + { + desc: "invalid name", + name: "`.\n", + expErr: git.ErrInvalidArg, + expMsg: "bad section or name", + }, + { + desc: "no section or name", + name: "missing", + expErr: git.ErrInvalidArg, + expMsg: "missing section or name", + }, + } { + t.Run(tc.desc, func(t *testing.T) { + ctx, cancel := testhelper.Context() + defer cancel() + + err := repoConfig.Set(ctx, tc.name, "some") + require.Error(t, err) + require.True(t, errors.Is(err, tc.expErr), err.Error()) + require.Contains(t, err.Error(), tc.expMsg) + }) + } + }) +} + func TestBuildConfigGetRegexpOptsFlags(t *testing.T) { for _, tc := range []struct { desc string diff --git a/internal/git/localrepo/remote.go b/internal/git/localrepo/remote.go index a490473a9..949bcd26f 100644 --- a/internal/git/localrepo/remote.go +++ b/internal/git/localrepo/remote.go @@ -217,8 +217,6 @@ type FetchOpts struct { Tags FetchOptsTags // Stderr if set it would be used to redirect stderr stream into it. Stderr io.Writer - // DisableTransactions will disable the reference-transaction hook and atomic transactions. - DisableTransactions bool } // ErrFetchFailed indicates that the fetch has failed. @@ -246,11 +244,7 @@ func (repo *Repo) FetchRemote(ctx context.Context, remoteName string, opts Fetch commandOptions := []git.CmdOpt{ git.WithEnv(opts.Env...), git.WithStderr(opts.Stderr), - } - if opts.DisableTransactions { - commandOptions = append(commandOptions, git.WithDisabledHooks()) - } else { - commandOptions = append(commandOptions, git.WithRefTxHook(ctx, repo, repo.cfg)) + git.WithDisabledHooks(), } commandOptions = append(commandOptions, opts.CommandOptions...) @@ -301,6 +295,7 @@ func (repo *Repo) FetchInternal( commandOptions := []git.CmdOpt{ git.WithEnv(append(env, opts.Env...)...), git.WithStderr(opts.Stderr), + git.WithRefTxHook(ctx, repo, repo.cfg), // We've observed performance issues when fetching into big repositories part of an // object pool. The root cause of this seems to be the connectivity check, which by // default will also include references of any alternates. Given that object pools @@ -310,17 +305,12 @@ func (repo *Repo) FetchInternal( // matter in the connectivity check either. git.WithConfig(git.ConfigPair{Key: "core.alternateRefsCommand", Value: "exit 0 #"}), } - if opts.DisableTransactions { - commandOptions = append(commandOptions, git.WithDisabledHooks()) - } else { - commandOptions = append(commandOptions, git.WithRefTxHook(ctx, repo, repo.cfg)) - } commandOptions = append(commandOptions, opts.CommandOptions...) if err := repo.ExecAndWait(ctx, git.SubCmd{ Name: "fetch", - Flags: opts.buildFlags(), + Flags: append(opts.buildFlags(), git.Flag{Name: "--atomic"}), Args: append([]string{gitalyssh.GitalyInternalURL}, refspecs...), }, commandOptions..., @@ -350,10 +340,6 @@ func (opts FetchOpts) buildFlags() []git.Option { flags = append(flags, git.Flag{Name: opts.Tags.String()}) } - if !opts.DisableTransactions { - flags = append(flags, git.Flag{Name: "--atomic"}) - } - return flags } diff --git a/internal/git/localrepo/remote_extra_test.go b/internal/git/localrepo/remote_extra_test.go index fe2027d24..f80be863b 100644 --- a/internal/git/localrepo/remote_extra_test.go +++ b/internal/git/localrepo/remote_extra_test.go @@ -60,7 +60,7 @@ func TestRepo_FetchInternal(t *testing.T) { repoProto, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0]) repo := localrepo.NewTestRepo(t, cfg, repoProto) - gittest.Exec(t, cfg, "-C", repoPath, "config", "fetch.writeCommitGraph", "true") + require.NoError(t, repo.Config().Set(ctx, "fetch.writeCommitGraph", "true")) require.NoError(t, repo.FetchInternal( ctx, remoteRepoProto, []string{"refs/heads/master:refs/heads/master"}, @@ -147,22 +147,7 @@ func TestRepo_FetchInternal(t *testing.T) { localrepo.FetchOpts{Stderr: &stderr, Env: []string{"GIT_TRACE=1"}}, ) require.NoError(t, err) - require.Contains(t, stderr.String(), "trace: built-in: git fetch --quiet --atomic --end-of-options") - }) - - t.Run("with disabled transactions", func(t *testing.T) { - ctx := testhelper.MergeIncomingMetadata(ctx, testhelper.GitalyServersMetadataFromCfg(t, cfg)) - - repoProto, _ := gittest.InitRepo(t, cfg, cfg.Storages[0]) - repo := localrepo.NewTestRepo(t, cfg, repoProto) - - var stderr bytes.Buffer - err := repo.FetchInternal( - ctx, remoteRepoProto, []string{"refs/heads/master"}, - localrepo.FetchOpts{Stderr: &stderr, Env: []string{"GIT_TRACE=1"}, DisableTransactions: true}, - ) - require.NoError(t, err) - require.Contains(t, stderr.String(), "trace: built-in: git fetch --quiet --end-of-options") + require.Contains(t, stderr.String(), "trace: built-in: git fetch") }) t.Run("invalid remote repo", func(t *testing.T) { diff --git a/internal/git/localrepo/remote_test.go b/internal/git/localrepo/remote_test.go index 6b165f0c9..4f1a8276a 100644 --- a/internal/git/localrepo/remote_test.go +++ b/internal/git/localrepo/remote_test.go @@ -361,22 +361,6 @@ func TestRepo_FetchRemote(t *testing.T) { var stderr bytes.Buffer require.NoError(t, repo.FetchRemote(ctx, "source", FetchOpts{Stderr: &stderr, Env: []string{"GIT_TRACE=1"}})) - require.Contains(t, stderr.String(), "trace: built-in: git fetch --quiet --atomic --end-of-options source") - }) - - t.Run("with disabled transactions", func(t *testing.T) { - _, sourceRepoPath := gittest.CloneRepo(t, cfg, cfg.Storages[0]) - testRepo, testRepoPath := gittest.CloneRepo(t, cfg, cfg.Storages[0]) - - repo := New(remoteCmd.repo.gitCmdFactory, remoteCmd.repo.catfileCache, testRepo, cfg) - gittest.Exec(t, cfg, "-C", testRepoPath, "remote", "add", "source", sourceRepoPath) - - var stderr bytes.Buffer - require.NoError(t, repo.FetchRemote(ctx, "source", FetchOpts{ - Stderr: &stderr, - Env: []string{"GIT_TRACE=1"}, - DisableTransactions: true, - })) require.Contains(t, stderr.String(), "trace: built-in: git fetch --quiet --end-of-options source") }) diff --git a/internal/git/pktline/pktline.go b/internal/git/pktline/pktline.go index 1841a94de..6a37f9651 100644 --- a/internal/git/pktline/pktline.go +++ b/internal/git/pktline/pktline.go @@ -15,19 +15,16 @@ import ( const ( // MaxSidebandData is the maximum number of bytes that fits into one Git // pktline side-band-64k packet. - MaxSidebandData = MaxPktSize - 5 + MaxSidebandData = maxPktSize - 5 - // MaxPktSize is the maximum size of content of a Git pktline side-band-64k - // packet, excluding size of length and band number - // https://gitlab.com/gitlab-org/git/-/blob/v2.30.0/pkt-line.h#L216 - MaxPktSize = 65520 + maxPktSize = 65520 // https://gitlab.com/gitlab-org/git/-/blob/v2.30.0/pkt-line.h#L216 pktDelim = "0001" ) // NewScanner returns a bufio.Scanner that splits on Git pktline boundaries func NewScanner(r io.Reader) *bufio.Scanner { scanner := bufio.NewScanner(r) - scanner.Buffer(make([]byte, MaxPktSize), MaxPktSize) + scanner.Buffer(make([]byte, maxPktSize), maxPktSize) scanner.Split(pktLineSplitter) return scanner } @@ -47,7 +44,7 @@ func IsFlush(pkt []byte) bool { // WriteString writes a string with pkt-line framing func WriteString(w io.Writer, str string) (int, error) { pktLen := len(str) + 4 - if pktLen > MaxPktSize { + if pktLen > maxPktSize { return 0, fmt.Errorf("string too large: %d bytes", len(str)) } @@ -134,7 +131,7 @@ func (sw *SidebandWriter) writeBand(band byte, data []byte) (int, error) { for len(data) > 0 { chunkSize := len(data) const headerSize = 5 - if max := MaxPktSize - headerSize; chunkSize > max { + if max := maxPktSize - headerSize; chunkSize > max { chunkSize = max } diff --git a/internal/git/updateref/updateref.go b/internal/git/updateref/updateref.go index b5b672875..dde7b5b76 100644 --- a/internal/git/updateref/updateref.go +++ b/internal/git/updateref/updateref.go @@ -9,6 +9,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/command" "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" ) // Updater wraps a `git update-ref --stdin` process, presenting an interface @@ -71,9 +72,14 @@ func New(ctx context.Context, conf config.Cfg, repo git.RepositoryExecutor, opts return nil, err } - gitVersion, err := git.CurrentVersionForExecutor(ctx, repo) - if err != nil { - return nil, fmt.Errorf("determining git version: %w", err) + withStatusFlushing := false + if featureflag.UpdaterefVerifyStateChanges.IsEnabled(ctx) { + gitVersion, err := git.CurrentVersionForExecutor(ctx, repo) + if err != nil { + return nil, fmt.Errorf("determining git version: %w", err) + } + + withStatusFlushing = gitVersion.FlushesUpdaterefStatus() } updater := &Updater{ @@ -81,7 +87,7 @@ func New(ctx context.Context, conf config.Cfg, repo git.RepositoryExecutor, opts cmd: cmd, stderr: &stderr, stdout: bufio.NewReader(cmd), - withStatusFlushing: gitVersion.FlushesUpdaterefStatus(), + withStatusFlushing: withStatusFlushing, } // By writing an explicit "start" to the command, we enable @@ -147,10 +153,7 @@ func (u *Updater) Cancel() error { func (u *Updater) setState(state string) error { _, err := fmt.Fprintf(u.cmd, "%s\x00", state) if err != nil { - // We need to explicitly cancel the command here and wait for it to terminate such - // that we can retrieve the command's stderr in a race-free manner. - _ = u.Cancel() - return fmt.Errorf("updating state to %q: %w, stderr: %q", state, err, u.stderr) + return fmt.Errorf("updating state to %q: %w", state, err) } // For each state-changing command, git-update-ref(1) will report successful execution via diff --git a/internal/git/updateref/updateref_test.go b/internal/git/updateref/updateref_test.go index c2cf6c0d6..aea0de5cb 100644 --- a/internal/git/updateref/updateref_test.go +++ b/internal/git/updateref/updateref_test.go @@ -12,6 +12,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/git/hooks" "gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" ) @@ -134,11 +135,12 @@ func TestUpdater_prepareLocksTransaction(t *testing.T) { } func TestUpdater_concurrentLocking(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.UpdaterefVerifyStateChanges, + }).Run(t, testUpdaterConcurrentLocking) +} +func testUpdaterConcurrentLocking(t *testing.T, ctx context.Context) { cfg, protoRepo, _ := testcfg.BuildWithRepo(t) repo := localrepo.NewTestRepo(t, cfg, protoRepo) @@ -156,10 +158,10 @@ func TestUpdater_concurrentLocking(t *testing.T) { // With flushing, we're able to detect concurrent locking at prepare time already instead of // at commit time. - if gitSupportsStatusFlushing(t, ctx, cfg) { + if gitSupportsStatusFlushing(t, ctx, cfg) && featureflag.UpdaterefVerifyStateChanges.IsEnabled(ctx) { err := secondUpdater.Prepare() require.Error(t, err) - require.Contains(t, err.Error(), "fatal: prepare: cannot lock ref 'refs/heads/master'") + require.Contains(t, err.Error(), "state update to \"prepare\" failed: EOF, stderr: \"warning: update refs/heads/master: missing <newvalue>, treating as zero\\nfatal: prepare: cannot lock ref 'refs/heads/master'") require.NoError(t, firstUpdater.Commit()) } else { @@ -168,7 +170,7 @@ func TestUpdater_concurrentLocking(t *testing.T) { err := secondUpdater.Commit() require.Error(t, err) - require.Contains(t, err.Error(), "fatal: prepare: cannot lock ref 'refs/heads/master'") + require.Contains(t, err.Error(), "git update-ref: exit status 128, stderr: \"warning: update refs/heads/master: missing <newvalue>, treating as zero\\nfatal: prepare: cannot lock ref 'refs/heads/master'") } } @@ -274,11 +276,12 @@ func TestUpdater_closingStdinAbortsChanges(t *testing.T) { } func TestUpdater_capturesStderr(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.UpdaterefVerifyStateChanges, + }).Run(t, testUpdaterCapturesStderr) +} +func testUpdaterCapturesStderr(t *testing.T, ctx context.Context) { cfg, _, updater := setupUpdater(t, ctx) ref := "refs/heads/a" @@ -288,7 +291,7 @@ func TestUpdater_capturesStderr(t *testing.T) { require.NoError(t, updater.Update(git.ReferenceName(ref), newValue, oldValue)) var expectedErr string - if gitSupportsStatusFlushing(t, ctx, cfg) { + if gitSupportsStatusFlushing(t, ctx, cfg) && featureflag.UpdaterefVerifyStateChanges.IsEnabled(ctx) { expectedErr = fmt.Sprintf("state update to \"commit\" failed: EOF, stderr: \"fatal: commit: cannot update ref '%s': "+ "trying to write ref '%s' with nonexistent object %s\\n\"", ref, ref, newValue) } else { diff --git a/internal/git2go/merge.go b/internal/git2go/merge.go index 9ce3890ac..067f36e4d 100644 --- a/internal/git2go/merge.go +++ b/internal/git2go/merge.go @@ -8,6 +8,7 @@ import ( "time" "gitlab.com/gitlab-org/gitaly/v14/internal/git/repository" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" ) const ( @@ -68,14 +69,33 @@ func (b Executor) Merge(ctx context.Context, repo repository.GitRepo, m MergeCom return MergeResult{}, fmt.Errorf("merge: %w: %s", ErrInvalidArgument, err.Error()) } - commitID, err := b.runWithGob(ctx, repo, "merge", m) + if featureflag.Git2GoMergeGob.IsEnabled(ctx) { + commitID, err := b.runWithGob(ctx, repo, "merge", m) + if err != nil { + return MergeResult{}, err + } + + return MergeResult{ + CommitID: commitID.String(), + }, nil + } + + serialized, err := serialize(m) + if err != nil { + return MergeResult{}, err + } + + stdout, err := b.run(ctx, repo, nil, "merge", "-request", serialized) if err != nil { return MergeResult{}, err } - return MergeResult{ - CommitID: commitID.String(), - }, nil + var response MergeResult + if err := deserialize(stdout.String(), &response); err != nil { + return MergeResult{}, err + } + + return response, nil } func (m MergeCommand) verify() error { diff --git a/internal/gitaly/service/namespace/namespace_test.go b/internal/gitaly/service/namespace/namespace_test.go index 8adab217a..56873a6c1 100644 --- a/internal/gitaly/service/namespace/namespace_test.go +++ b/internal/gitaly/service/namespace/namespace_test.go @@ -101,8 +101,6 @@ func getStorageDir(t *testing.T, cfg config.Cfg, storageName string) string { } func TestAddNamespace(t *testing.T) { - testhelper.SkipWithPraefect(t, "per_repository election strategy doesn't support storage scoped mutators") - cfg, client := setupNamespaceService(t) existingStorage := cfg.Storages[0] @@ -165,8 +163,6 @@ func TestAddNamespace(t *testing.T) { } func TestRemoveNamespace(t *testing.T) { - testhelper.SkipWithPraefect(t, "per_repository election strategy doesn't support storage scoped mutators") - cfg, client := setupNamespaceService(t) existingStorage := cfg.Storages[0] @@ -221,8 +217,6 @@ func TestRemoveNamespace(t *testing.T) { } func TestRenameNamespace(t *testing.T) { - testhelper.SkipWithPraefect(t, "per_repository election strategy doesn't support storage scoped mutators") - cfg, client := setupNamespaceService(t) existingStorage := cfg.Storages[0] @@ -291,8 +285,6 @@ func TestRenameNamespace(t *testing.T) { } func TestRenameNamespaceWithNonexistentParentDir(t *testing.T) { - testhelper.SkipWithPraefect(t, "per_repository election strategy doesn't support storage scoped mutators") - cfg, client := setupNamespaceService(t) existingStorage := cfg.Storages[0] diff --git a/internal/gitaly/service/operations/merge_test.go b/internal/gitaly/service/operations/merge_test.go index b5b2fe29a..ed7559a12 100644 --- a/internal/gitaly/service/operations/merge_test.go +++ b/internal/gitaly/service/operations/merge_test.go @@ -43,9 +43,12 @@ var ( func TestUserMergeBranch_successful(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchSuccessful) +} +func testUserMergeBranchSuccessful(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -127,9 +130,13 @@ func TestUserMergeBranch_successful(t *testing.T) { func TestUserMergeBranch_quarantine(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.UserMergeBranchAccessError, + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchQuarantine) +} +func testUserMergeBranchQuarantine(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -177,9 +184,12 @@ func TestUserMergeBranch_quarantine(t *testing.T) { func TestUserMergeBranch_stableMergeIDs(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchStableMergeIDs) +} +func testUserMergeBranchStableMergeIDs(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -248,9 +258,12 @@ func TestUserMergeBranch_stableMergeIDs(t *testing.T) { func TestUserMergeBranch_abort(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchAbort) +} +func testUserMergeBranchAbort(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -313,9 +326,13 @@ func TestUserMergeBranch_abort(t *testing.T) { func TestUserMergeBranch_concurrentUpdate(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.UserMergeBranchAccessError, + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchConcurrentUpdate) +} +func testUserMergeBranchConcurrentUpdate(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -363,9 +380,12 @@ func TestUserMergeBranch_concurrentUpdate(t *testing.T) { func TestUserMergeBranch_ambiguousReference(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchAmbiguousReference) +} +func testUserMergeBranchAmbiguousReference(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -428,9 +448,13 @@ func TestUserMergeBranch_ambiguousReference(t *testing.T) { func TestUserMergeBranch_failingHooks(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.UserMergeBranchAccessError, + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchFailingHooks) +} +func testUserMergeBranchFailingHooks(t *testing.T, ctx context.Context) { ctx, cfg, repo, repoPath, client := setupOperationsService(t, ctx) gittest.Exec(t, cfg, "-C", repoPath, "branch", mergeBranchName, mergeBranchHeadBefore) @@ -484,9 +508,12 @@ func TestUserMergeBranch_failingHooks(t *testing.T) { func TestUserMergeBranch_conflict(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeBranchConflict) +} +func testUserMergeBranchConflict(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) const mergeIntoBranch = "mergeIntoBranch" @@ -526,9 +553,12 @@ func TestUserMergeBranch_conflict(t *testing.T) { func TestUserMergeBranch_allowed(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.UserMergeBranchAccessError, + }).Run(t, testUserMergeBranchAllowed) +} +func testUserMergeBranchAllowed(t *testing.T, ctx context.Context) { mergeBranchHeadAfter := "ff0ac4dfa30d6b26fd14aa83a75650355270bf76" for _, tc := range []struct { @@ -856,9 +886,12 @@ func TestUserFFBranch_ambiguousReference(t *testing.T) { func TestUserMergeToRef_successful(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeToRefSuccessful) +} +func testUserMergeToRefSuccessful(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -963,9 +996,12 @@ func TestUserMergeToRef_successful(t *testing.T) { func TestUserMergeToRef_conflicts(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeToRefConflicts) +} +func testUserMergeToRefConflicts(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -1101,9 +1137,12 @@ func buildUserMergeToRefRequest(t testing.TB, cfg config.Cfg, repo *gitalypb.Rep func TestUserMergeToRef_stableMergeID(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeToRefStableMergeID) +} +func testUserMergeToRefStableMergeID(t *testing.T, ctx context.Context) { ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -1154,9 +1193,12 @@ func TestUserMergeToRef_stableMergeID(t *testing.T) { func TestUserMergeToRef_failure(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeToRefFailure) +} +func testUserMergeToRefFailure(t *testing.T, ctx context.Context) { ctx, cfg, repo, repoPath, client := setupOperationsService(t, ctx) gittest.Exec(t, cfg, "-C", repoPath, "branch", mergeBranchName, mergeBranchHeadBefore) @@ -1251,9 +1293,12 @@ func TestUserMergeToRef_failure(t *testing.T) { func TestUserMergeToRef_ignoreHooksRequest(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.Git2GoMergeGob, + }).Run(t, testUserMergeToRefIgnoreHooksRequest) +} +func testUserMergeToRefIgnoreHooksRequest(t *testing.T, ctx context.Context) { ctx, cfg, repo, repoPath, client := setupOperationsService(t, ctx) gittest.Exec(t, cfg, "-C", repoPath, "branch", mergeBranchName, mergeBranchHeadBefore) diff --git a/internal/gitaly/service/repository/apply_gitattributes.go b/internal/gitaly/service/repository/apply_gitattributes.go index 00d3c2bf7..38b517837 100644 --- a/internal/gitaly/service/repository/apply_gitattributes.go +++ b/internal/gitaly/service/repository/apply_gitattributes.go @@ -8,10 +8,12 @@ import ( "os" "path/filepath" + "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/git/catfile" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/transaction" "gitlab.com/gitlab-org/gitaly/v14/internal/helper" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" "gitlab.com/gitlab-org/gitaly/v14/internal/safe" "gitlab.com/gitlab-org/gitaly/v14/internal/transaction/txinfo" "gitlab.com/gitlab-org/gitaly/v14/internal/transaction/voting" @@ -63,23 +65,57 @@ func (s *server) applyGitattributes(ctx context.Context, c catfile.Batch, repoPa return err } - writer, err := safe.NewLockingFileWriter(attributesPath, safe.LockingFileWriterConfig{ - FileWriterConfig: safe.FileWriterConfig{FileMode: attributesFileMode}, - }) + if featureflag.TxFileLocking.IsEnabled(ctx) { + writer, err := safe.NewLockingFileWriter(attributesPath, safe.LockingFileWriterConfig{ + FileWriterConfig: safe.FileWriterConfig{FileMode: attributesFileMode}, + }) + if err != nil { + return fmt.Errorf("creating gitattributes writer: %w", err) + } + defer writer.Close() + + if _, err := io.CopyN(writer, blobObj.Reader, blobInfo.Size); err != nil { + return err + } + + if err := transaction.CommitLockedFile(ctx, s.txManager, writer); err != nil { + return fmt.Errorf("committing gitattributes: %w", err) + } + + return nil + } + + tempFile, err := os.CreateTemp(infoPath, "attributes") if err != nil { - return fmt.Errorf("creating gitattributes writer: %w", err) + return helper.ErrInternalf("creating temporary gitattributes file: %w", err) } - defer writer.Close() + defer func() { + if err := os.Remove(tempFile.Name()); err != nil && !errors.Is(err, os.ErrNotExist) { + ctxlogrus.Extract(ctx).WithError(err).Errorf("failed to remove tmp file %q", tempFile.Name()) + } + }() - if _, err := io.CopyN(writer, blobObj.Reader, blobInfo.Size); err != nil { + // Write attributes to temp file + if _, err := io.CopyN(tempFile, blobObj.Reader, blobInfo.Size); err != nil { return err } - if err := transaction.CommitLockedFile(ctx, s.txManager, writer); err != nil { - return fmt.Errorf("committing gitattributes: %w", err) + if err := tempFile.Close(); err != nil { + return err } - return nil + // Change the permission of tempFile as the permission of file attributesPath + if err := os.Chmod(tempFile.Name(), attributesFileMode); err != nil { + return err + } + + // Vote on the contents of the newly written gitattributes file. + if err := s.vote(ctx, blobInfo.Oid); err != nil { + return fmt.Errorf("could not commit gitattributes: %w", err) + } + + // Rename temp file and return the result + return os.Rename(tempFile.Name(), attributesPath) } func (s *server) vote(ctx context.Context, oid git.ObjectID) error { diff --git a/internal/gitaly/service/repository/apply_gitattributes_test.go b/internal/gitaly/service/repository/apply_gitattributes_test.go index f85b6f456..b83c2fd09 100644 --- a/internal/gitaly/service/repository/apply_gitattributes_test.go +++ b/internal/gitaly/service/repository/apply_gitattributes_test.go @@ -12,8 +12,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" + "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service" "gitlab.com/gitlab-org/gitaly/v14/internal/metadata" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testassert" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" @@ -27,11 +29,13 @@ import ( ) func TestApplyGitattributesSuccess(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.TxFileLocking, + }).Run(t, testApplyGitattributesSuccess) +} +func testApplyGitattributesSuccess(t *testing.T, ctx context.Context) { + t.Parallel() cfg, repo, _, client := setupRepositoryService(t) infoPath := filepath.Join(cfg.Storages[0].Path, repo.GetRelativePath(), "info") @@ -89,11 +93,13 @@ func (s *testTransactionServer) VoteTransaction(ctx context.Context, in *gitalyp } func TestApplyGitattributesWithTransaction(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.TxFileLocking, + }).Run(t, testApplyGitattributesWithTransaction) +} +func testApplyGitattributesWithTransaction(t *testing.T, ctx context.Context) { + t.Parallel() cfg, repo, repoPath := testcfg.BuildWithRepo(t) transactionServer := &testTransactionServer{} @@ -132,8 +138,16 @@ func TestApplyGitattributesWithTransaction(t *testing.T) { desc: "successful vote writes gitattributes", revision: []byte("e63f41fe459e62e1228fcef60d7189127aeba95a"), voteFn: func(t *testing.T, request *gitalypb.VoteTransactionRequest) (*gitalypb.VoteTransactionResponse, error) { - vote := voting.VoteFromData([]byte("/custom-highlighting/*.gitlab-custom gitlab-language=ruby\n")) - expectedHash := vote.Bytes() + var expectedHash []byte + if featureflag.TxFileLocking.IsEnabled(ctx) { + vote := voting.VoteFromData([]byte("/custom-highlighting/*.gitlab-custom gitlab-language=ruby\n")) + expectedHash = vote.Bytes() + } else { + oid, err := git.NewObjectIDFromHex("36814a3da051159a1683479e7a1487120309db8f") + require.NoError(t, err) + expectedHash, err = oid.Bytes() + require.NoError(t, err) + } require.Equal(t, expectedHash, request.ReferenceUpdatesHash) return &gitalypb.VoteTransactionResponse{ @@ -152,7 +166,11 @@ func TestApplyGitattributesWithTransaction(t *testing.T) { }, shouldExist: false, expectedErr: func() error { - return status.Error(codes.Unknown, "committing gitattributes: voting on locked file: preimage vote: transaction was aborted") + if featureflag.TxFileLocking.IsEnabled(ctx) { + return status.Error(codes.Unknown, "committing gitattributes: voting on locked file: preimage vote: transaction was aborted") + } + + return status.Error(codes.Unknown, "could not commit gitattributes: vote failed: transaction was aborted") }(), }, { @@ -162,8 +180,13 @@ func TestApplyGitattributesWithTransaction(t *testing.T) { return nil, errors.New("foobar") }, shouldExist: false, + expectedErr: func() error { - return status.Error(codes.Unknown, "committing gitattributes: voting on locked file: preimage vote: rpc error: code = Unknown desc = foobar") + if featureflag.TxFileLocking.IsEnabled(ctx) { + return status.Error(codes.Unknown, "committing gitattributes: voting on locked file: preimage vote: rpc error: code = Unknown desc = foobar") + } + + return status.Error(codes.Unknown, "could not commit gitattributes: vote failed: rpc error: code = Unknown desc = foobar") }(), }, { @@ -209,11 +232,13 @@ func TestApplyGitattributesWithTransaction(t *testing.T) { } func TestApplyGitattributesFailure(t *testing.T) { - t.Parallel() - - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.TxFileLocking, + }).Run(t, testApplyGitattributesFailure) +} +func testApplyGitattributesFailure(t *testing.T, ctx context.Context) { + t.Parallel() _, repo, _, client := setupRepositoryService(t) tests := []struct { diff --git a/internal/gitaly/service/repository/cleanup.go b/internal/gitaly/service/repository/cleanup.go index 3b44f2563..d3b3dbfbd 100644 --- a/internal/gitaly/service/repository/cleanup.go +++ b/internal/gitaly/service/repository/cleanup.go @@ -4,18 +4,14 @@ package repository import ( "bytes" "context" - "errors" "fmt" "io/ioutil" "os" "path/filepath" - "strings" "time" - "gitlab.com/gitlab-org/gitaly/v14/internal/command" "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo" - "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config" "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -79,15 +75,17 @@ func (s *server) cleanStaleWorktrees(ctx context.Context, repo *localrepo.Repo, } if info.ModTime().Before(threshold) { - err := removeWorktree(ctx, s.cfg, repo, info.Name()) - switch { - case errors.Is(err, errUnknownWorktree): - // if git doesn't recognise the worktree then we can safely remove it - if err := os.RemoveAll(filepath.Join(worktreePath, info.Name())); err != nil { - return fmt.Errorf("worktree remove dir: %w", err) - } - case err != nil: - return err + var stderr bytes.Buffer + if err := repo.ExecAndWait(ctx, git.SubSubCmd{ + Name: "worktree", + Action: "remove", + Flags: []git.Option{git.Flag{Name: "--force"}}, + Args: []string{info.Name()}, + }, + git.WithRefTxHook(ctx, repo, s.cfg), + git.WithStderr(&stderr), + ); err != nil { + return fmt.Errorf("worktree remove: %w, stderr: %q", err, stderr.String()) } } } @@ -95,38 +93,6 @@ func (s *server) cleanStaleWorktrees(ctx context.Context, repo *localrepo.Repo, return nil } -// errUnknownWorktree indicates that git does not recognise the worktree -var errUnknownWorktree = errors.New("unknown worktree") - -func removeWorktree(ctx context.Context, cfg config.Cfg, repo *localrepo.Repo, name string) error { - var stderr bytes.Buffer - err := repo.ExecAndWait(ctx, git.SubSubCmd{ - Name: "worktree", - Action: "remove", - Flags: []git.Option{git.Flag{Name: "--force"}}, - Args: []string{name}, - }, - git.WithRefTxHook(ctx, repo, cfg), - git.WithStderr(&stderr), - ) - if isExitWithCode(err, 128) && strings.HasPrefix(stderr.String(), "fatal: '"+name+"' is not a working tree") { - return errUnknownWorktree - } else if err != nil { - return fmt.Errorf("remove worktree: %w, stderr: %q", err, stderr.String()) - } - - return nil -} - -func isExitWithCode(err error, code int) bool { - actual, ok := command.ExitStatus(err) - if !ok { - return false - } - - return code == actual -} - func (s *server) cleanDisconnectedWorktrees(ctx context.Context, repo *localrepo.Repo) error { return repo.ExecAndWait(ctx, git.SubSubCmd{ Name: "worktree", diff --git a/internal/gitaly/service/repository/cleanup_test.go b/internal/gitaly/service/repository/cleanup_test.go index 3e8b2ce0b..dac386497 100644 --- a/internal/gitaly/service/repository/cleanup_test.go +++ b/internal/gitaly/service/repository/cleanup_test.go @@ -9,12 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/internal/git" - "gitlab.com/gitlab-org/gitaly/v14/internal/git/catfile" "gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest" - "gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" ) @@ -74,36 +70,13 @@ func TestCleanupDeletesStaleWorktrees(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, c) - require.NoDirExists(t, worktreeCheckoutPath) - require.NoDirExists(t, worktreePath) + require.NoFileExists(t, worktreeCheckoutPath) + require.NoFileExists(t, worktreePath) } }) } } -func TestCleanupDeletesOrphanedWorktrees(t *testing.T) { - t.Parallel() - - _, repo, repoPath, client := setupRepositoryService(t) - - worktreeCheckoutPath := filepath.Join(repoPath, worktreePrefix, "test-worktree") - basePath := filepath.Join(repoPath, "worktrees") - worktreePath := filepath.Join(basePath, "test-worktree") - - require.NoError(t, os.MkdirAll(worktreeCheckoutPath, os.ModePerm)) - require.NoError(t, os.Chtimes(worktreeCheckoutPath, oldTreeTime, oldTreeTime)) - - ctx, cancel := testhelper.Context() - defer cancel() - - c, err := client.Cleanup(ctx, &gitalypb.CleanupRequest{Repository: repo}) - assert.NoError(t, err) - assert.NotNil(t, c) - - require.NoDirExists(t, worktreeCheckoutPath) - require.NoDirExists(t, worktreePath) -} - // TODO: replace emulated rebase RPC with actual // https://gitlab.com/gitlab-org/gitaly/issues/1750 func TestCleanupDisconnectedWorktrees(t *testing.T) { @@ -141,72 +114,9 @@ func TestCleanupDisconnectedWorktrees(t *testing.T) { // cleanup should prune the disconnected worktree administrative files _, err = client.Cleanup(ctx, req) require.NoError(t, err) - require.NoDirExists(t, worktreeAdminPath) + require.NoFileExists(t, worktreeAdminPath) // if the worktree administrative files are pruned, then we should be able // to checkout another worktree at the same path gittest.AddWorktree(t, cfg, repoPath, worktreePath) } - -func TestRemoveWorktree(t *testing.T) { - t.Parallel() - - cfg, repoProto, repoPath := testcfg.BuildWithRepo(t) - gitCmdFactory := git.NewExecCommandFactory(cfg) - repo := localrepo.New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg) - - existingWorktreePath := filepath.Join(repoPath, worktreePrefix, "existing") - gittest.AddWorktree(t, cfg, repoPath, existingWorktreePath) - - disconnectedWorktreePath := filepath.Join(repoPath, worktreePrefix, "disconnected") - gittest.AddWorktree(t, cfg, repoPath, disconnectedWorktreePath) - require.NoError(t, os.RemoveAll(disconnectedWorktreePath)) - - orphanedWorktreePath := filepath.Join(repoPath, worktreePrefix, "orphaned") - require.NoError(t, os.MkdirAll(orphanedWorktreePath, os.ModePerm)) - - for _, tc := range []struct { - worktree string - errorIs error - expectExists bool - }{ - { - worktree: "existing", - expectExists: false, - }, - { - worktree: "disconnected", - expectExists: false, - }, - { - worktree: "unknown", - errorIs: errUnknownWorktree, - expectExists: false, - }, - { - worktree: "orphaned", - errorIs: errUnknownWorktree, - expectExists: true, - }, - } { - t.Run(tc.worktree, func(t *testing.T) { - ctx, cancel := testhelper.Context() - defer cancel() - - worktreePath := filepath.Join(repoPath, worktreePrefix, tc.worktree) - - err := removeWorktree(ctx, cfg, repo, tc.worktree) - if tc.errorIs == nil { - require.NoError(t, err) - } else { - require.ErrorIs(t, err, tc.errorIs) - } - - if tc.expectExists { - require.DirExists(t, worktreePath) - } else { - require.NoDirExists(t, worktreePath) - } - }) - } -} diff --git a/internal/gitaly/service/repository/config.go b/internal/gitaly/service/repository/config.go index a0a7f420c..c650bc65b 100644 --- a/internal/gitaly/service/repository/config.go +++ b/internal/gitaly/service/repository/config.go @@ -1,11 +1,16 @@ package repository import ( + "context" + "fmt" "io" "os" "path/filepath" + "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/transaction" "gitlab.com/gitlab-org/gitaly/v14/internal/helper" + "gitlab.com/gitlab-org/gitaly/v14/internal/transaction/txinfo" + "gitlab.com/gitlab-org/gitaly/v14/internal/transaction/voting" "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" "gitlab.com/gitlab-org/gitaly/v14/streamio" "google.golang.org/grpc/codes" @@ -44,3 +49,38 @@ func (s *server) GetConfig( return nil } + +func (s *server) voteOnConfig(ctx context.Context, repo *gitalypb.Repository) error { + return transaction.RunOnContext(ctx, func(tx txinfo.Transaction) error { + repoPath, err := s.locator.GetPath(repo) + if err != nil { + return fmt.Errorf("get repo path: %w", err) + } + + var vote voting.Vote + + config, err := os.Open(filepath.Join(repoPath, "config")) + switch { + case err == nil: + hash := voting.NewVoteHash() + if _, err := io.Copy(hash, config); err != nil { + return fmt.Errorf("seeding vote: %w", err) + } + + vote, err = hash.Vote() + if err != nil { + return fmt.Errorf("computing vote: %w", err) + } + case os.IsNotExist(err): + vote = voting.VoteFromData([]byte("notfound")) + default: + return fmt.Errorf("open repo config: %w", err) + } + + if err := s.txManager.Vote(ctx, tx, vote); err != nil { + return fmt.Errorf("casting vote: %w", err) + } + + return nil + }) +} diff --git a/internal/gitaly/service/repository/create_bundle_from_ref_list.go b/internal/gitaly/service/repository/create_bundle_from_ref_list.go index 6bc15efd1..2829b4da7 100644 --- a/internal/gitaly/service/repository/create_bundle_from_ref_list.go +++ b/internal/gitaly/service/repository/create_bundle_from_ref_list.go @@ -68,10 +68,7 @@ func (s *server) CreateBundleFromRefList(stream gitalypb.RepositoryService_Creat return status.Errorf(codes.Internal, "stream writer failed: %v", err) } - err = cmd.Wait() - if isExitWithCode(err, 128) && bytes.HasPrefix(stderr.Bytes(), []byte("fatal: Refusing to create empty bundle.")) { - return status.Errorf(codes.FailedPrecondition, "cmd wait failed: refusing to create empty bundle") - } else if err != nil { + if err := cmd.Wait(); err != nil { return status.Errorf(codes.Internal, "cmd wait failed: %v, stderr: %q", err, stderr.String()) } diff --git a/internal/gitaly/service/repository/create_bundle_from_ref_list_test.go b/internal/gitaly/service/repository/create_bundle_from_ref_list_test.go index 382fce605..2174d891d 100644 --- a/internal/gitaly/service/repository/create_bundle_from_ref_list_test.go +++ b/internal/gitaly/service/repository/create_bundle_from_ref_list_test.go @@ -71,30 +71,17 @@ func TestCreateBundleFromRefList_success(t *testing.T) { func TestCreateBundleFromRefList_validations(t *testing.T) { t.Parallel() - _, repo, _, client := setupRepositoryService(t) + _, client := setupRepositoryServiceWithoutRepo(t) testCases := []struct { - desc string - request *gitalypb.CreateBundleFromRefListRequest - expectedErr string - expectedCode codes.Code + desc string + request *gitalypb.CreateBundleFromRefListRequest + code codes.Code }{ { - desc: "empty repository", - request: &gitalypb.CreateBundleFromRefListRequest{ - Patterns: [][]byte{[]byte("master")}, - }, - expectedErr: "empty Repository", - expectedCode: codes.InvalidArgument, - }, - { - desc: "empty bundle", - request: &gitalypb.CreateBundleFromRefListRequest{ - Repository: repo, - Patterns: [][]byte{[]byte("master"), []byte("^master")}, - }, - expectedErr: "cmd wait failed: refusing to create empty bundle", - expectedCode: codes.FailedPrecondition, + desc: "empty repository", + request: &gitalypb.CreateBundleFromRefListRequest{Patterns: [][]byte{[]byte("master")}}, + code: codes.InvalidArgument, }, } @@ -109,15 +96,9 @@ func TestCreateBundleFromRefList_validations(t *testing.T) { require.NoError(t, stream.Send(testCase.request)) require.NoError(t, stream.CloseSend()) - for { - _, err = stream.Recv() - if err != nil { - break - } - } - require.Error(t, err) - require.Contains(t, err.Error(), testCase.expectedErr) - testhelper.RequireGrpcError(t, err, testCase.expectedCode) + _, err = stream.Recv() + require.NotEqual(t, io.EOF, err) + testhelper.RequireGrpcError(t, err, testCase.code) }) } } diff --git a/internal/gitaly/service/repository/fetch_bundle.go b/internal/gitaly/service/repository/fetch_bundle.go deleted file mode 100644 index 05204d064..000000000 --- a/internal/gitaly/service/repository/fetch_bundle.go +++ /dev/null @@ -1,75 +0,0 @@ -package repository - -import ( - "io" - "os" - "path/filepath" - - gitalyerrors "gitlab.com/gitlab-org/gitaly/v14/internal/errors" - "gitlab.com/gitlab-org/gitaly/v14/internal/git" - "gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo" - "gitlab.com/gitlab-org/gitaly/v14/internal/helper" - "gitlab.com/gitlab-org/gitaly/v14/internal/tempdir" - "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" - "gitlab.com/gitlab-org/gitaly/v14/streamio" -) - -const ( - mirrorRefSpec = "+refs/*:refs/*" -) - -func (s *server) FetchBundle(stream gitalypb.RepositoryService_FetchBundleServer) error { - firstRequest, err := stream.Recv() - if err != nil { - return helper.ErrInternalf("first request: %v", err) - } - - if firstRequest.GetRepository() == nil { - return helper.ErrInvalidArgument(gitalyerrors.ErrEmptyRepository) - } - - firstRead := true - reader := streamio.NewReader(func() ([]byte, error) { - if firstRead { - firstRead = false - return firstRequest.GetData(), nil - } - - request, err := stream.Recv() - return request.GetData(), err - }) - - ctx := stream.Context() - repo := s.localrepo(firstRequest.GetRepository()) - - tmpDir, err := tempdir.New(ctx, repo.GetStorageName(), s.locator) - if err != nil { - return helper.ErrInternal(err) - } - - bundlePath := filepath.Join(tmpDir.Path(), "repo.bundle") - file, err := os.Create(bundlePath) - if err != nil { - return helper.ErrInternal(err) - } - - _, err = io.Copy(file, reader) - if err != nil { - return helper.ErrInternalf("copy bundle: %w", err) - } - - config := []git.ConfigPair{ - {Key: "remote.inmemory.url", Value: bundlePath}, - {Key: "remote.inmemory.fetch", Value: mirrorRefSpec}, - } - opts := localrepo.FetchOpts{ - Prune: true, - CommandOptions: []git.CmdOpt{git.WithConfigEnv(config...)}, - } - - if err := repo.FetchRemote(ctx, "inmemory", opts); err != nil { - return helper.ErrInternal(err) - } - - return stream.SendAndClose(&gitalypb.FetchBundleResponse{}) -} diff --git a/internal/gitaly/service/repository/fetch_bundle_test.go b/internal/gitaly/service/repository/fetch_bundle_test.go deleted file mode 100644 index a81889000..000000000 --- a/internal/gitaly/service/repository/fetch_bundle_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package repository - -import ( - "context" - "io" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest" - gitalyhook "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/hook" - "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service" - "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/hook" - "gitlab.com/gitlab-org/gitaly/v14/internal/helper" - "gitlab.com/gitlab-org/gitaly/v14/internal/metadata" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testserver" - "gitlab.com/gitlab-org/gitaly/v14/internal/transaction/txinfo" - "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" - "gitlab.com/gitlab-org/gitaly/v14/streamio" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" -) - -func TestServer_FetchBundle_success(t *testing.T) { - t.Parallel() - cfg, _, repoPath, client := setupRepositoryService(t) - - tmp := testhelper.TempDir(t) - bundlePath := filepath.Join(tmp, "test.bundle") - - gittest.Exec(t, cfg, "-C", repoPath, "bundle", "create", bundlePath, "--all") - expectedRefs := gittest.Exec(t, cfg, "-C", repoPath, "show-ref", "--head") - - targetRepo, targetRepoPath := gittest.InitRepo(t, cfg, cfg.Storages[0]) - - ctx, cancel := testhelper.Context() - defer cancel() - - stream, err := client.FetchBundle(ctx) - require.NoError(t, err) - - request := &gitalypb.FetchBundleRequest{Repository: targetRepo} - writer := streamio.NewWriter(func(p []byte) error { - request.Data = p - - if err := stream.Send(request); err != nil { - return err - } - - request = &gitalypb.FetchBundleRequest{} - - return nil - }) - - bundle, err := os.Open(bundlePath) - require.NoError(t, err) - defer testhelper.MustClose(t, bundle) - - _, err = io.Copy(writer, bundle) - require.NoError(t, err) - - _, err = stream.CloseAndRecv() - require.NoError(t, err) - - refs := gittest.Exec(t, cfg, "-C", targetRepoPath, "show-ref", "--head") - require.Equal(t, string(expectedRefs), string(refs)) -} - -func TestServer_FetchBundle_transaction(t *testing.T) { - t.Parallel() - cfg, repoProto, repoPath := testcfg.BuildWithRepo(t) - testhelper.BuildGitalyHooks(t, cfg) - - hookManager := &mockHookManager{} - addr := testserver.RunGitalyServer(t, cfg, nil, func(srv *grpc.Server, deps *service.Dependencies) { - gitalypb.RegisterRepositoryServiceServer(srv, NewServer( - deps.GetCfg(), - deps.GetRubyServer(), - deps.GetLocator(), - deps.GetTxManager(), - deps.GetGitCmdFactory(), - deps.GetCatfileCache(), - )) - gitalypb.RegisterHookServiceServer(srv, hook.NewServer( - deps.GetCfg(), - deps.GetHookManager(), - deps.GetGitCmdFactory(), - deps.GetPackObjectsCache(), - )) - }, testserver.WithHookManager(hookManager), testserver.WithDisablePraefect()) - - client := newRepositoryClient(t, cfg, addr) - - tmp := testhelper.TempDir(t) - bundlePath := filepath.Join(tmp, "test.bundle") - gittest.BundleTestRepo(t, cfg, "gitlab-test.git", bundlePath) - - _, stopGitServer := gittest.GitServer(t, cfg, repoPath, nil) - defer func() { require.NoError(t, stopGitServer()) }() - - ctx, cancel := testhelper.Context() - defer cancel() - ctx, err := txinfo.InjectTransaction(ctx, 1, "node", true) - require.NoError(t, err) - ctx = metadata.IncomingToOutgoing(ctx) - - require.Empty(t, hookManager.states) - - stream, err := client.FetchBundle(ctx) - require.NoError(t, err) - - request := &gitalypb.FetchBundleRequest{Repository: repoProto} - writer := streamio.NewWriter(func(p []byte) error { - request.Data = p - - if err := stream.Send(request); err != nil { - return err - } - - request = &gitalypb.FetchBundleRequest{} - - return nil - }) - - bundle, err := os.Open(bundlePath) - require.NoError(t, err) - defer testhelper.MustClose(t, bundle) - - _, err = io.Copy(writer, bundle) - require.NoError(t, err) - - _, err = stream.CloseAndRecv() - require.NoError(t, err) - - require.Equal(t, []gitalyhook.ReferenceTransactionState{ - gitalyhook.ReferenceTransactionPrepared, - gitalyhook.ReferenceTransactionCommitted, - }, hookManager.states) -} - -func TestServer_FetchBundle_validation(t *testing.T) { - t.Parallel() - - for _, tc := range []struct { - desc string - firstRequest *gitalypb.FetchBundleRequest - expectedStreamErr string - expectedStreamErrCode codes.Code - }{ - { - desc: "no repo", - firstRequest: &gitalypb.FetchBundleRequest{ - Repository: nil, - }, - expectedStreamErr: "empty Repository", - expectedStreamErrCode: codes.InvalidArgument, - }, - { - desc: "unknown repo", - firstRequest: &gitalypb.FetchBundleRequest{ - Repository: &gitalypb.Repository{ - StorageName: "default", - RelativePath: "unknown", - }, - }, - expectedStreamErr: "not a git repository", - expectedStreamErrCode: codes.NotFound, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - _, client := setupRepositoryServiceWithoutRepo(t) - - ctx, cancel := testhelper.Context() - defer cancel() - - stream, err := client.FetchBundle(ctx) - require.NoError(t, err) - - err = stream.Send(tc.firstRequest) - require.NoError(t, err) - - _, err = stream.CloseAndRecv() - require.Error(t, err) - if tc.expectedStreamErr != "" { - require.Contains(t, err.Error(), tc.expectedStreamErr) - } - if tc.expectedStreamErrCode != 0 { - require.Equal(t, tc.expectedStreamErrCode, helper.GrpcCode(err)) - } - }) - } -} - -type mockHookManager struct { - gitalyhook.Manager - states []gitalyhook.ReferenceTransactionState -} - -func (m *mockHookManager) ReferenceTransactionHook(_ context.Context, state gitalyhook.ReferenceTransactionState, _ []string, _ io.Reader) error { - m.states = append(m.states, state) - return nil -} diff --git a/internal/gitaly/service/repository/fetch_remote.go b/internal/gitaly/service/repository/fetch_remote.go index 0a18c9140..34a9c90fa 100644 --- a/internal/gitaly/service/repository/fetch_remote.go +++ b/internal/gitaly/service/repository/fetch_remote.go @@ -26,12 +26,11 @@ func (s *server) FetchRemote(ctx context.Context, req *gitalypb.FetchRemoteReque var stderr bytes.Buffer opts := localrepo.FetchOpts{ - Stderr: &stderr, - Force: req.Force, - Prune: !req.NoPrune, - Tags: localrepo.FetchOptsTagsAll, - Verbose: req.GetCheckTagsChanged(), - DisableTransactions: true, + Stderr: &stderr, + Force: req.Force, + Prune: !req.NoPrune, + Tags: localrepo.FetchOptsTagsAll, + Verbose: req.GetCheckTagsChanged(), } if req.GetNoTags() { diff --git a/internal/gitaly/service/repository/fullpath.go b/internal/gitaly/service/repository/fullpath.go index d2fdbe86d..0fbe27878 100644 --- a/internal/gitaly/service/repository/fullpath.go +++ b/internal/gitaly/service/repository/fullpath.go @@ -4,6 +4,7 @@ import ( "context" "gitlab.com/gitlab-org/gitaly/v14/internal/helper" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" ) @@ -25,8 +26,24 @@ func (s *server) SetFullPath( repo := s.localrepo(request.GetRepository()) - if err := repo.SetConfig(ctx, fullPathKey, request.GetPath(), s.txManager); err != nil { - return nil, helper.ErrInternalf("setting config: %w", err) + if featureflag.TxFileLocking.IsEnabled(ctx) { + if err := repo.SetConfig(ctx, fullPathKey, request.GetPath(), s.txManager); err != nil { + return nil, helper.ErrInternalf("setting config: %w", err) + } + + return &gitalypb.SetFullPathResponse{}, nil + } + + if err := s.voteOnConfig(ctx, request.GetRepository()); err != nil { + return nil, helper.ErrInternalf("preimage vote on config: %w", err) + } + + if err := repo.Config().Set(ctx, fullPathKey, request.GetPath()); err != nil { + return nil, helper.ErrInternalf("writing config: %w", err) + } + + if err := s.voteOnConfig(ctx, request.GetRepository()); err != nil { + return nil, helper.ErrInternalf("postimage vote on config: %w", err) } return &gitalypb.SetFullPathResponse{}, nil diff --git a/internal/gitaly/service/repository/fullpath_test.go b/internal/gitaly/service/repository/fullpath_test.go index dea6d131e..1224e30fd 100644 --- a/internal/gitaly/service/repository/fullpath_test.go +++ b/internal/gitaly/service/repository/fullpath_test.go @@ -1,6 +1,7 @@ package repository import ( + "context" "fmt" "os" "path/filepath" @@ -11,6 +12,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config" "gitlab.com/gitlab-org/gitaly/v14/internal/helper" "gitlab.com/gitlab-org/gitaly/v14/internal/helper/text" + "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testassert" "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" @@ -19,9 +21,12 @@ import ( func TestSetFullPath(t *testing.T) { t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() + testhelper.NewFeatureSets([]featureflag.FeatureFlag{ + featureflag.TxFileLocking, + }).Run(t, testSetFullPath) +} +func testSetFullPath(t *testing.T, ctx context.Context) { cfg, client := setupRepositoryServiceWithoutRepo(t) t.Run("missing repository", func(t *testing.T) { @@ -74,8 +79,12 @@ func TestSetFullPath(t *testing.T) { require.Nil(t, response) - expectedErr := fmt.Sprintf("rpc error: code = NotFound desc = setting config: rpc "+ + expectedErr := fmt.Sprintf("rpc error: code = NotFound desc = writing config: rpc "+ "error: code = NotFound desc = GetRepoPath: not a git repository: %q", repoPath) + if featureflag.TxFileLocking.IsEnabled(ctx) { + expectedErr = fmt.Sprintf("rpc error: code = NotFound desc = setting config: rpc "+ + "error: code = NotFound desc = GetRepoPath: not a git repository: %q", repoPath) + } require.EqualError(t, err, expectedErr) }) diff --git a/internal/gitaly/service/smarthttp/testhelper_test.go b/internal/gitaly/service/smarthttp/testhelper_test.go index 3b4ef7cfc..bb6b2c9fe 100644 --- a/internal/gitaly/service/smarthttp/testhelper_test.go +++ b/internal/gitaly/service/smarthttp/testhelper_test.go @@ -53,22 +53,6 @@ func runSmartHTTPServer(t *testing.T, cfg config.Cfg, serverOpts ...ServerOpt) s return gitalyServer.Address() } -// TODO: remove this method and use runSmartHTTPServer after -// https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1218 -func runSmartHTTPServerWithoutPraefect(t *testing.T, cfg config.Cfg, serverOpts ...ServerOpt) string { - gitalyServer := testserver.StartGitalyServer(t, cfg, nil, func(srv *grpc.Server, deps *service.Dependencies) { - gitalypb.RegisterSmartHTTPServiceServer(srv, NewServer( - deps.GetCfg(), - deps.GetLocator(), - deps.GetGitCmdFactory(), - deps.GetDiskCache(), - serverOpts..., - )) - gitalypb.RegisterHookServiceServer(srv, hookservice.NewServer(deps.GetCfg(), deps.GetHookManager(), deps.GetGitCmdFactory(), deps.GetPackObjectsCache())) - }, testserver.WithDisablePraefect()) - return gitalyServer.Address() -} - func newSmartHTTPClient(t *testing.T, serverSocketPath, token string) (gitalypb.SmartHTTPServiceClient, *grpc.ClientConn) { t.Helper() diff --git a/internal/gitaly/service/smarthttp/upload_pack.go b/internal/gitaly/service/smarthttp/upload_pack.go index 768e686e6..e8e900d63 100644 --- a/internal/gitaly/service/smarthttp/upload_pack.go +++ b/internal/gitaly/service/smarthttp/upload_pack.go @@ -10,20 +10,12 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/command" "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/git/stats" - "gitlab.com/gitlab-org/gitaly/v14/internal/helper" - "gitlab.com/gitlab-org/gitaly/v14/internal/sidechannel" "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" "gitlab.com/gitlab-org/gitaly/v14/streamio" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) -type basicPostUploadPackRequest interface { - GetRepository() *gitalypb.Repository - GetGitConfigOptions() []string - GetGitProtocol() string -} - func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackServer) error { ctx := stream.Context() @@ -32,48 +24,81 @@ func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackS return err } - if req.Data != nil { - return status.Errorf(codes.InvalidArgument, "non-empty Data") - } - - repoPath, gitConfig, err := s.validateUploadPackRequest(ctx, req) - if err != nil { + if err := validateUploadPackRequest(req); err != nil { return err } - stdin := streamio.NewReader(func() ([]byte, error) { + h := sha1.New() + + stdinReader := io.TeeReader(streamio.NewReader(func() ([]byte, error) { resp, err := stream.Recv() return resp.GetData(), err - }) + }), h) + + stdin, collector := s.runStatsCollector(stream.Context(), stdinReader) + defer collector.finish() + + var respBytes int64 + stdout := streamio.NewWriter(func(p []byte) error { + respBytes += int64(len(p)) return stream.Send(&gitalypb.PostUploadPackResponse{Data: p}) }) - return s.runUploadPack(ctx, req, repoPath, gitConfig, stdin, stdout) -} + repoPath, err := s.locator.GetRepoPath(req.Repository) + if err != nil { + return err + } + + git.WarnIfTooManyBitmaps(ctx, s.locator, req.GetRepository().GetStorageName(), repoPath) -func (s *server) PostUploadPackWithSidechannel(ctx context.Context, req *gitalypb.PostUploadPackWithSidechannelRequest) (*gitalypb.PostUploadPackWithSidechannelResponse, error) { - repoPath, gitConfig, err := s.validateUploadPackRequest(ctx, req) + config, err := git.ConvertConfigOptions(req.GitConfigOptions) if err != nil { - return nil, err + return err } - conn, err := sidechannel.OpenSidechannel(ctx) + commandOpts := []git.CmdOpt{ + git.WithStdin(stdin), + git.WithStdout(stdout), + git.WithGitProtocol(ctx, req), + git.WithConfig(config...), + git.WithPackObjectsHookEnv(ctx, req.Repository, s.cfg), + } + + cmd, err := s.gitCmdFactory.NewWithoutRepo(ctx, git.SubCmd{ + Name: "upload-pack", + Flags: []git.Option{git.Flag{Name: "--stateless-rpc"}}, + Args: []string{repoPath}, + }, commandOpts...) if err != nil { - return nil, status.Errorf(codes.Internal, "open sidechannel: %v", err) + return status.Errorf(codes.Unavailable, "PostUploadPack: cmd: %v", err) } - defer conn.Close() - if err := s.runUploadPack(ctx, req, repoPath, gitConfig, conn, conn); err != nil { - return nil, err + if err := cmd.Wait(); err != nil { + stats := collector.finish() + + if _, ok := command.ExitStatus(err); ok && stats.Deepen != "" { + // We have seen a 'deepen' message in the request. It is expected that + // git-upload-pack has a non-zero exit status: don't treat this as an + // error. + return nil + } + + return status.Errorf(codes.Unavailable, "PostUploadPack: %v", err) } - if err := conn.Close(); err != nil { - return nil, status.Errorf(codes.Internal, "close sidechannel connection: %v", err) + ctxlogrus.Extract(ctx).WithField("request_sha", fmt.Sprintf("%x", h.Sum(nil))).WithField("response_bytes", respBytes).Info("request details") + + return nil +} + +func validateUploadPackRequest(req *gitalypb.PostUploadPackRequest) error { + if req.Data != nil { + return status.Errorf(codes.InvalidArgument, "PostUploadPack: non-empty Data") } - return &gitalypb.PostUploadPackWithSidechannelResponse{}, nil + return nil } type statsCollector struct { @@ -108,65 +133,3 @@ func (s *server) runStatsCollector(ctx context.Context, r io.Reader) (io.Reader, return io.TeeReader(r, pw), sc } - -func (s *server) validateUploadPackRequest(ctx context.Context, req basicPostUploadPackRequest) (string, []git.ConfigPair, error) { - repoPath, err := s.locator.GetRepoPath(req.GetRepository()) - if err != nil { - return "", nil, helper.ErrInvalidArgument(err) - } - - git.WarnIfTooManyBitmaps(ctx, s.locator, req.GetRepository().GetStorageName(), repoPath) - - config, err := git.ConvertConfigOptions(req.GetGitConfigOptions()) - if err != nil { - return "", nil, helper.ErrInvalidArgument(err) - } - - return repoPath, config, nil -} - -func (s *server) runUploadPack(ctx context.Context, req basicPostUploadPackRequest, repoPath string, gitConfig []git.ConfigPair, stdin io.Reader, stdout io.Writer) error { - h := sha1.New() - - stdin = io.TeeReader(stdin, h) - stdin, collector := s.runStatsCollector(ctx, stdin) - defer collector.finish() - - commandOpts := []git.CmdOpt{ - git.WithStdin(stdin), - git.WithGitProtocol(ctx, req), - git.WithConfig(gitConfig...), - git.WithPackObjectsHookEnv(ctx, req.GetRepository(), s.cfg), - } - - cmd, err := s.gitCmdFactory.NewWithoutRepo(ctx, git.SubCmd{ - Name: "upload-pack", - Flags: []git.Option{git.Flag{Name: "--stateless-rpc"}}, - Args: []string{repoPath}, - }, commandOpts...) - if err != nil { - return helper.ErrUnavailablef("cmd: %v", err) - } - - respBytes, err := io.Copy(stdout, cmd) - if err != nil { - return helper.ErrUnavailablef("Fail to transfer git data: %v", err) - } - - if err := cmd.Wait(); err != nil { - stats := collector.finish() - - if _, ok := command.ExitStatus(err); ok && stats.Deepen != "" { - // We have seen a 'deepen' message in the request. It is expected that - // git-upload-pack has a non-zero exit status: don't treat this as an - // error. - return nil - } - - return helper.ErrUnavailable(err) - } - - ctxlogrus.Extract(ctx).WithField("request_sha", fmt.Sprintf("%x", h.Sum(nil))).WithField("response_bytes", respBytes).Info("request details") - - return nil -} diff --git a/internal/gitaly/service/smarthttp/upload_pack_test.go b/internal/gitaly/service/smarthttp/upload_pack_test.go index cd4fbbd3a..8785a2c0e 100644 --- a/internal/gitaly/service/smarthttp/upload_pack_test.go +++ b/internal/gitaly/service/smarthttp/upload_pack_test.go @@ -13,64 +13,44 @@ import ( promtest "github.com/prometheus/client_golang/prometheus/testutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - gitalyauth "gitlab.com/gitlab-org/gitaly/v14/auth" "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v14/internal/git/pktline" - "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config" - "gitlab.com/gitlab-org/gitaly/v14/internal/sidechannel" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" "gitlab.com/gitlab-org/gitaly/v14/streamio" - "google.golang.org/grpc" "google.golang.org/grpc/codes" - "google.golang.org/grpc/credentials/insecure" ) const ( clientCapabilities = `multi_ack_detailed no-done side-band-64k thin-pack include-tag ofs-delta deepen-since deepen-not filter agent=git/2.18.0` ) -type ( - requestMaker func(ctx context.Context, t *testing.T, serverSocketPath, token string, in *gitalypb.PostUploadPackRequest, body io.Reader) (*bytes.Buffer, error) - serverRunner func(t *testing.T, cfg config.Cfg, serverOpts ...ServerOpt) string -) - -func runTestWithAndWithoutConfigOptions( - t *testing.T, - tf func(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option), - makeRequest requestMaker, - runServer serverRunner, - opts ...testcfg.Option, -) { +func runTestWithAndWithoutConfigOptions(t *testing.T, tf func(t *testing.T, ctx context.Context, opts ...testcfg.Option), opts ...testcfg.Option) { ctx, cancel := testhelper.Context() defer cancel() - t.Run("no config options", func(t *testing.T) { tf(t, ctx, makeRequest, runServer) }) + t.Run("no config options", func(t *testing.T) { tf(t, ctx) }) if len(opts) > 0 { t.Run("with config options", func(t *testing.T) { - tf(t, ctx, makeRequest, runServer, opts...) + tf(t, ctx, opts...) }) } } func TestServer_PostUpload(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUpload, makePostUploadPackRequest, runSmartHTTPServer, testcfg.WithPackObjectsCacheEnabled()) -} - -func TestServer_PostUploadWithChannel(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUpload, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions(t, testServerPostUpload, testcfg.WithPackObjectsCacheEnabled()) } -func testServerPostUpload(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { +func testServerPostUpload(t *testing.T, ctx context.Context, opts ...testcfg.Option) { cfg, repo, repoPath := testcfg.BuildWithRepo(t, opts...) _, localRepoPath := gittest.CloneRepo(t, cfg, cfg.Storages[0]) testhelper.BuildGitalyHooks(t, cfg) negotiationMetrics := prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"feature"}) - serverSocketPath := runServer(t, cfg, WithPackfileNegotiationMetrics(negotiationMetrics)) + serverSocketPath := runSmartHTTPServer(t, cfg, WithPackfileNegotiationMetrics(negotiationMetrics)) oldCommit, err := git.NewObjectIDFromHex("1e292f8fedd741b75372e19097c76d327140c312") // refs/heads/master require.NoError(t, err) @@ -85,7 +65,7 @@ func testServerPostUpload(t *testing.T, ctx context.Context, makeRequest request gittest.WritePktlineFlush(t, requestBuffer) req := &gitalypb.PostUploadPackRequest{Repository: repo} - responseBuffer, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, req, requestBuffer) + responseBuffer, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, req, requestBuffer) require.NoError(t, err) pack, version, entries := extractPackDataFromResponse(t, responseBuffer) @@ -101,18 +81,14 @@ func testServerPostUpload(t *testing.T, ctx context.Context, makeRequest request } func TestServer_PostUploadPack_gitConfigOptions(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitConfigOptions, makePostUploadPackRequest, runSmartHTTPServer, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitConfigOptions, testcfg.WithPackObjectsCacheEnabled()) } -func TestServer_PostUploadPackSidechannel_gitConfigOptions(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitConfigOptions, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect, testcfg.WithPackObjectsCacheEnabled()) -} - -func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { +func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, opts ...testcfg.Option) { cfg, repo, repoPath := testcfg.BuildWithRepo(t, opts...) testhelper.BuildGitalyHooks(t, cfg) - serverSocketPath := runServer(t, cfg) + serverSocketPath := runSmartHTTPServer(t, cfg) want := "3dd08961455abf80ef9115f4afdc1c6f968b503c" // refs/heads/csv gittest.Exec(t, cfg, "-C", repoPath, "update-ref", "refs/hidden/csv", want) @@ -130,7 +106,7 @@ func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, t.Run("sanity check: ref exists and can be fetched", func(t *testing.T) { rpcRequest := &gitalypb.PostUploadPackRequest{Repository: repo} - response, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, bytes.NewReader(requestBody.Bytes())) + response, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, bytes.NewReader(requestBody.Bytes())) require.NoError(t, err) _, _, count := extractPackDataFromResponse(t, response) require.Equal(t, 5, count, "pack should have 5 entries") @@ -144,7 +120,7 @@ func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, "uploadpack.allowAnySHA1InWant=false", }, } - response, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, bytes.NewReader(requestBody.Bytes())) + response, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, bytes.NewReader(requestBody.Bytes())) testhelper.RequireGrpcError(t, err, codes.Unavailable) // The failure message proves that upload-pack failed because of @@ -155,17 +131,13 @@ func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, } func TestServer_PostUploadPack_gitProtocol(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitProtocol, makePostUploadPackRequest, runSmartHTTPServer, testcfg.WithPackObjectsCacheEnabled()) -} - -func TestServer_PostUploadPackWithSidechannel_gitProtocol(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitProtocol, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitProtocol, testcfg.WithPackObjectsCacheEnabled()) } -func testServerPostUploadPackGitProtocol(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { +func testServerPostUploadPackGitProtocol(t *testing.T, ctx context.Context, opts ...testcfg.Option) { cfg, repo, _ := testcfg.BuildWithRepo(t, opts...) readProto, cfg := gittest.EnableGitProtocolV2Support(t, cfg) - serverSocketPath := runServer(t, cfg) + serverSocketPath := runSmartHTTPServer(t, cfg) // command=ls-refs does not exist in protocol v0, so if this succeeds, we're talking v2 requestBody := &bytes.Buffer{} @@ -180,7 +152,7 @@ func testServerPostUploadPackGitProtocol(t *testing.T, ctx context.Context, make GitProtocol: git.ProtocolV2, } - _, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, requestBody) + _, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, requestBody) require.NoError(t, err) envData := readProto() @@ -191,16 +163,12 @@ func testServerPostUploadPackGitProtocol(t *testing.T, ctx context.Context, make // on 'deepen' requests even though the request is being handled just // fine from the client perspective. func TestServer_PostUploadPack_suppressDeepenExitError(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackSuppressDeepenExitError, makePostUploadPackRequest, runSmartHTTPServer, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackSuppressDeepenExitError, testcfg.WithPackObjectsCacheEnabled()) } -func TestServer_PostUploadPackWithSidechannel_suppressDeepenExitError(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackSuppressDeepenExitError, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect, testcfg.WithPackObjectsCacheEnabled()) -} - -func testServerPostUploadPackSuppressDeepenExitError(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { +func testServerPostUploadPackSuppressDeepenExitError(t *testing.T, ctx context.Context, opts ...testcfg.Option) { cfg, repo, _ := testcfg.BuildWithRepo(t, opts...) - serverSocketPath := runServer(t, cfg) + serverSocketPath := runSmartHTTPServer(t, cfg) requestBody := &bytes.Buffer{} gittest.WritePktlineString(t, requestBody, fmt.Sprintf("want e63f41fe459e62e1228fcef60d7189127aeba95a %s\n", clientCapabilities)) @@ -208,7 +176,7 @@ func testServerPostUploadPackSuppressDeepenExitError(t *testing.T, ctx context.C gittest.WritePktlineFlush(t, requestBody) rpcRequest := &gitalypb.PostUploadPackRequest{Repository: repo} - response, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, requestBody) + response, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, requestBody) // This assertion is the main reason this test exists. assert.NoError(t, err) @@ -216,20 +184,6 @@ func testServerPostUploadPackSuppressDeepenExitError(t *testing.T, ctx context.C } func TestServer_PostUploadPack_usesPackObjectsHook(t *testing.T) { - ctx, cancel := testhelper.Context() - defer cancel() - - testServerPostUploadPackUsesPackObjectsHook(t, ctx, makePostUploadPackRequest, runSmartHTTPServer) -} - -func TestServer_PostUploadPackWithSidechannel_usesPackObjectsHook(t *testing.T) { - ctx, cancel := testhelper.Context() - defer cancel() - - testServerPostUploadPackUsesPackObjectsHook(t, ctx, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect) -} - -func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { cfg, repo, repoPath := testcfg.BuildWithRepo(t, testcfg.WithPackObjectsCacheEnabled()) cfg.BinDir = testhelper.TempDir(t) @@ -245,7 +199,7 @@ func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Conte // transferred back. testhelper.WriteExecutable(t, filepath.Join(cfg.BinDir, "gitaly-hooks"), []byte(hookScript)) - serverSocketPath := runServer(t, cfg) + serverSocketPath := runSmartHTTPServer(t, cfg) oldHead := bytes.TrimSpace(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "master~")) newHead := bytes.TrimSpace(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "master")) @@ -256,7 +210,10 @@ func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Conte gittest.WritePktlineString(t, requestBuffer, fmt.Sprintf("have %s\n", oldHead)) gittest.WritePktlineFlush(t, requestBuffer) - _, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, &gitalypb.PostUploadPackRequest{ + ctx, cancel := testhelper.Context() + defer cancel() + + _, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, &gitalypb.PostUploadPackRequest{ Repository: repo, }, requestBuffer) require.NoError(t, err) @@ -266,12 +223,12 @@ func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Conte } func TestServer_PostUploadPack_validation(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackValidation, makePostUploadPackRequest, runSmartHTTPServer, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackValidation, testcfg.WithPackObjectsCacheEnabled()) } -func testServerPostUploadPackValidation(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { +func testServerPostUploadPackValidation(t *testing.T, ctx context.Context, opts ...testcfg.Option) { cfg := testcfg.Build(t, opts...) - serverSocketPath := runServer(t, cfg) + serverSocketPath := runSmartHTTPServer(t, cfg) rpcRequests := []*gitalypb.PostUploadPackRequest{ {Repository: &gitalypb.Repository{StorageName: "fake", RelativePath: "path"}}, // Repository doesn't exist @@ -281,31 +238,39 @@ func testServerPostUploadPackValidation(t *testing.T, ctx context.Context, makeR for _, rpcRequest := range rpcRequests { t.Run(fmt.Sprintf("%v", rpcRequest), func(t *testing.T) { - _, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, bytes.NewBuffer(nil)) + _, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, bytes.NewBuffer(nil)) testhelper.RequireGrpcError(t, err, codes.InvalidArgument) }) } } -func TestServer_PostUploadPackSidechannel_validation(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackWithSideChannelValidation, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect, testcfg.WithPackObjectsCacheEnabled()) -} +func makePostUploadPackRequest(ctx context.Context, t *testing.T, serverSocketPath, token string, in *gitalypb.PostUploadPackRequest, body io.Reader) (*bytes.Buffer, error) { + client, conn := newSmartHTTPClient(t, serverSocketPath, token) + defer conn.Close() -func testServerPostUploadPackWithSideChannelValidation(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { - cfg := testcfg.Build(t, opts...) - serverSocketPath := runServer(t, cfg) + stream, err := client.PostUploadPack(ctx) + require.NoError(t, err) - rpcRequests := []*gitalypb.PostUploadPackRequest{ - {Repository: &gitalypb.Repository{StorageName: "fake", RelativePath: "path"}}, // Repository doesn't exist - {Repository: nil}, // Repository is nil - } + require.NoError(t, stream.Send(in)) - for _, rpcRequest := range rpcRequests { - t.Run(fmt.Sprintf("%v", rpcRequest), func(t *testing.T) { - _, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, rpcRequest, bytes.NewBuffer(nil)) - testhelper.RequireGrpcError(t, err, codes.InvalidArgument) + if body != nil { + sw := streamio.NewWriter(func(p []byte) error { + return stream.Send(&gitalypb.PostUploadPackRequest{Data: p}) }) + + _, err = io.Copy(sw, body) + require.NoError(t, err) + require.NoError(t, stream.CloseSend()) } + + responseBuffer := &bytes.Buffer{} + rr := streamio.NewReader(func() ([]byte, error) { + resp, err := stream.Recv() + return resp.GetData(), err + }) + _, err = io.Copy(responseBuffer, rr) + + return responseBuffer, err } // The response contains bunch of things; metadata, progress messages, and a pack file. We're only @@ -348,20 +313,16 @@ func extractPackDataFromResponse(t *testing.T, buf *bytes.Buffer) ([]byte, int, } func TestServer_PostUploadPack_partialClone(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackPartialClone, makePostUploadPackRequest, runSmartHTTPServer, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackPartialClone, testcfg.WithPackObjectsCacheEnabled()) } -func TestServer_PostUploadPackWithSidechannel_partialClone(t *testing.T) { - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackPartialClone, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect, testcfg.WithPackObjectsCacheEnabled()) -} - -func testServerPostUploadPackPartialClone(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { +func testServerPostUploadPackPartialClone(t *testing.T, ctx context.Context, opts ...testcfg.Option) { cfg, repo, repoPath := testcfg.BuildWithRepo(t, opts...) _, localRepoPath := gittest.InitRepo(t, cfg, cfg.Storages[0]) testhelper.BuildGitalyHooks(t, cfg) negotiationMetrics := prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"feature"}) - serverSocketPath := runServer(t, cfg, WithPackfileNegotiationMetrics(negotiationMetrics)) + serverSocketPath := runSmartHTTPServer(t, cfg, WithPackfileNegotiationMetrics(negotiationMetrics)) oldCommit, err := git.NewObjectIDFromHex("1e292f8fedd741b75372e19097c76d327140c312") // refs/heads/master require.NoError(t, err) @@ -375,7 +336,7 @@ func testServerPostUploadPackPartialClone(t *testing.T, ctx context.Context, mak gittest.WritePktlineFlush(t, &requestBuffer) req := &gitalypb.PostUploadPackRequest{Repository: repo} - responseBuffer, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, req, &requestBuffer) + responseBuffer, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, req, &requestBuffer) require.NoError(t, err) pack, version, entries := extractPackDataFromResponse(t, responseBuffer) @@ -402,22 +363,11 @@ func TestServer_PostUploadPack_allowAnySHA1InWant(t *testing.T) { ctx, cancel := testhelper.Context() defer cancel() - testServerPostUploadPackAllowAnySHA1InWant(t, ctx, makePostUploadPackRequest, runSmartHTTPServer) -} - -func TestServer_PostUploadPackWithSidechannel_allowAnySHA1InWant(t *testing.T) { - ctx, cancel := testhelper.Context() - defer cancel() - - testServerPostUploadPackAllowAnySHA1InWant(t, ctx, makePostUploadPackWithSidechannelRequest, runSmartHTTPServerWithoutPraefect) -} - -func testServerPostUploadPackAllowAnySHA1InWant(t *testing.T, ctx context.Context, makeRequest requestMaker, runServer serverRunner, opts ...testcfg.Option) { cfg, repo, repoPath := testcfg.BuildWithRepo(t) _, localRepoPath := gittest.InitRepo(t, cfg, cfg.Storages[0]) testhelper.BuildGitalyHooks(t, cfg) - serverSocketPath := runServer(t, cfg) + serverSocketPath := runSmartHTTPServer(t, cfg) newCommit := gittest.WriteCommit(t, cfg, repoPath) var requestBuffer bytes.Buffer @@ -427,7 +377,7 @@ func testServerPostUploadPackAllowAnySHA1InWant(t *testing.T, ctx context.Contex gittest.WritePktlineFlush(t, &requestBuffer) req := &gitalypb.PostUploadPackRequest{Repository: repo} - responseBuffer, err := makeRequest(ctx, t, serverSocketPath, cfg.Auth.Token, req, &requestBuffer) + responseBuffer, err := makePostUploadPackRequest(ctx, t, serverSocketPath, cfg.Auth.Token, req, &requestBuffer) require.NoError(t, err) pack, version, entries := extractPackDataFromResponse(t, responseBuffer) @@ -437,90 +387,3 @@ func testServerPostUploadPackAllowAnySHA1InWant(t *testing.T, ctx context.Contex gittest.GitObjectMustExist(t, cfg.Git.BinPath, localRepoPath, newCommit.String()) } - -func makePostUploadPackRequest(ctx context.Context, t *testing.T, serverSocketPath, token string, in *gitalypb.PostUploadPackRequest, body io.Reader) (*bytes.Buffer, error) { - client, conn := newSmartHTTPClient(t, serverSocketPath, token) - defer conn.Close() - - stream, err := client.PostUploadPack(ctx) - require.NoError(t, err) - - require.NoError(t, stream.Send(in)) - - if body != nil { - sw := streamio.NewWriter(func(p []byte) error { - return stream.Send(&gitalypb.PostUploadPackRequest{Data: p}) - }) - - _, err = io.Copy(sw, body) - require.NoError(t, err) - require.NoError(t, stream.CloseSend()) - } - - responseBuffer := &bytes.Buffer{} - rr := streamio.NewReader(func() ([]byte, error) { - resp, err := stream.Recv() - return resp.GetData(), err - }) - _, err = io.Copy(responseBuffer, rr) - - return responseBuffer, err -} - -func dialSmartHTTPServerWithSidechannel(t *testing.T, serverSocketPath, token string, registry *sidechannel.Registry) *grpc.ClientConn { - t.Helper() - - clientHandshaker := sidechannel.NewClientHandshaker(testhelper.DiscardTestEntry(t), registry) - connOpts := []grpc.DialOption{ - grpc.WithTransportCredentials(clientHandshaker.ClientHandshake(insecure.NewCredentials())), - grpc.WithPerRPCCredentials(gitalyauth.RPCCredentialsV2(token)), - } - - conn, err := grpc.Dial(serverSocketPath, connOpts...) - require.NoError(t, err) - - return conn -} - -func makePostUploadPackWithSidechannelRequest(ctx context.Context, t *testing.T, serverSocketPath, token string, in *gitalypb.PostUploadPackRequest, body io.Reader) (*bytes.Buffer, error) { - t.Helper() - - registry := sidechannel.NewRegistry() - conn := dialSmartHTTPServerWithSidechannel(t, serverSocketPath, token, registry) - client := gitalypb.NewSmartHTTPServiceClient(conn) - defer testhelper.MustClose(t, conn) - - responseBuffer := &bytes.Buffer{} - ctxOut, waiter := sidechannel.RegisterSidechannel(ctx, registry, func(sideConn *sidechannel.ClientConn) error { - errC := make(chan error, 1) - go func() { - _, err := io.Copy(responseBuffer, sideConn) - errC <- err - }() - - if body != nil { - if _, err := io.Copy(sideConn, body); err != nil { - return err - } - } - - if err := sideConn.CloseWrite(); err != nil { - return err - } - - return <-errC - }) - defer waiter.Close() - - rpcRequest := &gitalypb.PostUploadPackWithSidechannelRequest{ - Repository: in.GetRepository(), - GitConfigOptions: in.GetGitConfigOptions(), - GitProtocol: in.GetGitProtocol(), - } - _, err := client.PostUploadPackWithSidechannel(ctxOut, rpcRequest) - if err == nil { - require.NoError(t, waiter.Close()) - } - - return responseBuffer, err -} diff --git a/internal/log/hook.go b/internal/log/hook.go index 36a6c848d..d9a995f3e 100644 --- a/internal/log/hook.go +++ b/internal/log/hook.go @@ -31,8 +31,6 @@ func NewHookLogger() *HookLogger { logger.SetOutput(logFile) } - logger.SetFormatter(UTCTextFormatter()) - return &HookLogger{logger: logger} } diff --git a/internal/log/log.go b/internal/log/log.go index 99381418d..21171758e 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -10,32 +10,9 @@ const ( // GitalyLogDirEnvKey defines the environment variable used to specify the Gitaly log directory GitalyLogDirEnvKey = "GITALY_LOG_DIR" // LogTimestampFormat defines the timestamp format in log files - LogTimestampFormat = "2006-01-02T15:04:05.000" - // LogTimestampFormatUTC defines the utc timestamp format in log files - LogTimestampFormatUTC = "2006-01-02T15:04:05.000Z" + LogTimestampFormat = "2006-01-02T15:04:05.000Z" ) -type utcFormatter struct { - logrus.Formatter -} - -func (u utcFormatter) Format(e *logrus.Entry) ([]byte, error) { - e.Time = e.Time.UTC() - return u.Formatter.Format(e) -} - -// UTCJsonFormatter returns a Formatter that formats a logrus Entry's as json and converts the time -// field into UTC -func UTCJsonFormatter() logrus.Formatter { - return &utcFormatter{Formatter: &logrus.JSONFormatter{TimestampFormat: LogTimestampFormatUTC}} -} - -// UTCTextFormatter returns a Formatter that formats a logrus Entry's as text and converts the time -// field into UTC -func UTCTextFormatter() logrus.Formatter { - return &utcFormatter{Formatter: &logrus.TextFormatter{TimestampFormat: LogTimestampFormatUTC}} -} - var ( defaultLogger = logrus.StandardLogger() grpcGo = logrus.New() @@ -60,9 +37,11 @@ func Configure(loggers []*logrus.Logger, format string, level string) { var formatter logrus.Formatter switch format { case "json": - formatter = UTCJsonFormatter() - case "", "text": - formatter = UTCTextFormatter() + formatter = &logrus.JSONFormatter{TimestampFormat: LogTimestampFormat} + case "text": + formatter = &logrus.TextFormatter{TimestampFormat: LogTimestampFormat} + case "": + // Just stick with the default default: logrus.WithField("format", format).Fatal("invalid logger format") } diff --git a/internal/log/log_test.go b/internal/log/log_test.go index 5be348027..d51f6da3c 100644 --- a/internal/log/log_test.go +++ b/internal/log/log_test.go @@ -1,12 +1,9 @@ package log import ( - "bytes" "testing" - "time" "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -21,7 +18,7 @@ func TestConfigure(t *testing.T) { desc: "json format with info level", format: "json", logger: &logrus.Logger{ - Formatter: &utcFormatter{&logrus.JSONFormatter{TimestampFormat: LogTimestampFormatUTC}}, + Formatter: &logrus.JSONFormatter{TimestampFormat: LogTimestampFormat}, Level: logrus.InfoLevel, }, }, @@ -29,15 +26,14 @@ func TestConfigure(t *testing.T) { desc: "text format with info level", format: "text", logger: &logrus.Logger{ - Formatter: &utcFormatter{&logrus.TextFormatter{TimestampFormat: LogTimestampFormatUTC}}, + Formatter: &logrus.TextFormatter{TimestampFormat: LogTimestampFormat}, Level: logrus.InfoLevel, }, }, { desc: "empty format with info level", logger: &logrus.Logger{ - Formatter: &utcFormatter{&logrus.TextFormatter{TimestampFormat: LogTimestampFormatUTC}}, - Level: logrus.InfoLevel, + Level: logrus.InfoLevel, }, }, { @@ -45,7 +41,7 @@ func TestConfigure(t *testing.T) { format: "text", level: "debug", logger: &logrus.Logger{ - Formatter: &utcFormatter{&logrus.TextFormatter{TimestampFormat: LogTimestampFormatUTC}}, + Formatter: &logrus.TextFormatter{TimestampFormat: LogTimestampFormat}, Level: logrus.DebugLevel, }, }, @@ -54,44 +50,15 @@ func TestConfigure(t *testing.T) { format: "text", level: "invalid-level", logger: &logrus.Logger{ - Formatter: &utcFormatter{&logrus.TextFormatter{TimestampFormat: LogTimestampFormatUTC}}, + Formatter: &logrus.TextFormatter{TimestampFormat: LogTimestampFormat}, Level: logrus.InfoLevel, }, }, } { t.Run(tc.desc, func(t *testing.T) { - loggers := []*logrus.Logger{{Formatter: &logrus.TextFormatter{}}, {Formatter: &logrus.TextFormatter{}}} + loggers := []*logrus.Logger{{}, {}} Configure(loggers, tc.format, tc.level) require.Equal(t, []*logrus.Logger{tc.logger, tc.logger}, loggers) - - now := time.Now() - nowUTCFormatted := now.UTC().Format(LogTimestampFormatUTC) - - message := "this is a logging message." - var out bytes.Buffer - - // both loggers are the same, so no need to test both the same way - logger := loggers[0] - logger.Out = &out - entry := logger.WithTime(now) - - switch tc.level { - case "debug": - entry.Debug(message) - case "warn": - entry.Warn(message) - case "error": - entry.Error(message) - case "", "info": - entry.Info(message) - default: - entry.Info(message) - } - - if tc.format != "" { - assert.Contains(t, out.String(), nowUTCFormatted) - } - assert.Contains(t, out.String(), message) }) } } diff --git a/internal/metadata/featureflag/ff_git2go_merge_gob.go b/internal/metadata/featureflag/ff_git2go_merge_gob.go new file mode 100644 index 000000000..80ee664a7 --- /dev/null +++ b/internal/metadata/featureflag/ff_git2go_merge_gob.go @@ -0,0 +1,6 @@ +package featureflag + +// Git2GoMergeGob switches gitaly-git2go's merge command to use gob for serialization. This change +// allows Gitaly to pass through errors with additional details, for example to describe the set of +// conflicting files. +var Git2GoMergeGob = NewFeatureFlag("git2go_merge_gob", false) diff --git a/internal/metadata/featureflag/ff_tx_file_locking.go b/internal/metadata/featureflag/ff_tx_file_locking.go new file mode 100644 index 000000000..08f1c9f6c --- /dev/null +++ b/internal/metadata/featureflag/ff_tx_file_locking.go @@ -0,0 +1,5 @@ +package featureflag + +// TxFileLocking enables two-phase voting on files with proper locking semantics such that no races +// can exist anymore. +var TxFileLocking = NewFeatureFlag("tx_file_locking", false) diff --git a/internal/metadata/featureflag/ff_updateref_assert_locking.go b/internal/metadata/featureflag/ff_updateref_assert_locking.go new file mode 100644 index 000000000..e018fd1e6 --- /dev/null +++ b/internal/metadata/featureflag/ff_updateref_assert_locking.go @@ -0,0 +1,4 @@ +package featureflag + +// UpdaterefVerifyStateChanges causes us to assert that transactional state changes finish correctly. +var UpdaterefVerifyStateChanges = NewFeatureFlag("updateref_verify_state_changes", true) diff --git a/internal/praefect/config/config.go b/internal/praefect/config/config.go index bef7f8d62..60899deb3 100644 --- a/internal/praefect/config/config.go +++ b/internal/praefect/config/config.go @@ -36,9 +36,6 @@ const ( ElectionStrategySQL ElectionStrategy = "sql" // ElectionStrategyPerRepository configures an SQL based strategy that elects different primaries per repository. ElectionStrategyPerRepository ElectionStrategy = "per_repository" - - minimalSyncCheckInterval = time.Minute - minimalSyncRunInterval = time.Minute ) type Failover struct { @@ -100,14 +97,11 @@ type Replication struct { // BatchSize controls how many replication jobs to dequeue and lock // in a single call to the database. BatchSize uint `toml:"batch_size"` - // ParallelStorageProcessingWorkers is a number of workers used to process replication - // events per virtual storage (how many storages would be processed in parallel). - ParallelStorageProcessingWorkers uint `toml:"parallel_storage_processing_workers"` } // DefaultReplicationConfig returns the default values for replication configuration. func DefaultReplicationConfig() Replication { - return Replication{BatchSize: 10, ParallelStorageProcessingWorkers: 1} + return Replication{BatchSize: 10} } // Config is a container for everything found in the TOML config file @@ -128,10 +122,10 @@ type Config struct { DB `toml:"database"` Failover Failover `toml:"failover"` // Keep for legacy reasons: remove after Omnibus has switched - FailoverEnabled bool `toml:"failover_enabled"` - MemoryQueueEnabled bool `toml:"memory_queue_enabled"` - GracefulStopTimeout config.Duration `toml:"graceful_stop_timeout"` - RepositoriesCleanup RepositoriesCleanup `toml:"repositories_cleanup"` + FailoverEnabled bool `toml:"failover_enabled"` + MemoryQueueEnabled bool `toml:"memory_queue_enabled"` + GracefulStopTimeout config.Duration `toml:"graceful_stop_timeout"` + // ForceCreateRepositories will enable force-creation of repositories in the // coordinator when routing repository-scoped mutators. This must never be used // outside of tests. @@ -162,8 +156,7 @@ func FromFile(filePath string) (Config, error) { Replication: DefaultReplicationConfig(), Prometheus: prometheus.DefaultConfig(), // Sets the default Failover, to be overwritten when deserializing the TOML - Failover: Failover{Enabled: true, ElectionStrategy: ElectionStrategyPerRepository}, - RepositoriesCleanup: DefaultRepositoriesCleanup(), + Failover: Failover{Enabled: true, ElectionStrategy: ElectionStrategyPerRepository}, } if err := toml.Unmarshal(b, conf); err != nil { return Config{}, err @@ -256,15 +249,6 @@ func (c *Config) Validate() error { } } - if c.RepositoriesCleanup.RunInterval.Duration() > 0 { - if c.RepositoriesCleanup.CheckInterval.Duration() < minimalSyncCheckInterval { - return fmt.Errorf("repositories_cleanup.check_interval is less then %s, which could lead to a database performance problem", minimalSyncCheckInterval.String()) - } - if c.RepositoriesCleanup.RunInterval.Duration() < minimalSyncRunInterval { - return fmt.Errorf("repositories_cleanup.run_interval is less then %s, which could lead to a database performance problem", minimalSyncRunInterval.String()) - } - } - return nil } @@ -432,24 +416,3 @@ func (db DB) ToPQString(direct bool) string { return strings.Join(fields, " ") } - -// RepositoriesCleanup configures repository synchronisation. -type RepositoriesCleanup struct { - // CheckInterval is a time period used to check if operation should be executed. - // It is recommended to keep it less than run_interval configuration as some - // nodes may be out of service, so they can be stale for too long. - CheckInterval config.Duration `toml:"check_interval"` - // RunInterval: the check runs if the previous operation was done at least RunInterval before. - RunInterval config.Duration `toml:"run_interval"` - // RepositoriesInBatch is the number of repositories to pass as a batch for processing. - RepositoriesInBatch int `toml:"repositories_in_batch"` -} - -// DefaultRepositoriesCleanup contains default configuration values for the RepositoriesCleanup. -func DefaultRepositoriesCleanup() RepositoriesCleanup { - return RepositoriesCleanup{ - CheckInterval: config.Duration(30 * time.Minute), - RunInterval: config.Duration(24 * time.Hour), - RepositoriesInBatch: 16, - } -} diff --git a/internal/praefect/config/config_test.go b/internal/praefect/config/config_test.go index a4ca7e4e8..205f2a57d 100644 --- a/internal/praefect/config/config_test.go +++ b/internal/praefect/config/config_test.go @@ -198,20 +198,6 @@ func TestConfigValidation(t *testing.T) { }, errMsg: `virtual storage "default" has a default replication factor (2) which is higher than the number of storages (1)`, }, - { - desc: "repositories_cleanup minimal duration is too low", - changeConfig: func(cfg *Config) { - cfg.RepositoriesCleanup.CheckInterval = config.Duration(minimalSyncCheckInterval - time.Nanosecond) - }, - errMsg: `repositories_cleanup.check_interval is less then 1m0s, which could lead to a database performance problem`, - }, - { - desc: "repositories_cleanup minimal duration is too low", - changeConfig: func(cfg *Config) { - cfg.RepositoriesCleanup.RunInterval = config.Duration(minimalSyncRunInterval - time.Nanosecond) - }, - errMsg: `repositories_cleanup.run_interval is less then 1m0s, which could lead to a database performance problem`, - }, } for _, tc := range testCases { @@ -223,8 +209,7 @@ func TestConfigValidation(t *testing.T) { {Name: "default", Nodes: vs1Nodes}, {Name: "secondary", Nodes: vs2Nodes}, }, - Failover: Failover{ElectionStrategy: ElectionStrategySQL}, - RepositoriesCleanup: DefaultRepositoriesCleanup(), + Failover: Failover{ElectionStrategy: ElectionStrategySQL}, } tc.changeConfig(&config) @@ -317,7 +302,7 @@ func TestConfigParsing(t *testing.T) { SchedulingInterval: config.Duration(time.Minute), HistogramBuckets: []float64{1, 2, 3, 4, 5}, }, - Replication: Replication{BatchSize: 1, ParallelStorageProcessingWorkers: 2}, + Replication: Replication{BatchSize: 1}, Failover: Failover{ Enabled: true, ElectionStrategy: ElectionStrategyPerRepository, @@ -327,11 +312,6 @@ func TestConfigParsing(t *testing.T) { BootstrapInterval: config.Duration(1 * time.Second), MonitorInterval: config.Duration(3 * time.Second), }, - RepositoriesCleanup: RepositoriesCleanup{ - CheckInterval: config.Duration(time.Second), - RunInterval: config.Duration(3 * time.Second), - RepositoriesInBatch: 10, - }, }, }, { @@ -344,18 +324,13 @@ func TestConfigParsing(t *testing.T) { HistogramBuckets: []float64{1, 2, 3, 4, 5}, }, Prometheus: prometheus.DefaultConfig(), - Replication: Replication{BatchSize: 1, ParallelStorageProcessingWorkers: 2}, + Replication: Replication{BatchSize: 1}, Failover: Failover{ Enabled: false, ElectionStrategy: "local", BootstrapInterval: config.Duration(5 * time.Second), MonitorInterval: config.Duration(10 * time.Second), }, - RepositoriesCleanup: RepositoriesCleanup{ - CheckInterval: config.Duration(time.Second), - RunInterval: config.Duration(4 * time.Second), - RepositoriesInBatch: 11, - }, }, }, { @@ -372,11 +347,6 @@ func TestConfigParsing(t *testing.T) { BootstrapInterval: config.Duration(time.Second), MonitorInterval: config.Duration(3 * time.Second), }, - RepositoriesCleanup: RepositoriesCleanup{ - CheckInterval: config.Duration(30 * time.Minute), - RunInterval: config.Duration(24 * time.Hour), - RepositoriesInBatch: 16, - }, }, }, { diff --git a/internal/praefect/config/testdata/config.overwritedefaults.toml b/internal/praefect/config/testdata/config.overwritedefaults.toml index 869597f01..9b204b1fc 100644 --- a/internal/praefect/config/testdata/config.overwritedefaults.toml +++ b/internal/praefect/config/testdata/config.overwritedefaults.toml @@ -1,6 +1,5 @@ [replication] batch_size = 1 -parallel_storage_processing_workers = 2 [reconciliation] scheduling_interval = 0 @@ -12,8 +11,3 @@ election_strategy = "local" read_only_after_failover = false bootstrap_interval = "5s" monitor_interval = "10s" - -[repositories_cleanup] -check_interval = "1s" -run_interval = "4s" -repositories_in_batch = 11 diff --git a/internal/praefect/config/testdata/config.toml b/internal/praefect/config/testdata/config.toml index 839b807b0..09175ed50 100644 --- a/internal/praefect/config/testdata/config.toml +++ b/internal/praefect/config/testdata/config.toml @@ -8,7 +8,6 @@ graceful_stop_timeout = "30s" [replication] batch_size = 1 -parallel_storage_processing_workers = 2 [reconciliation] scheduling_interval = "1m" @@ -72,8 +71,3 @@ sslrootcert = "/path/to/sp/root-cert" error_threshold_window = "20s" write_error_threshold_count = 1500 read_error_threshold_count = 100 - -[repositories_cleanup] -check_interval = "1s" -run_interval = "3s" -repositories_in_batch = 10 diff --git a/internal/praefect/coordinator.go b/internal/praefect/coordinator.go index 0cfc43782..aea341dd0 100644 --- a/internal/praefect/coordinator.go +++ b/internal/praefect/coordinator.go @@ -73,7 +73,6 @@ var transactionRPCs = map[string]transactionsCondition{ "/gitaly.RepositoryService/CreateRepositoryFromBundle": transactionsEnabled, "/gitaly.RepositoryService/CreateRepositoryFromSnapshot": transactionsEnabled, "/gitaly.RepositoryService/CreateRepositoryFromURL": transactionsEnabled, - "/gitaly.RepositoryService/FetchBundle": transactionsEnabled, "/gitaly.RepositoryService/FetchRemote": transactionsEnabled, "/gitaly.RepositoryService/FetchSourceBranch": transactionsEnabled, "/gitaly.RepositoryService/RemoveRepository": transactionsEnabled, @@ -331,27 +330,20 @@ func (c *Coordinator) directRepositoryScopedMessage(ctx context.Context, call gr var ps *proxy.StreamParameters if c.forceCreateRepositories { - replicationType, _, err := getReplicationDetails(call.fullMethodName, call.msg) + // This is a hack for the tests: during execution of the gitaly tests under praefect proxy + // the repositories are created directly on the filesystem. There is no call for the + // CreateRepository that creates records in the database that is why we do it artificially + // before redirecting the calls. + id, err := c.rs.ReserveRepositoryID(ctx, call.targetRepo.StorageName, call.targetRepo.RelativePath) if err != nil { - return nil, err - } - - if replicationType != datastore.CreateRepo { - // This is a hack for the tests: during execution of the gitaly tests under praefect proxy - // the repositories are created directly on the filesystem. There is no call for the - // CreateRepository that creates records in the database that is why we do it artificially - // before redirecting the calls. - id, err := c.rs.ReserveRepositoryID(ctx, call.targetRepo.StorageName, call.targetRepo.RelativePath) - if err != nil { - if !errors.Is(err, commonerr.ErrRepositoryAlreadyExists) { + if !errors.Is(err, commonerr.ErrRepositoryAlreadyExists) { + return nil, err + } + } else { + if err := c.rs.CreateRepository(ctx, id, call.targetRepo.StorageName, call.targetRepo.RelativePath, call.targetRepo.StorageName, nil, nil, true, true); err != nil { + if !errors.As(err, &datastore.RepositoryExistsError{}) { return nil, err } - } else { - if err := c.rs.CreateRepository(ctx, id, call.targetRepo.StorageName, call.targetRepo.RelativePath, call.targetRepo.StorageName, nil, nil, true, true); err != nil { - if !errors.As(err, &datastore.RepositoryExistsError{}) { - return nil, err - } - } } } } diff --git a/internal/praefect/coordinator_test.go b/internal/praefect/coordinator_test.go index 9df1dcf76..35e4b54a5 100644 --- a/internal/praefect/coordinator_test.go +++ b/internal/praefect/coordinator_test.go @@ -157,7 +157,14 @@ func TestStreamDirectorMutator(t *testing.T) { }, }, } - db := glsql.NewDB(t) + + var replEventWait sync.WaitGroup + + queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(glsql.NewDB(t))) + queueInterceptor.OnEnqueue(func(ctx context.Context, event datastore.ReplicationEvent, queue datastore.ReplicationEventQueue) (datastore.ReplicationEvent, error) { + defer replEventWait.Done() + return queue.Enqueue(ctx, event) + }) targetRepo := gitalypb.Repository{ StorageName: "praefect", @@ -188,7 +195,7 @@ func TestStreamDirectorMutator(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - tx := db.Begin(t) + tx := glsql.NewDB(t).Begin(t) defer tx.Rollback(t) rs := datastore.NewPostgresRepositoryStore(tx, conf.StorageNames()) @@ -198,11 +205,6 @@ func TestStreamDirectorMutator(t *testing.T) { } testhelper.SetHealthyNodes(t, ctx, tx, map[string]map[string][]string{"praefect": conf.StorageNames()}) - queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(db)) - queueInterceptor.OnEnqueue(func(ctx context.Context, event datastore.ReplicationEvent, queue datastore.ReplicationEventQueue) (datastore.ReplicationEvent, error) { - assert.True(t, len(queueInterceptor.GetEnqueued()) < 2, "expected only one event to be created") - return queue.Enqueue(ctx, event) - }) coordinator := NewCoordinator( queueInterceptor, @@ -252,14 +254,11 @@ func TestStreamDirectorMutator(t *testing.T) { require.NoError(t, err) require.Equal(t, "praefect-internal-1", rewrittenTargetRepo.GetStorageName(), "stream director should have rewritten the storage name") + replEventWait.Add(1) // expected only one event to be created // this call creates new events in the queue and simulates usual flow of the update operation require.NoError(t, streamParams.RequestFinalizer()) - // wait until event persisted (async operation) - require.NoError(t, queueInterceptor.Wait(time.Minute, func(i *datastore.ReplicationEventQueueInterceptor) bool { - return len(i.GetEnqueuedResult()) == 1 - })) - + replEventWait.Wait() // wait until event persisted (async operation) events, err := queueInterceptor.Dequeue(ctx, "praefect", "praefect-internal-2", 10) require.NoError(t, err) require.Len(t, events, 1) @@ -833,6 +832,13 @@ func TestStreamDirector_repo_creation(t *testing.T) { }, } + var replEventWait sync.WaitGroup + queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(db)) + queueInterceptor.OnEnqueue(func(ctx context.Context, event datastore.ReplicationEvent, queue datastore.ReplicationEventQueue) (datastore.ReplicationEvent, error) { + defer replEventWait.Done() + return queue.Enqueue(ctx, event) + }) + rewrittenStorage := primaryNode.Storage targetRepo := gitalypb.Repository{ StorageName: "praefect", @@ -920,7 +926,6 @@ func TestStreamDirector_repo_creation(t *testing.T) { } txMgr := transactions.NewManager(conf) - queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(db)) coordinator := NewCoordinator( queueInterceptor, @@ -962,6 +967,8 @@ func TestStreamDirector_repo_creation(t *testing.T) { require.NoError(t, err) require.Equal(t, rewrittenStorage, rewrittenTargetRepo.GetStorageName(), "stream director should have rewritten the storage name") + replEventWait.Add(1) + vote := voting.VoteFromData([]byte{}) require.NoError(t, txMgr.VoteTransaction(ctx, 1, "praefect-internal-1", vote)) require.NoError(t, txMgr.VoteTransaction(ctx, 1, "praefect-internal-2", vote)) @@ -970,10 +977,7 @@ func TestStreamDirector_repo_creation(t *testing.T) { err = streamParams.RequestFinalizer() require.NoError(t, err) - // wait until event persisted (async operation) - require.NoError(t, queueInterceptor.Wait(time.Minute, func(i *datastore.ReplicationEventQueueInterceptor) bool { - return len(i.GetEnqueuedResult()) == 1 - })) + replEventWait.Wait() // wait until event persisted (async operation) var expectedEvents, actualEvents []datastore.ReplicationEvent for _, target := range []string{unhealthySecondaryNode.Storage} { @@ -1059,11 +1063,14 @@ func TestAbsentCorrelationID(t *testing.T) { }, } + var replEventWait sync.WaitGroup + queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(glsql.NewDB(t))) queueInterceptor.OnEnqueue(func(ctx context.Context, event datastore.ReplicationEvent, queue datastore.ReplicationEventQueue) (datastore.ReplicationEvent, error) { - assert.True(t, len(queueInterceptor.GetEnqueued()) < 2, "expected only one event to be created") + defer replEventWait.Done() return queue.Enqueue(ctx, event) }) + targetRepo := gitalypb.Repository{ StorageName: "praefect", RelativePath: "/path/to/hashed/storage", @@ -1102,12 +1109,11 @@ func TestAbsentCorrelationID(t *testing.T) { require.NoError(t, err) require.Equal(t, primaryAddress, streamParams.Primary().Conn.Target()) + replEventWait.Add(1) // expected only one event to be created // must be run as it adds replication events to the queue require.NoError(t, streamParams.RequestFinalizer()) - require.NoError(t, queueInterceptor.Wait(time.Minute, func(i *datastore.ReplicationEventQueueInterceptor) bool { - return len(i.GetEnqueuedResult()) == 1 - })) + replEventWait.Wait() // wait until event persisted (async operation) jobs, err := queueInterceptor.Dequeue(ctx, conf.VirtualStorages[0].Name, conf.VirtualStorages[0].Nodes[1].Storage, 1) require.NoError(t, err) require.Len(t, jobs, 1) diff --git a/internal/praefect/datastore/glsql/postgres_test.go b/internal/praefect/datastore/glsql/postgres_test.go index b91db2b58..5616274bd 100644 --- a/internal/praefect/datastore/glsql/postgres_test.go +++ b/internal/praefect/datastore/glsql/postgres_test.go @@ -1,13 +1,28 @@ package glsql import ( + "os" + "strconv" "testing" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" ) func TestOpenDB(t *testing.T) { - dbCfg := GetDBConfig(t, "postgres") + getEnvFromGDK(t) + + dbCfg := config.DB{ + Host: os.Getenv("PGHOST"), + Port: func() int { + pgPort := os.Getenv("PGPORT") + port, err := strconv.Atoi(pgPort) + require.NoError(t, err, "failed to parse PGPORT %q", pgPort) + return port + }(), + DBName: "postgres", + SSLMode: "disable", + } t.Run("failed to ping because of incorrect config", func(t *testing.T) { badCfg := dbCfg diff --git a/internal/praefect/datastore/glsql/testing.go b/internal/praefect/datastore/glsql/testing.go index 5181bf9c7..bb9430b1f 100644 --- a/internal/praefect/datastore/glsql/testing.go +++ b/internal/praefect/datastore/glsql/testing.go @@ -8,7 +8,6 @@ import ( "os/exec" "strconv" "strings" - "sync" "testing" "github.com/google/uuid" @@ -98,8 +97,6 @@ func (db DB) TruncateAll(t testing.TB) { "storage_repositories", "repositories", "virtual_storages", - "repository_assignments", - "storage_cleanups", ) } @@ -134,34 +131,39 @@ func NewDB(t testing.TB) DB { // GetDBConfig returns the database configuration determined by // environment variables. See NewDB() for the list of variables. func GetDBConfig(t testing.TB, database string) config.DB { - env := getDatabaseEnvironment(t) + getEnvFromGDK(t) - require.Contains(t, env, "PGHOST", "PGHOST env var expected to be provided to connect to Postgres database") - require.Contains(t, env, "PGPORT", "PGHOST env var expected to be provided to connect to Postgres database") + host, hostFound := os.LookupEnv("PGHOST") + require.True(t, hostFound, "PGHOST env var expected to be provided to connect to Postgres database") - portNumber, err := strconv.Atoi(env["PGPORT"]) - require.NoError(t, err, "PGPORT must be a port number of the Postgres database listens for incoming connections") + port, portFound := os.LookupEnv("PGPORT") + require.True(t, portFound, "PGPORT env var expected to be provided to connect to Postgres database") + portNumber, pErr := strconv.Atoi(port) + require.NoError(t, pErr, "PGPORT must be a port number of the Postgres database listens for incoming connections") // connect to 'postgres' database first to re-create testing database from scratch conf := config.DB{ - Host: env["PGHOST"], + Host: host, Port: portNumber, DBName: database, SSLMode: "disable", - User: env["PGUSER"], + User: os.Getenv("PGUSER"), SessionPooled: config.DBConnection{ - Host: env["PGHOST"], + Host: host, Port: portNumber, }, } - if bouncerHost, ok := env["PGHOST_PGBOUNCER"]; ok { + bouncerHost, bouncerHostFound := os.LookupEnv("PGHOST_PGBOUNCER") + if bouncerHostFound { conf.Host = bouncerHost } - if bouncerPort, ok := env["PGPORT_PGBOUNCER"]; ok { - bouncerPortNumber, err := strconv.Atoi(bouncerPort) - require.NoError(t, err, "PGPORT_PGBOUNCER must be a port number of the PgBouncer") + bouncerPort, bouncerPortFound := os.LookupEnv("PGPORT_PGBOUNCER") + if bouncerPortFound { + bouncerPortNumber, pErr := strconv.Atoi(bouncerPort) + require.NoError(t, pErr, "PGPORT_PGBOUNCER must be a port number of the PgBouncer") + conf.Port = bouncerPortNumber } @@ -285,48 +287,25 @@ func scanSingleBool(t testing.TB, db *sql.DB, query string, args ...interface{}) return flag } -var ( - // Running `gdk env` takes about 250ms on my system and is thus comparatively slow. When - // running with Praefect as proxy, this time adds up and may thus slow down tests by quite a - // margin. We thus amortize these costs by only running it once. - databaseEnvOnce sync.Once - databaseEnv map[string]string -) +func getEnvFromGDK(t testing.TB) { + gdkEnv, err := exec.Command("gdk", "env").Output() + if err != nil { + // Assume we are not in a GDK setup; this is not an error so just return. + return + } -func getDatabaseEnvironment(t testing.TB) map[string]string { - databaseEnvOnce.Do(func() { - envvars := map[string]string{} - - // We only process output if `gdk env` returned success. If it didn't, we simply assume that - // we are not running in a GDK environment and will try to extract variables from the - // environment instead. - if output, err := exec.Command("gdk", "env").Output(); err == nil { - for _, line := range strings.Split(string(output), "\n") { - const prefix = "export " - if !strings.HasPrefix(line, prefix) { - continue - } - - split := strings.SplitN(strings.TrimPrefix(line, prefix), "=", 2) - if len(split) != 2 { - continue - } - - envvars[split[0]] = split[1] - } + for _, line := range strings.Split(string(gdkEnv), "\n") { + const prefix = "export " + if !strings.HasPrefix(line, prefix) { + continue } - for _, key := range []string{"PGHOST", "PGPORT", "PGUSER", "PGHOST_PGBOUNCER", "PGPORT_PGBOUNCER"} { - if _, ok := envvars[key]; !ok { - value, ok := os.LookupEnv(key) - if ok { - envvars[key] = value - } - } + split := strings.SplitN(strings.TrimPrefix(line, prefix), "=", 2) + if len(split) != 2 { + continue } + key, value := split[0], split[1] - databaseEnv = envvars - }) - - return databaseEnv + require.NoError(t, os.Setenv(key, value), "set env var %v", key) + } } diff --git a/internal/praefect/datastore/memory.go b/internal/praefect/datastore/memory.go index a57507ffe..9c8139d48 100644 --- a/internal/praefect/datastore/memory.go +++ b/internal/praefect/datastore/memory.go @@ -216,204 +216,87 @@ func (s *memoryReplicationEventQueue) defineDest(event ReplicationEvent) eventDe return eventDestination{virtual: event.Job.VirtualStorage, storage: event.Job.TargetNodeStorage, relativePath: event.Job.RelativePath} } -// NewReplicationEventQueueInterceptor returns interception over `ReplicationEventQueue` interface. -func NewReplicationEventQueueInterceptor(queue ReplicationEventQueue) *ReplicationEventQueueInterceptor { - return &ReplicationEventQueueInterceptor{ - ReplicationEventQueue: queue, - } -} - -// DequeParams is the list of parameters used for Dequeue method call. -type DequeParams struct { - VirtualStorage, NodeStorage string - Count int +// ReplicationEventQueueInterceptor allows to register interceptors for `ReplicationEventQueue` interface. +type ReplicationEventQueueInterceptor interface { + // ReplicationEventQueue actual implementation. + ReplicationEventQueue + // OnEnqueue allows to set action that would be executed each time when `Enqueue` method called. + OnEnqueue(func(context.Context, ReplicationEvent, ReplicationEventQueue) (ReplicationEvent, error)) + // OnDequeue allows to set action that would be executed each time when `Dequeue` method called. + OnDequeue(func(context.Context, string, string, int, ReplicationEventQueue) ([]ReplicationEvent, error)) + // OnAcknowledge allows to set action that would be executed each time when `Acknowledge` method called. + OnAcknowledge(func(context.Context, JobState, []uint64, ReplicationEventQueue) ([]uint64, error)) + // OnStartHealthUpdate allows to set action that would be executed each time when `StartHealthUpdate` method called. + OnStartHealthUpdate(func(context.Context, <-chan time.Time, []ReplicationEvent) error) + // OnAcknowledgeStale allows to set action that would be executed each time when `AcknowledgeStale` method called. + OnAcknowledgeStale(func(context.Context, time.Duration) error) } -// AcknowledgeParams is the list of parameters used for Acknowledge method call. -type AcknowledgeParams struct { - State JobState - IDs []uint64 +// NewReplicationEventQueueInterceptor returns interception over `ReplicationEventQueue` interface. +func NewReplicationEventQueueInterceptor(queue ReplicationEventQueue) ReplicationEventQueueInterceptor { + return &replicationEventQueueInterceptor{ReplicationEventQueue: queue} } -// ReplicationEventQueueInterceptor allows to register interceptors for `ReplicationEventQueue` interface. -// It also provides additional methods to get info about incoming and outgoing data from the underling -// queue. -// NOTE: it should be used for testing purposes only as it persists data in memory and doesn't clean it up. -type ReplicationEventQueueInterceptor struct { - mtx sync.Mutex +type replicationEventQueueInterceptor struct { ReplicationEventQueue onEnqueue func(context.Context, ReplicationEvent, ReplicationEventQueue) (ReplicationEvent, error) onDequeue func(context.Context, string, string, int, ReplicationEventQueue) ([]ReplicationEvent, error) onAcknowledge func(context.Context, JobState, []uint64, ReplicationEventQueue) ([]uint64, error) onStartHealthUpdate func(context.Context, <-chan time.Time, []ReplicationEvent) error onAcknowledgeStale func(context.Context, time.Duration) error - - enqueue []ReplicationEvent - enqueueResult []ReplicationEvent - dequeue []DequeParams - dequeueResult [][]ReplicationEvent - acknowledge []AcknowledgeParams - acknowledgeResult [][]uint64 } -// OnEnqueue allows to set action that would be executed each time when `Enqueue` method called. -func (i *ReplicationEventQueueInterceptor) OnEnqueue(action func(context.Context, ReplicationEvent, ReplicationEventQueue) (ReplicationEvent, error)) { +func (i *replicationEventQueueInterceptor) OnEnqueue(action func(context.Context, ReplicationEvent, ReplicationEventQueue) (ReplicationEvent, error)) { i.onEnqueue = action } -// OnDequeue allows to set action that would be executed each time when `Dequeue` method called. -func (i *ReplicationEventQueueInterceptor) OnDequeue(action func(context.Context, string, string, int, ReplicationEventQueue) ([]ReplicationEvent, error)) { +func (i *replicationEventQueueInterceptor) OnDequeue(action func(context.Context, string, string, int, ReplicationEventQueue) ([]ReplicationEvent, error)) { i.onDequeue = action } -// OnAcknowledge allows to set action that would be executed each time when `Acknowledge` method called. -func (i *ReplicationEventQueueInterceptor) OnAcknowledge(action func(context.Context, JobState, []uint64, ReplicationEventQueue) ([]uint64, error)) { +func (i *replicationEventQueueInterceptor) OnAcknowledge(action func(context.Context, JobState, []uint64, ReplicationEventQueue) ([]uint64, error)) { i.onAcknowledge = action } -// OnStartHealthUpdate allows to set action that would be executed each time when `StartHealthUpdate` method called. -func (i *ReplicationEventQueueInterceptor) OnStartHealthUpdate(action func(context.Context, <-chan time.Time, []ReplicationEvent) error) { +func (i *replicationEventQueueInterceptor) OnStartHealthUpdate(action func(context.Context, <-chan time.Time, []ReplicationEvent) error) { i.onStartHealthUpdate = action } -// OnAcknowledgeStale allows to set action that would be executed each time when `AcknowledgeStale` method called. -func (i *ReplicationEventQueueInterceptor) OnAcknowledgeStale(action func(context.Context, time.Duration) error) { +func (i *replicationEventQueueInterceptor) OnAcknowledgeStale(action func(context.Context, time.Duration) error) { i.onAcknowledgeStale = action } -// Enqueue intercepts call to the Enqueue method of the underling implementation or a call back. -// It populates storage of incoming and outgoing parameters before and after method call. -func (i *ReplicationEventQueueInterceptor) Enqueue(ctx context.Context, event ReplicationEvent) (ReplicationEvent, error) { - i.mtx.Lock() - i.enqueue = append(i.enqueue, event) - i.mtx.Unlock() - - var enqEvent ReplicationEvent - var err error - +func (i *replicationEventQueueInterceptor) Enqueue(ctx context.Context, event ReplicationEvent) (ReplicationEvent, error) { if i.onEnqueue != nil { - enqEvent, err = i.onEnqueue(ctx, event, i.ReplicationEventQueue) - } else { - enqEvent, err = i.ReplicationEventQueue.Enqueue(ctx, event) + return i.onEnqueue(ctx, event, i.ReplicationEventQueue) } - - i.mtx.Lock() - i.enqueueResult = append(i.enqueueResult, enqEvent) - i.mtx.Unlock() - return enqEvent, err + return i.ReplicationEventQueue.Enqueue(ctx, event) } -// Dequeue intercepts call to the Dequeue method of the underling implementation or a call back. -// It populates storage of incoming and outgoing parameters before and after method call. -func (i *ReplicationEventQueueInterceptor) Dequeue(ctx context.Context, virtualStorage, nodeStorage string, count int) ([]ReplicationEvent, error) { - i.mtx.Lock() - i.dequeue = append(i.dequeue, DequeParams{VirtualStorage: virtualStorage, NodeStorage: nodeStorage, Count: count}) - i.mtx.Unlock() - - var deqEvents []ReplicationEvent - var err error - +func (i *replicationEventQueueInterceptor) Dequeue(ctx context.Context, virtualStorage, nodeStorage string, count int) ([]ReplicationEvent, error) { if i.onDequeue != nil { - deqEvents, err = i.onDequeue(ctx, virtualStorage, nodeStorage, count, i.ReplicationEventQueue) - } else { - deqEvents, err = i.ReplicationEventQueue.Dequeue(ctx, virtualStorage, nodeStorage, count) + return i.onDequeue(ctx, virtualStorage, nodeStorage, count, i.ReplicationEventQueue) } - - i.mtx.Lock() - i.dequeueResult = append(i.dequeueResult, deqEvents) - i.mtx.Unlock() - return deqEvents, err + return i.ReplicationEventQueue.Dequeue(ctx, virtualStorage, nodeStorage, count) } -// Acknowledge intercepts call to the Acknowledge method of the underling implementation or a call back. -// It populates storage of incoming and outgoing parameters before and after method call. -func (i *ReplicationEventQueueInterceptor) Acknowledge(ctx context.Context, state JobState, ids []uint64) ([]uint64, error) { - i.mtx.Lock() - i.acknowledge = append(i.acknowledge, AcknowledgeParams{State: state, IDs: ids}) - i.mtx.Unlock() - - var ackIDs []uint64 - var err error - +func (i *replicationEventQueueInterceptor) Acknowledge(ctx context.Context, state JobState, ids []uint64) ([]uint64, error) { if i.onAcknowledge != nil { - ackIDs, err = i.onAcknowledge(ctx, state, ids, i.ReplicationEventQueue) - } else { - ackIDs, err = i.ReplicationEventQueue.Acknowledge(ctx, state, ids) + return i.onAcknowledge(ctx, state, ids, i.ReplicationEventQueue) } - - i.mtx.Lock() - i.acknowledgeResult = append(i.acknowledgeResult, ackIDs) - i.mtx.Unlock() - return ackIDs, err + return i.ReplicationEventQueue.Acknowledge(ctx, state, ids) } -// StartHealthUpdate intercepts call to the StartHealthUpdate method of the underling implementation or a call back. -func (i *ReplicationEventQueueInterceptor) StartHealthUpdate(ctx context.Context, trigger <-chan time.Time, events []ReplicationEvent) error { +func (i *replicationEventQueueInterceptor) StartHealthUpdate(ctx context.Context, trigger <-chan time.Time, events []ReplicationEvent) error { if i.onStartHealthUpdate != nil { return i.onStartHealthUpdate(ctx, trigger, events) } return i.ReplicationEventQueue.StartHealthUpdate(ctx, trigger, events) } -// AcknowledgeStale intercepts call to the AcknowledgeStale method of the underling implementation or a call back. -func (i *ReplicationEventQueueInterceptor) AcknowledgeStale(ctx context.Context, staleAfter time.Duration) error { +func (i *replicationEventQueueInterceptor) AcknowledgeStale(ctx context.Context, staleAfter time.Duration) error { if i.onAcknowledgeStale != nil { return i.onAcknowledgeStale(ctx, staleAfter) } return i.ReplicationEventQueue.AcknowledgeStale(ctx, staleAfter) } - -// GetEnqueued returns a list of events used for Enqueue method or a call-back invocation. -func (i *ReplicationEventQueueInterceptor) GetEnqueued() []ReplicationEvent { - i.mtx.Lock() - defer i.mtx.Unlock() - return i.enqueue -} - -// GetEnqueuedResult returns a list of events returned by Enqueue method or a call-back invocation. -func (i *ReplicationEventQueueInterceptor) GetEnqueuedResult() []ReplicationEvent { - i.mtx.Lock() - defer i.mtx.Unlock() - return i.enqueueResult -} - -// GetDequeued returns a list of parameters used for Dequeue method or a call-back invocation. -func (i *ReplicationEventQueueInterceptor) GetDequeued() []DequeParams { - i.mtx.Lock() - defer i.mtx.Unlock() - return i.dequeue -} - -// GetDequeuedResult returns a list of events returned after Dequeue method or a call-back invocation. -func (i *ReplicationEventQueueInterceptor) GetDequeuedResult() [][]ReplicationEvent { - i.mtx.Lock() - defer i.mtx.Unlock() - return i.dequeueResult -} - -// GetAcknowledge returns a list of parameters used for Acknowledge method or a call-back invocation. -func (i *ReplicationEventQueueInterceptor) GetAcknowledge() []AcknowledgeParams { - i.mtx.Lock() - defer i.mtx.Unlock() - return i.acknowledge -} - -// GetAcknowledgeResult returns a list of results returned after Acknowledge method or a call-back invocation. -func (i *ReplicationEventQueueInterceptor) GetAcknowledgeResult() [][]uint64 { - i.mtx.Lock() - defer i.mtx.Unlock() - return i.acknowledgeResult -} - -// Wait checks the condition in a loop with await until it returns true or deadline is exceeded. -// The error is returned only in case the deadline is exceeded. -func (i *ReplicationEventQueueInterceptor) Wait(deadline time.Duration, condition func(i *ReplicationEventQueueInterceptor) bool) error { - dead := time.Now().Add(deadline) - for !condition(i) { - if dead.Before(time.Now()) { - return context.DeadlineExceeded - } - time.Sleep(time.Millisecond * 100) - } - return nil -} diff --git a/internal/praefect/datastore/migrations/20210906145021_link_repository_id.go b/internal/praefect/datastore/migrations/20210906145021_link_repository_id.go deleted file mode 100644 index 08c9663bd..000000000 --- a/internal/praefect/datastore/migrations/20210906145021_link_repository_id.go +++ /dev/null @@ -1,28 +0,0 @@ -package migrations - -import migrate "github.com/rubenv/sql-migrate" - -func init() { - m := &migrate.Migration{ - Id: "20210906145021_link_repository_id", - Up: []string{ - ` -UPDATE storage_repositories -SET repository_id = repositories.repository_id -FROM repositories -WHERE storage_repositories.virtual_storage = repositories.virtual_storage -AND storage_repositories.relative_path = repositories.relative_path - `, - ` -UPDATE repository_assignments -SET repository_id = repositories.repository_id -FROM repositories -WHERE repository_assignments.virtual_storage = repositories.virtual_storage -AND repository_assignments.relative_path = repositories.relative_path - `, - }, - Down: []string{}, - } - - allMigrations = append(allMigrations, m) -} diff --git a/internal/praefect/datastore/migrations/20210914115710_storage_cleanups_table.go b/internal/praefect/datastore/migrations/20210914115710_storage_cleanups_table.go deleted file mode 100644 index 17d68cade..000000000 --- a/internal/praefect/datastore/migrations/20210914115710_storage_cleanups_table.go +++ /dev/null @@ -1,23 +0,0 @@ -package migrations - -import migrate "github.com/rubenv/sql-migrate" - -func init() { - m := &migrate.Migration{ - Id: "20210914115710_storage_cleanups_table", - Up: []string{ - `CREATE TABLE storage_cleanups ( - virtual_storage TEXT NOT NULL, - storage TEXT NOT NULL, - last_run TIMESTAMP WITHOUT TIME ZONE, - triggered_at TIMESTAMP WITHOUT TIME ZONE, - PRIMARY KEY (virtual_storage, storage) - )`, - }, - Down: []string{ - `DROP TABLE storage_cleanups`, - }, - } - - allMigrations = append(allMigrations, m) -} diff --git a/internal/praefect/datastore/migrations/20210921131816_backfill_replica_path.go b/internal/praefect/datastore/migrations/20210921131816_backfill_replica_path.go deleted file mode 100644 index e18ea3d4c..000000000 --- a/internal/praefect/datastore/migrations/20210921131816_backfill_replica_path.go +++ /dev/null @@ -1,13 +0,0 @@ -package migrations - -import migrate "github.com/rubenv/sql-migrate" - -func init() { - m := &migrate.Migration{ - Id: "20210921131816_backfill_replica_path", - Up: []string{"UPDATE repositories SET replica_path = relative_path"}, - Down: []string{}, - } - - allMigrations = append(allMigrations, m) -} diff --git a/internal/praefect/datastore/migrations/20210922091614_repository_id_primary_key_indexes.go b/internal/praefect/datastore/migrations/20210922091614_repository_id_primary_key_indexes.go deleted file mode 100644 index e5441ff94..000000000 --- a/internal/praefect/datastore/migrations/20210922091614_repository_id_primary_key_indexes.go +++ /dev/null @@ -1,19 +0,0 @@ -package migrations - -import migrate "github.com/rubenv/sql-migrate" - -func init() { - m := &migrate.Migration{ - Id: "20210922091614_repository_id_primary_key_indexes", - Up: []string{ - "CREATE UNIQUE INDEX repository_assignments_new_pkey ON repository_assignments (repository_id, storage)", - "CREATE UNIQUE INDEX storage_repositories_new_pkey ON storage_repositories (repository_id, storage)", - }, - Down: []string{ - "DROP INDEX repository_assignments_new_pkey", - "DROP INDEX storage_repositories_new_pkey", - }, - } - - allMigrations = append(allMigrations, m) -} diff --git a/internal/praefect/datastore/migrations/20210927083631_repository_path_index.go b/internal/praefect/datastore/migrations/20210927083631_repository_path_index.go deleted file mode 100644 index cc7022738..000000000 --- a/internal/praefect/datastore/migrations/20210927083631_repository_path_index.go +++ /dev/null @@ -1,19 +0,0 @@ -package migrations - -import migrate "github.com/rubenv/sql-migrate" - -func init() { - m := &migrate.Migration{ - Id: "20210927083631_repository_path_index", - Up: []string{ - `CREATE INDEX CONCURRENTLY repository_replica_path_index - ON repositories (replica_path, virtual_storage)`, - }, - DisableTransactionUp: true, - Down: []string{ - `DROP INDEX repository_replica_path_index`, - }, - } - - allMigrations = append(allMigrations, m) -} diff --git a/internal/praefect/datastore/storage_cleanup.go b/internal/praefect/datastore/storage_cleanup.go deleted file mode 100644 index adc43401b..000000000 --- a/internal/praefect/datastore/storage_cleanup.go +++ /dev/null @@ -1,182 +0,0 @@ -package datastore - -import ( - "context" - "database/sql" - "errors" - "fmt" - "time" - - "github.com/lib/pq" - "gitlab.com/gitlab-org/gitaly/v14/internal/helper" -) - -// RepositoryClusterPath identifies location of the repository in the cluster. -type RepositoryClusterPath struct { - ClusterPath - // RelativeReplicaPath relative path to the repository on the disk. - RelativeReplicaPath string -} - -// NewRepositoryClusterPath initializes and returns RepositoryClusterPath. -func NewRepositoryClusterPath(virtualStorage, storage, relativePath string) RepositoryClusterPath { - return RepositoryClusterPath{ - ClusterPath: ClusterPath{ - VirtualStorage: virtualStorage, - Storage: storage, - }, - RelativeReplicaPath: relativePath, - } -} - -// ClusterPath represents path on the cluster to the storage. -type ClusterPath struct { - // VirtualStorage is the name of the virtual storage. - VirtualStorage string - // Storage is the name of the gitaly storage. - Storage string -} - -// NewStorageCleanup initialises and returns a new instance of the StorageCleanup. -func NewStorageCleanup(db *sql.DB) *StorageCleanup { - return &StorageCleanup{db: db} -} - -// StorageCleanup provides methods on the database for the repository cleanup operation. -type StorageCleanup struct { - db *sql.DB -} - -// Populate adds storage to the set, so it can be acquired afterwards. -func (ss *StorageCleanup) Populate(ctx context.Context, virtualStorage, storage string) error { - if _, err := ss.db.ExecContext( - ctx, - ` - INSERT INTO storage_cleanups (virtual_storage, storage) VALUES ($1, $2) - ON CONFLICT (virtual_storage, storage) DO NOTHING`, - virtualStorage, storage, - ); err != nil { - return fmt.Errorf("exec: %w", err) - } - return nil -} - -// AcquireNextStorage picks up the next storage for processing. -// Once acquired no other call to the same method will return the same storage, so it -// works as exclusive lock on that entry. -// Once processing is done the returned function needs to be called to release -// acquired storage. It updates last_run column of the entry on execution. -func (ss *StorageCleanup) AcquireNextStorage(ctx context.Context, inactive, updatePeriod time.Duration) (*ClusterPath, func() error, error) { - var entry ClusterPath - if err := ss.db.QueryRowContext( - ctx, - `UPDATE storage_cleanups - SET triggered_at = NOW() - WHERE (virtual_storage, storage) IN ( - SELECT virtual_storage, storage - FROM storage_cleanups - WHERE - COALESCE(last_run, TO_TIMESTAMP(0)) <= (NOW() - INTERVAL '1 MILLISECOND' * $1) - AND COALESCE(triggered_at, TO_TIMESTAMP(0)) <= (NOW() - INTERVAL '1 MILLISECOND' * $2) - ORDER BY last_run NULLS FIRST, virtual_storage, storage - LIMIT 1 - FOR UPDATE SKIP LOCKED - ) - RETURNING virtual_storage, storage`, - inactive.Milliseconds(), updatePeriod.Milliseconds(), - ).Scan(&entry.VirtualStorage, &entry.Storage); err != nil { - if !errors.Is(err, sql.ErrNoRows) { - return nil, nil, fmt.Errorf("scan: %w", err) - } - return nil, func() error { return nil }, nil - } - - stop := make(chan struct{}, 1) - stopped := make(chan struct{}) - go func() { - trigger := helper.NewTimerTicker(updatePeriod - 100*time.Millisecond) - defer func() { - trigger.Stop() - close(stopped) - }() - - for { - trigger.Reset() - select { - case <-ctx.Done(): - return - case <-stop: - return - case <-trigger.C(): - if _, err := ss.db.ExecContext( - ctx, - `UPDATE storage_cleanups - SET triggered_at = NOW() - WHERE virtual_storage = $1 AND storage = $2`, - entry.VirtualStorage, entry.Storage, - ); err != nil { - return - } - } - } - }() - - return &entry, func() error { - // signals health update goroutine to terminate - stop <- struct{}{} - // waits for the health update goroutine to terminate to prevent update - // of the triggered_at after setting it to NULL - <-stopped - - if _, err := ss.db.ExecContext( - ctx, - `UPDATE storage_cleanups - SET last_run = NOW(), triggered_at = NULL - WHERE virtual_storage = $1 AND storage = $2`, - entry.VirtualStorage, entry.Storage, - ); err != nil { - return fmt.Errorf("update storage_cleanups: %w", err) - } - return nil - }, nil -} - -// DoesntExist returns RepositoryClusterPath for each repository that doesn't exist in the database -// by querying repositories and storage_repositories tables. -func (ss *StorageCleanup) DoesntExist(ctx context.Context, virtualStorage, storage string, replicaPaths []string) ([]RepositoryClusterPath, error) { - if len(replicaPaths) == 0 { - return nil, nil - } - - rows, err := ss.db.QueryContext( - ctx, - `SELECT $1 AS virtual_storage, $2 AS storage, UNNEST($3::TEXT[]) AS replica_path - EXCEPT ( - SELECT virtual_storage, storage, replica_path - FROM repositories - JOIN storage_repositories USING (virtual_storage, relative_path) - WHERE virtual_storage = $1 AND storage = $2 AND replica_path = ANY($3) - )`, - virtualStorage, storage, pq.StringArray(replicaPaths), - ) - if err != nil { - return nil, fmt.Errorf("query: %w", err) - } - defer func() { _ = rows.Close() }() - - var res []RepositoryClusterPath - for rows.Next() { - var curr RepositoryClusterPath - if err := rows.Scan(&curr.VirtualStorage, &curr.Storage, &curr.RelativeReplicaPath); err != nil { - return nil, fmt.Errorf("scan: %w", err) - } - res = append(res, curr) - } - if err := rows.Err(); err != nil { - return nil, fmt.Errorf("loop: %w", err) - } - if err := rows.Close(); err != nil { - return nil, fmt.Errorf("close: %w", err) - } - return res, nil -} diff --git a/internal/praefect/datastore/storage_cleanup_test.go b/internal/praefect/datastore/storage_cleanup_test.go deleted file mode 100644 index bb8e66d75..000000000 --- a/internal/praefect/datastore/storage_cleanup_test.go +++ /dev/null @@ -1,283 +0,0 @@ -package datastore - -import ( - "database/sql" - "testing" - "time" - - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore/glsql" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" -) - -func TestStorageCleanup_Populate(t *testing.T) { - t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() - db := glsql.NewDB(t) - storageCleanup := NewStorageCleanup(db.DB) - - require.NoError(t, storageCleanup.Populate(ctx, "praefect", "gitaly-1")) - actual := getAllStoragesCleanup(t, db) - single := []storageCleanupRow{{ClusterPath: ClusterPath{VirtualStorage: "praefect", Storage: "gitaly-1"}}} - require.Equal(t, single, actual) - - err := storageCleanup.Populate(ctx, "praefect", "gitaly-1") - require.NoError(t, err, "population of the same data should not generate an error") - actual = getAllStoragesCleanup(t, db) - require.Equal(t, single, actual, "same data should not create additional rows or change existing") - - require.NoError(t, storageCleanup.Populate(ctx, "default", "gitaly-2")) - multiple := append(single, storageCleanupRow{ClusterPath: ClusterPath{VirtualStorage: "default", Storage: "gitaly-2"}}) - actual = getAllStoragesCleanup(t, db) - require.ElementsMatch(t, multiple, actual, "new data should create additional row") -} - -func TestStorageCleanup_AcquireNextStorage(t *testing.T) { - t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() - db := glsql.NewDB(t) - storageCleanup := NewStorageCleanup(db.DB) - - t.Run("ok", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - - clusterPath, release, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.Equal(t, &ClusterPath{VirtualStorage: "vs", Storage: "g1"}, clusterPath) - }) - - t.Run("last_run condition", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - // Acquire it to initialize last_run column. - _, release, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - - clusterPath, release, err := storageCleanup.AcquireNextStorage(ctx, time.Hour, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.Nil(t, clusterPath, "no result expected as there can't be such entries") - }) - - t.Run("sorting based on storage name as no executions done yet", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g2")) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g3")) - - clusterPath, release, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.Equal(t, &ClusterPath{VirtualStorage: "vs", Storage: "g1"}, clusterPath) - }) - - t.Run("sorting based on storage name and last_run", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - _, release, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g2")) - - clusterPath, release, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.Equal(t, &ClusterPath{VirtualStorage: "vs", Storage: "g2"}, clusterPath) - }) - - t.Run("sorting based on last_run", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g2")) - clusterPath, release, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.Equal(t, &ClusterPath{VirtualStorage: "vs", Storage: "g1"}, clusterPath) - clusterPath, release, err = storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.Equal(t, &ClusterPath{VirtualStorage: "vs", Storage: "g2"}, clusterPath) - - clusterPath, release, err = storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NoError(t, release()) - require.Equal(t, &ClusterPath{VirtualStorage: "vs", Storage: "g1"}, clusterPath) - }) - - t.Run("already acquired won't be acquired until released", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - _, release1, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - - clusterPath, release2, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.Nil(t, clusterPath, clusterPath) - require.NoError(t, release1()) - require.NoError(t, release2()) - - clusterPath, release3, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NotNil(t, clusterPath) - require.NoError(t, release3()) - }) - - t.Run("already acquired won't be acquired until released", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - _, release1, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - - clusterPath, release2, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.Nil(t, clusterPath, clusterPath) - require.NoError(t, release1()) - require.NoError(t, release2()) - - clusterPath, release3, err := storageCleanup.AcquireNextStorage(ctx, 0, time.Second) - require.NoError(t, err) - require.NotNil(t, clusterPath) - require.NoError(t, release3()) - }) - - t.Run("acquired for long time triggers update loop", func(t *testing.T) { - db.TruncateAll(t) - require.NoError(t, storageCleanup.Populate(ctx, "vs", "g1")) - start := time.Now().UTC() - _, release, err := storageCleanup.AcquireNextStorage(ctx, 0, 500*time.Millisecond) - require.NoError(t, err) - - // Make sure the triggered_at column has a non NULL value after the record is acquired. - check1 := getAllStoragesCleanup(t, db) - require.Len(t, check1, 1) - require.True(t, check1[0].TriggeredAt.Valid) - require.True(t, check1[0].TriggeredAt.Time.After(start), check1[0].TriggeredAt.Time.String(), start.String()) - - // Check the goroutine running in the background updates triggered_at column periodically. - time.Sleep(time.Second) - - check2 := getAllStoragesCleanup(t, db) - require.Len(t, check2, 1) - require.True(t, check2[0].TriggeredAt.Valid) - require.True(t, check2[0].TriggeredAt.Time.After(check1[0].TriggeredAt.Time), check2[0].TriggeredAt.Time.String(), check1[0].TriggeredAt.Time.String()) - - require.NoError(t, release()) - - // Make sure the triggered_at column has a NULL value after the record is released. - check3 := getAllStoragesCleanup(t, db) - require.Len(t, check3, 1) - require.False(t, check3[0].TriggeredAt.Valid) - }) -} - -func TestStorageCleanup_Exists(t *testing.T) { - t.Parallel() - ctx, cancel := testhelper.Context() - defer cancel() - - db := glsql.NewDB(t) - - repoStore := NewPostgresRepositoryStore(db.DB, nil) - require.NoError(t, repoStore.CreateRepository(ctx, 0, "vs", "p/1", "g1", []string{"g2", "g3"}, nil, false, false)) - require.NoError(t, repoStore.CreateRepository(ctx, 1, "vs", "p/2", "g1", []string{"g2", "g3"}, nil, false, false)) - storageCleanup := NewStorageCleanup(db.DB) - - for _, tc := range []struct { - desc string - virtualStorage string - storage string - relativeReplicaPaths []string - out []RepositoryClusterPath - }{ - { - desc: "multiple doesn't exist", - virtualStorage: "vs", - storage: "g1", - relativeReplicaPaths: []string{"p/1", "p/2", "path/x", "path/y"}, - out: []RepositoryClusterPath{ - {ClusterPath: ClusterPath{VirtualStorage: "vs", Storage: "g1"}, RelativeReplicaPath: "path/x"}, - {ClusterPath: ClusterPath{VirtualStorage: "vs", Storage: "g1"}, RelativeReplicaPath: "path/y"}, - }, - }, - { - desc: "duplicates", - virtualStorage: "vs", - storage: "g1", - relativeReplicaPaths: []string{"p/1", "path/x", "path/x"}, - out: []RepositoryClusterPath{ - {ClusterPath: ClusterPath{VirtualStorage: "vs", Storage: "g1"}, RelativeReplicaPath: "path/x"}, - }, - }, - { - desc: "all exist", - virtualStorage: "vs", - storage: "g1", - relativeReplicaPaths: []string{"p/1", "p/2"}, - out: nil, - }, - { - desc: "all doesn't exist", - virtualStorage: "vs", - storage: "g1", - relativeReplicaPaths: []string{"path/x", "path/y", "path/z"}, - out: []RepositoryClusterPath{ - {ClusterPath: ClusterPath{VirtualStorage: "vs", Storage: "g1"}, RelativeReplicaPath: "path/x"}, - {ClusterPath: ClusterPath{VirtualStorage: "vs", Storage: "g1"}, RelativeReplicaPath: "path/y"}, - {ClusterPath: ClusterPath{VirtualStorage: "vs", Storage: "g1"}, RelativeReplicaPath: "path/z"}, - }, - }, - { - desc: "doesn't exist because of storage", - virtualStorage: "vs", - storage: "stub", - relativeReplicaPaths: []string{"path/x"}, - out: []RepositoryClusterPath{ - {ClusterPath: ClusterPath{VirtualStorage: "vs", Storage: "stub"}, RelativeReplicaPath: "path/x"}, - }, - }, - { - desc: "doesn't exist because of virtual storage", - virtualStorage: "stub", - storage: "g1", - relativeReplicaPaths: []string{"path/x"}, - out: []RepositoryClusterPath{ - {ClusterPath: ClusterPath{VirtualStorage: "stub", Storage: "g1"}, RelativeReplicaPath: "path/x"}, - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - res, err := storageCleanup.DoesntExist(ctx, tc.virtualStorage, tc.storage, tc.relativeReplicaPaths) - require.NoError(t, err) - require.ElementsMatch(t, tc.out, res) - }) - } -} - -type storageCleanupRow struct { - ClusterPath - LastRun sql.NullTime - TriggeredAt sql.NullTime -} - -func getAllStoragesCleanup(t testing.TB, db glsql.DB) []storageCleanupRow { - rows, err := db.Query(`SELECT * FROM storage_cleanups`) - require.NoError(t, err) - defer func() { - require.NoError(t, rows.Close()) - }() - - var res []storageCleanupRow - for rows.Next() { - var dst storageCleanupRow - err := rows.Scan(&dst.VirtualStorage, &dst.Storage, &dst.LastRun, &dst.TriggeredAt) - require.NoError(t, err) - res = append(res, dst) - } - require.NoError(t, rows.Err()) - return res -} diff --git a/internal/praefect/grpc-proxy/proxy/handler_ext_test.go b/internal/praefect/grpc-proxy/proxy/handler_ext_test.go index 0aaea9cfe..d33fa458d 100644 --- a/internal/praefect/grpc-proxy/proxy/handler_ext_test.go +++ b/internal/praefect/grpc-proxy/proxy/handler_ext_test.go @@ -12,7 +12,6 @@ import ( "net/http" "net/http/httptest" "net/url" - "os" "path/filepath" "testing" "time" @@ -31,6 +30,7 @@ import ( pb "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/grpc-proxy/testdata" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testassert" + "go.uber.org/goleak" "google.golang.org/grpc" "google.golang.org/grpc/codes" grpc_metadata "google.golang.org/grpc/metadata" @@ -49,18 +49,11 @@ const ( ) func TestMain(m *testing.M) { - os.Exit(testMain(m)) -} - -func testMain(m *testing.M) int { - defer func() { - testhelper.MustHaveNoChildProcess() - testhelper.MustHaveNoGoroutines() - }() + defer testhelper.MustHaveNoChildProcess() cleanup := testhelper.Configure() defer cleanup() - return m.Run() + goleak.VerifyTestMain(m, goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start")) } // asserting service is implemented on the server side and serves as a handler for stuff diff --git a/internal/praefect/helper_test.go b/internal/praefect/helper_test.go index 70d320eaa..0c559047d 100644 --- a/internal/praefect/helper_test.go +++ b/internal/praefect/helper_test.go @@ -54,9 +54,7 @@ func testConfig(backends int) config.Config { return cfg } -type noopBackoffFactory struct{} - -func (noopBackoffFactory) Create() (Backoff, BackoffReset) { +func noopBackoffFunc() (backoff, backoffReset) { return func() time.Duration { return 0 }, func() {} @@ -176,7 +174,7 @@ func runPraefectServer(t testing.TB, ctx context.Context, conf config.Config, op // TODO: run a replmgr for EVERY virtual storage replmgr := NewReplMgr( opt.withLogger, - conf.StorageNames(), + conf.VirtualStorageNames(), opt.withQueue, opt.withRepoStore, opt.withNodeMgr, @@ -202,10 +200,7 @@ func runPraefectServer(t testing.TB, ctx context.Context, conf config.Config, op errQ := make(chan error) ctx, cancel := context.WithCancel(ctx) - go func() { - errQ <- prf.Serve(listener) - close(errQ) - }() + go func() { errQ <- prf.Serve(listener) }() replMgrDone := startProcessBacklog(ctx, replmgr) // dial client to praefect @@ -289,7 +284,7 @@ func startProcessBacklog(ctx context.Context, replMgr ReplMgr) <-chan struct{} { done := make(chan struct{}) go func() { defer close(done) - replMgr.ProcessBacklog(ctx, noopBackoffFactory{}) + replMgr.ProcessBacklog(ctx, noopBackoffFunc) }() return done } diff --git a/internal/praefect/protoregistry/protoregistry.go b/internal/praefect/protoregistry/protoregistry.go index 7434de176..6c9bbff5d 100644 --- a/internal/praefect/protoregistry/protoregistry.go +++ b/internal/praefect/protoregistry/protoregistry.go @@ -172,7 +172,7 @@ func New(protos ...*descriptorpb.FileDescriptorProto) (*Registry, error) { p.GetPackage(), svc.GetName(), method.GetName(), ) - if intercepted, err := protoutil.IsInterceptedMethod(svc, method); err != nil { + if intercepted, err := protoutil.IsInterceptedService(svc); err != nil { return nil, fmt.Errorf("is intercepted: %w", err) } else if intercepted { interceptedMethods[fullMethodName] = struct{}{} diff --git a/internal/praefect/protoregistry/protoregistry_test.go b/internal/praefect/protoregistry/protoregistry_test.go index 515c13e3d..87ebfcd9d 100644 --- a/internal/praefect/protoregistry/protoregistry_test.go +++ b/internal/praefect/protoregistry/protoregistry_test.go @@ -112,7 +112,6 @@ func TestNewProtoRegistry(t *testing.T) { "RepositorySize": protoregistry.OpAccessor, "ApplyGitattributes": protoregistry.OpMutator, "FetchRemote": protoregistry.OpMutator, - "FetchBundle": protoregistry.OpMutator, "CreateRepository": protoregistry.OpMutator, "GetArchive": protoregistry.OpAccessor, "HasLocalBranches": protoregistry.OpAccessor, diff --git a/internal/praefect/replicator.go b/internal/praefect/replicator.go index 0436cf431..8d3cbdf4f 100644 --- a/internal/praefect/replicator.go +++ b/internal/praefect/replicator.go @@ -11,7 +11,6 @@ import ( "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/repository" "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage" - "gitlab.com/gitlab-org/gitaly/v14/internal/helper" "gitlab.com/gitlab-org/gitaly/v14/internal/middleware/metadatahandler" "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" @@ -407,18 +406,17 @@ func (dr defaultReplicator) RepackFull(ctx context.Context, event datastore.Repl // ReplMgr is a replication manager for handling replication jobs type ReplMgr struct { - log *logrus.Entry - queue datastore.ReplicationEventQueue - hc HealthChecker - nodes NodeSet - storageNamesByVirtualStorage map[string][]string // replicas this replicator is responsible for - replicator Replicator // does the actual replication logic - replInFlightMetric *prometheus.GaugeVec - replLatencyMetric prommetrics.HistogramVec - replDelayMetric prommetrics.HistogramVec - replJobTimeout time.Duration - dequeueBatchSize uint - parallelStorageProcessingWorkers uint + log *logrus.Entry + queue datastore.ReplicationEventQueue + hc HealthChecker + nodes NodeSet + virtualStorages []string // replicas this replicator is responsible for + replicator Replicator // does the actual replication logic + replInFlightMetric *prometheus.GaugeVec + replLatencyMetric prommetrics.HistogramVec + replDelayMetric prommetrics.HistogramVec + replJobTimeout time.Duration + dequeueBatchSize uint } // ReplMgrOpt allows a replicator to be configured with additional options @@ -445,50 +443,31 @@ func WithDequeueBatchSize(size uint) func(*ReplMgr) { } } -// WithParallelStorageProcessingWorkers configures the number of workers used to process replication -// events per virtual storage. -func WithParallelStorageProcessingWorkers(n uint) func(*ReplMgr) { - return func(m *ReplMgr) { - m.parallelStorageProcessingWorkers = n - } -} - // NewReplMgr initializes a replication manager with the provided dependencies // and options -func NewReplMgr(log *logrus.Entry, storageNames map[string][]string, queue datastore.ReplicationEventQueue, rs datastore.RepositoryStore, hc HealthChecker, nodes NodeSet, opts ...ReplMgrOpt) ReplMgr { +func NewReplMgr(log *logrus.Entry, virtualStorages []string, queue datastore.ReplicationEventQueue, rs datastore.RepositoryStore, hc HealthChecker, nodes NodeSet, opts ...ReplMgrOpt) ReplMgr { r := ReplMgr{ - log: log.WithField("component", "replication_manager"), - queue: queue, - replicator: defaultReplicator{rs: rs, log: log.WithField("component", "replicator")}, - storageNamesByVirtualStorage: storageNames, - hc: hc, - nodes: nodes, + log: log.WithField("component", "replication_manager"), + queue: queue, + replicator: defaultReplicator{rs: rs, log: log.WithField("component", "replicator")}, + virtualStorages: virtualStorages, + hc: hc, + nodes: nodes, replInFlightMetric: prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "gitaly_praefect_replication_jobs", Help: "Number of replication jobs in flight.", }, []string{"virtual_storage", "gitaly_storage", "change_type"}, ), - replLatencyMetric: prometheus.NewHistogramVec(prometheus.HistogramOpts{}, []string{"type"}), - replDelayMetric: prometheus.NewHistogramVec(prometheus.HistogramOpts{}, []string{"type"}), - dequeueBatchSize: config.DefaultReplicationConfig().BatchSize, - parallelStorageProcessingWorkers: 1, + replLatencyMetric: prometheus.NewHistogramVec(prometheus.HistogramOpts{}, []string{"type"}), + replDelayMetric: prometheus.NewHistogramVec(prometheus.HistogramOpts{}, []string{"type"}), + dequeueBatchSize: config.DefaultReplicationConfig().BatchSize, } for _, opt := range opts { opt(&r) } - for virtual, sn := range storageNames { - if len(sn) < int(r.parallelStorageProcessingWorkers) { - r.log.Infof("parallel processing workers decreased from %d "+ - "configured with config to %d according to minumal amount of "+ - "storages in the virtual storage %q", - r.parallelStorageProcessingWorkers, len(storageNames), virtual, - ) - r.parallelStorageProcessingWorkers = uint(len(storageNames)) - } - } return r } @@ -506,35 +485,33 @@ const ( logWithVirtualStorage = "virtual_storage" ) -// ExpBackoffFactory creates exponentially growing durations. -type ExpBackoffFactory struct { - Start, Max time.Duration -} +type ( + backoff func() time.Duration + backoffReset func() +) -// Create returns a backoff function based on Start and Max time durations. -func (b ExpBackoffFactory) Create() (Backoff, BackoffReset) { - const factor = 2 - duration := b.Start +// BackoffFunc is a function that n turn provides a pair of functions backoff and backoffReset +type BackoffFunc func() (backoff, backoffReset) - return func() time.Duration { - defer func() { - duration *= time.Duration(factor) - if (duration) >= b.Max { - duration = b.Max - } - }() - return duration - }, func() { - duration = b.Start - } -} +// ExpBackoffFunc generates a backoffFunc based off of start and max time durations +func ExpBackoffFunc(start time.Duration, max time.Duration) BackoffFunc { + return func() (backoff, backoffReset) { + const factor = 2 + duration := start -type ( - // Backoff returns next backoff. - Backoff func() time.Duration - // BackoffReset resets backoff provider. - BackoffReset func() -) + return func() time.Duration { + defer func() { + duration *= time.Duration(factor) + if (duration) >= max { + duration = max + } + }() + return duration + }, func() { + duration = start + } + } +} func getCorrelationID(params datastore.Params) string { correlationID := "" @@ -544,26 +521,21 @@ func getCorrelationID(params datastore.Params) string { return correlationID } -// BackoffFactory creates backoff function and a reset pair for it. -type BackoffFactory interface { - // Create return new backoff provider and a reset function for it. - Create() (Backoff, BackoffReset) -} - // ProcessBacklog starts processing of queued jobs. // It will be processing jobs until ctx is Done. ProcessBacklog // blocks until all backlog processing goroutines have returned -func (r ReplMgr) ProcessBacklog(ctx context.Context, b BackoffFactory) { +func (r ReplMgr) ProcessBacklog(ctx context.Context, b BackoffFunc) { var wg sync.WaitGroup - defer wg.Wait() - for virtualStorage := range r.storageNamesByVirtualStorage { + for _, virtualStorage := range r.virtualStorages { wg.Add(1) go func(virtualStorage string) { defer wg.Done() r.processBacklog(ctx, b, virtualStorage) }(virtualStorage) } + + wg.Wait() } // ProcessStale starts a background process to acknowledge stale replication jobs. @@ -591,83 +563,43 @@ func (r ReplMgr) ProcessStale(ctx context.Context, checkPeriod, staleAfter time. return done } -func (r ReplMgr) processBacklog(ctx context.Context, b BackoffFactory, virtualStorage string) { - var wg sync.WaitGroup - defer wg.Wait() - +func (r ReplMgr) processBacklog(ctx context.Context, b BackoffFunc, virtualStorage string) { logger := r.log.WithField(logWithVirtualStorage, virtualStorage) - logger.Info("processing started") - - // We should make a graceful shutdown of the processing loop and don't want to interrupt - // in-flight operations. That is why we suppress cancellation on the provided context. - appCtx := ctx - ctx = helper.SuppressCancellation(ctx) - - storageNames := r.storageNamesByVirtualStorage[virtualStorage] - type StorageProcessing struct { - StorageName string - Backoff - BackoffReset - } - storagesQueue := make(chan StorageProcessing, len(storageNames)) - for _, storageName := range storageNames { - backoff, reset := b.Create() - storagesQueue <- StorageProcessing{StorageName: storageName, Backoff: backoff, BackoffReset: reset} - } + backoff, reset := b() - for i := uint(0); i < r.parallelStorageProcessingWorkers; i++ { - wg.Add(1) - go func() { - defer wg.Done() + logger.Info("processing started") - for { - var storageProcessing StorageProcessing - select { - case <-appCtx.Done(): - logger.WithError(appCtx.Err()).Info("processing stopped") - return - case storageProcessing = <-storagesQueue: - } + for { + select { + case <-ctx.Done(): + logger.WithError(ctx.Err()).Info("processing stopped") + return // processing must be stopped + default: + // proceed with processing + } - healthyStorages := r.hc.HealthyNodes()[virtualStorage] - healthy := false - for _, healthyStorageName := range healthyStorages { - if healthyStorageName != storageProcessing.StorageName { - continue - } - healthy = true - break - } + var totalEvents int + for _, storage := range r.hc.HealthyNodes()[virtualStorage] { + target, ok := r.nodes[virtualStorage][storage] + if !ok { + logger.WithField("storage", storage).Error("no connection to target storage") + continue + } - var processedEvents int - if healthy { - target, ok := r.nodes[virtualStorage][storageProcessing.StorageName] - if !ok { - logger.WithField("storage", storageProcessing.StorageName).Error("no connection to target storage") - } else { - processedEvents = r.handleNode(ctx, virtualStorage, target) - } - } + totalEvents += r.handleNode(ctx, virtualStorage, target) + } - if processedEvents == 0 { - // if the storage is not healthy or if there is no events to - // process we don't put it back to the queue immediately but - // wait for certain time period first. - go func() { - select { - case <-time.After(storageProcessing.Backoff()): - storagesQueue <- storageProcessing - case <-appCtx.Done(): - logger.WithError(appCtx.Err()).Info("processing stopped") - return - } - }() - } else { - storageProcessing.BackoffReset() - storagesQueue <- storageProcessing - } + if totalEvents == 0 { + select { + case <-time.After(backoff()): + continue + case <-ctx.Done(): + logger.WithError(ctx.Err()).Info("processing stopped") + return } - }() + } + + reset() } } diff --git a/internal/praefect/replicator_test.go b/internal/praefect/replicator_test.go index 043838b49..33fab625c 100644 --- a/internal/praefect/replicator_test.go +++ b/internal/praefect/replicator_test.go @@ -169,42 +169,36 @@ func TestReplMgr_ProcessBacklog(t *testing.T) { replMgr := NewReplMgr( loggerEntry, - conf.StorageNames(), + conf.VirtualStorageNames(), queue, datastore.MockRepositoryStore{}, nodeMgr, NodeSetFromNodeManager(nodeMgr), WithLatencyMetric(&mockReplicationLatencyHistogramVec), WithDelayMetric(&mockReplicationDelayHistogramVec), - WithParallelStorageProcessingWorkers(100), ) - replMgr.ProcessBacklog(ctx, noopBackoffFactory{}) + replMgr.ProcessBacklog(ctx, ExpBackoffFunc(time.Hour, 0)) logEntries := loggerHook.AllEntries() - require.True(t, len(logEntries) > 4, "expected at least 5 log entries to be present") - require.Equal(t, - []interface{}{`parallel processing workers decreased from 100 configured with config to 1 according to minumal amount of storages in the virtual storage "virtual"`}, - []interface{}{logEntries[0].Message}, - ) - + require.True(t, len(logEntries) > 3, "expected at least 4 log entries to be present") require.Equal(t, []interface{}{"processing started", "virtual"}, - []interface{}{logEntries[1].Message, logEntries[1].Data["virtual_storage"]}, + []interface{}{logEntries[0].Message, logEntries[0].Data["virtual_storage"]}, ) require.Equal(t, []interface{}{"replication job processing started", "virtual", "correlation-id"}, - []interface{}{logEntries[2].Message, logEntries[2].Data["virtual_storage"], logEntries[2].Data[logWithCorrID]}, + []interface{}{logEntries[1].Message, logEntries[1].Data["virtual_storage"], logEntries[1].Data[logWithCorrID]}, ) - dequeuedEvent := logEntries[2].Data["event"].(datastore.ReplicationEvent) + dequeuedEvent := logEntries[1].Data["event"].(datastore.ReplicationEvent) require.Equal(t, datastore.JobStateInProgress, dequeuedEvent.State) require.Equal(t, []string{"backup", "primary"}, []string{dequeuedEvent.Job.TargetNodeStorage, dequeuedEvent.Job.SourceNodeStorage}) require.Equal(t, []interface{}{"replication job processing finished", "virtual", datastore.JobStateCompleted, "correlation-id"}, - []interface{}{logEntries[3].Message, logEntries[3].Data["virtual_storage"], logEntries[3].Data["new_state"], logEntries[3].Data[logWithCorrID]}, + []interface{}{logEntries[2].Message, logEntries[2].Data["virtual_storage"], logEntries[2].Data["new_state"], logEntries[2].Data[logWithCorrID]}, ) replicatedPath := filepath.Join(backupCfg.Storages[0].Path, testRepo.GetRelativePath()) @@ -345,7 +339,7 @@ func TestReplicator_PropagateReplicationJob(t *testing.T) { protoregistry.GitalyProtoPreregistered, ) - replmgr := NewReplMgr(logEntry, conf.StorageNames(), queue, rs, nodeMgr, NodeSetFromNodeManager(nodeMgr)) + replmgr := NewReplMgr(logEntry, conf.VirtualStorageNames(), queue, rs, nodeMgr, NodeSetFromNodeManager(nodeMgr)) prf := NewGRPCServer(conf, logEntry, protoregistry.GitalyProtoPreregistered, coordinator.StreamDirector, nodeMgr, txMgr, queue, rs, nil, nil, nil) @@ -685,6 +679,41 @@ func TestProcessBacklog_FailedJobs(t *testing.T) { defer cancel() queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(glsql.NewDB(t))) + processed := make(chan struct{}) + + dequeues := 0 + queueInterceptor.OnDequeue(func(ctx context.Context, virtual, target string, count int, queue datastore.ReplicationEventQueue) ([]datastore.ReplicationEvent, error) { + events, err := queue.Dequeue(ctx, virtual, target, count) + if len(events) > 0 { + dequeues++ + } + return events, err + }) + + completedAcks := 0 + failedAcks := 0 + deadAcks := 0 + + queueInterceptor.OnAcknowledge(func(ctx context.Context, state datastore.JobState, ids []uint64, queue datastore.ReplicationEventQueue) ([]uint64, error) { + switch state { + case datastore.JobStateCompleted: + require.Equal(t, []uint64{1}, ids) + completedAcks++ + case datastore.JobStateFailed: + require.Equal(t, []uint64{2}, ids) + failedAcks++ + case datastore.JobStateDead: + require.Equal(t, []uint64{2}, ids) + deadAcks++ + default: + require.FailNow(t, "acknowledge is not expected", state) + } + ackIDs, err := queue.Acknowledge(ctx, state, ids) + if completedAcks+failedAcks+deadAcks == 4 { + close(processed) + } + return ackIDs, err + }) // this job exists to verify that replication works okJob := datastore.ReplicationJob{ @@ -713,7 +742,7 @@ func TestProcessBacklog_FailedJobs(t *testing.T) { replMgr := NewReplMgr( logEntry, - conf.StorageNames(), + conf.VirtualStorageNames(), queueInterceptor, datastore.MockRepositoryStore{}, nodeMgr, @@ -721,30 +750,19 @@ func TestProcessBacklog_FailedJobs(t *testing.T) { ) replMgrDone := startProcessBacklog(ctx, replMgr) - require.NoError(t, queueInterceptor.Wait(time.Minute, func(i *datastore.ReplicationEventQueueInterceptor) bool { - return len(i.GetAcknowledgeResult()) == 4 - })) - cancel() - <-replMgrDone - - var dequeueCalledEffectively int - for _, res := range queueInterceptor.GetDequeuedResult() { - if len(res) > 0 { - dequeueCalledEffectively++ - } + select { + case <-processed: + cancel() + case <-time.After(60 * time.Second): + // strongly depends on the processing capacity + t.Fatal("time limit expired for job to complete") } - require.Equal(t, 3, dequeueCalledEffectively, "expected 1 deque to get [okJob, failJob] and 2 more for [failJob] only") - expAcks := map[datastore.JobState][]uint64{ - datastore.JobStateFailed: {2, 2}, - datastore.JobStateDead: {2}, - datastore.JobStateCompleted: {1}, - } - acks := map[datastore.JobState][]uint64{} - for _, ack := range queueInterceptor.GetAcknowledge() { - acks[ack.State] = append(acks[ack.State], ack.IDs...) - } - require.Equal(t, expAcks, acks) + require.Equal(t, 3, dequeues, "expected 1 deque to get [okJob, failJob] and 2 more for [failJob] only") + require.Equal(t, 2, failedAcks) + require.Equal(t, 1, deadAcks) + require.Equal(t, 1, completedAcks) + <-replMgrDone } func TestProcessBacklog_Success(t *testing.T) { @@ -785,18 +803,21 @@ func TestProcessBacklog_Success(t *testing.T) { defer cancel() queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(glsql.NewDB(t))) + + processed := make(chan struct{}) queueInterceptor.OnAcknowledge(func(ctx context.Context, state datastore.JobState, ids []uint64, queue datastore.ReplicationEventQueue) ([]uint64, error) { ackIDs, err := queue.Acknowledge(ctx, state, ids) if len(ids) > 0 { - assert.Equal(t, datastore.JobStateCompleted, state, "no fails expected") - assert.Equal(t, []uint64{1, 3, 4}, ids, "all jobs must be processed at once") + require.Equal(t, datastore.JobStateCompleted, state, "no fails expected") + require.Equal(t, []uint64{1, 3, 4}, ids, "all jobs must be processed at once") + close(processed) } return ackIDs, err }) var healthUpdated int32 queueInterceptor.OnStartHealthUpdate(func(ctx context.Context, trigger <-chan time.Time, events []datastore.ReplicationEvent) error { - assert.Len(t, events, 3) + require.Len(t, events, 3) atomic.AddInt32(&healthUpdated, 1) return nil }) @@ -863,7 +884,7 @@ func TestProcessBacklog_Success(t *testing.T) { replMgr := NewReplMgr( logEntry, - conf.StorageNames(), + conf.VirtualStorageNames(), queueInterceptor, datastore.MockRepositoryStore{}, nodeMgr, @@ -871,18 +892,18 @@ func TestProcessBacklog_Success(t *testing.T) { ) replMgrDone := startProcessBacklog(ctx, replMgr) - require.NoError(t, queueInterceptor.Wait(time.Minute, func(i *datastore.ReplicationEventQueueInterceptor) bool { - var ids []uint64 - for _, params := range i.GetAcknowledge() { - ids = append(ids, params.IDs...) - } - return len(ids) == 3 - })) - cancel() - <-replMgrDone + select { + case <-processed: + require.EqualValues(t, 1, atomic.LoadInt32(&healthUpdated), "health update should be called") + cancel() + case <-time.After(30 * time.Second): + // strongly depends on the processing capacity + t.Fatal("time limit expired for job to complete") + } require.NoDirExists(t, fullNewPath1, "repository must be moved from %q to the new location", fullNewPath1) require.True(t, storage.IsGitDirectory(fullNewPath2), "repository must exist at new last RenameRepository location") + <-replMgrDone } func TestReplMgrProcessBacklog_OnlyHealthyNodes(t *testing.T) { @@ -902,22 +923,23 @@ func TestReplMgrProcessBacklog_OnlyHealthyNodes(t *testing.T) { ctx, cancel := testhelper.Context() - var mtx sync.Mutex - expStorages := map[string]bool{conf.VirtualStorages[0].Nodes[0].Storage: true, conf.VirtualStorages[0].Nodes[2].Storage: true} + first := true queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(glsql.NewDB(t))) queueInterceptor.OnDequeue(func(_ context.Context, virtualStorageName string, storageName string, _ int, _ datastore.ReplicationEventQueue) ([]datastore.ReplicationEvent, error) { select { case <-ctx.Done(): return nil, nil default: - mtx.Lock() - defer mtx.Unlock() - assert.Equal(t, conf.VirtualStorages[0].Name, virtualStorageName) - assert.True(t, expStorages[storageName], storageName, storageName) - delete(expStorages, storageName) - if len(expStorages) == 0 { - cancel() + if first { + first = false + require.Equal(t, conf.VirtualStorages[0].Name, virtualStorageName) + require.Equal(t, conf.VirtualStorages[0].Nodes[0].Storage, storageName) + return nil, nil } + + assert.Equal(t, conf.VirtualStorages[0].Name, virtualStorageName) + assert.Equal(t, conf.VirtualStorages[0].Nodes[2].Storage, storageName) + cancel() return nil, nil } }) @@ -929,7 +951,7 @@ func TestReplMgrProcessBacklog_OnlyHealthyNodes(t *testing.T) { replMgr := NewReplMgr( testhelper.DiscardTestEntry(t), - conf.StorageNames(), + conf.VirtualStorageNames(), queueInterceptor, nil, StaticHealthChecker{virtualStorage: {node1.Storage, node3.Storage}}, @@ -1000,7 +1022,7 @@ func TestProcessBacklog_ReplicatesToReadOnlyPrimary(t *testing.T) { replMgr := NewReplMgr( testhelper.DiscardTestEntry(t), - conf.StorageNames(), + conf.VirtualStorageNames(), queue, datastore.MockRepositoryStore{}, StaticHealthChecker{virtualStorage: {primaryStorage, secondaryStorage}}, @@ -1029,7 +1051,7 @@ func TestProcessBacklog_ReplicatesToReadOnlyPrimary(t *testing.T) { <-replMgrDone } -func TestBackoffFactory(t *testing.T) { +func TestBackoff(t *testing.T) { start := 1 * time.Microsecond max := 6 * time.Microsecond expectedBackoffs := []time.Duration{ @@ -1040,7 +1062,7 @@ func TestBackoffFactory(t *testing.T) { 6 * time.Microsecond, 6 * time.Microsecond, } - b, reset := ExpBackoffFactory{Start: start, Max: max}.Create() + b, reset := ExpBackoffFunc(start, max)() for _, expectedBackoff := range expectedBackoffs { require.Equal(t, expectedBackoff, b()) } diff --git a/internal/praefect/repocleaner/action_log.go b/internal/praefect/repocleaner/action_log.go deleted file mode 100644 index 934d69c49..000000000 --- a/internal/praefect/repocleaner/action_log.go +++ /dev/null @@ -1,33 +0,0 @@ -package repocleaner - -import ( - "context" - - "github.com/sirupsen/logrus" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" -) - -// LogWarnAction is an implementation of the Action interface that allows to log a warning message -// for the repositories that are not known for the praefect. -type LogWarnAction struct { - logger logrus.FieldLogger -} - -// NewLogWarnAction return new instance of the LogWarnAction. -func NewLogWarnAction(logger logrus.FieldLogger) *LogWarnAction { - return &LogWarnAction{ - logger: logger.WithField("component", "repocleaner.log_warn_action"), - } -} - -// Perform logs a warning for each repository that is not known to praefect. -func (al LogWarnAction) Perform(_ context.Context, notExisting []datastore.RepositoryClusterPath) error { - for _, entry := range notExisting { - al.logger.WithFields(logrus.Fields{ - "virtual_storage": entry.VirtualStorage, - "storage": entry.Storage, - "relative_replica_path": entry.RelativeReplicaPath, - }).Warn("repository is not managed by praefect") - } - return nil -} diff --git a/internal/praefect/repocleaner/action_log_test.go b/internal/praefect/repocleaner/action_log_test.go deleted file mode 100644 index 1c7af50b2..000000000 --- a/internal/praefect/repocleaner/action_log_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package repocleaner - -import ( - "context" - "testing" - - "github.com/sirupsen/logrus" - "github.com/sirupsen/logrus/hooks/test" - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" -) - -func TestLogWarnAction_Perform(t *testing.T) { - logger, hook := test.NewNullLogger() - action := NewLogWarnAction(logger) - err := action.Perform(context.TODO(), []datastore.RepositoryClusterPath{ - {ClusterPath: datastore.ClusterPath{VirtualStorage: "vs1", Storage: "g1"}, RelativeReplicaPath: "p/1"}, - {ClusterPath: datastore.ClusterPath{VirtualStorage: "vs2", Storage: "g2"}, RelativeReplicaPath: "p/2"}, - }) - require.NoError(t, err) - require.Len(t, hook.AllEntries(), 2) - - exp := []map[string]interface{}{{ - "Data": logrus.Fields{ - "component": "repocleaner.log_warn_action", - "virtual_storage": "vs1", - "storage": "g1", - "relative_replica_path": "p/1", - }, - "Message": "repository is not managed by praefect", - }, { - "Data": logrus.Fields{ - "component": "repocleaner.log_warn_action", - "virtual_storage": "vs2", - "storage": "g2", - "relative_replica_path": "p/2", - }, - "Message": "repository is not managed by praefect", - }} - - require.ElementsMatch(t, exp, []map[string]interface{}{{ - "Data": hook.AllEntries()[0].Data, - "Message": hook.AllEntries()[0].Message, - }, { - "Data": hook.AllEntries()[1].Data, - "Message": hook.AllEntries()[1].Message, - }}) -} diff --git a/internal/praefect/repocleaner/init_test.go b/internal/praefect/repocleaner/init_test.go deleted file mode 100644 index 011d4f2a4..000000000 --- a/internal/praefect/repocleaner/init_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package repocleaner - -import ( - "os" - "testing" - - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" -) - -func TestMain(m *testing.M) { - os.Exit(testMain(m)) -} - -func testMain(m *testing.M) (code int) { - defer testhelper.MustHaveNoChildProcess() - cleanup := testhelper.Configure() - defer cleanup() - return m.Run() -} diff --git a/internal/praefect/repocleaner/repository.go b/internal/praefect/repocleaner/repository.go deleted file mode 100644 index fbf3b841b..000000000 --- a/internal/praefect/repocleaner/repository.go +++ /dev/null @@ -1,202 +0,0 @@ -package repocleaner - -import ( - "context" - "errors" - "fmt" - "io" - "time" - - "github.com/sirupsen/logrus" - "gitlab.com/gitlab-org/gitaly/v14/internal/helper" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" - "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" -) - -// StateOwner performs check for the existence of the repositories. -type StateOwner interface { - // DoesntExist returns RepositoryClusterPath for each repository that doesn't exist in the database - // by querying repositories and storage_repositories tables. - DoesntExist(ctx context.Context, virtualStorage, storage string, replicaPaths []string) ([]datastore.RepositoryClusterPath, error) -} - -// Acquirer acquires storage for processing and no any other Acquirer can acquire it again until it is released. -type Acquirer interface { - // Populate adds provided storage into the pool of entries to acquire. - Populate(ctx context.Context, virtualStorage, storage string) error - // AcquireNextStorage acquires next storage based on the inactive time. - AcquireNextStorage(ctx context.Context, inactive, updatePeriod time.Duration) (*datastore.ClusterPath, func() error, error) -} - -// Action is a procedure to be executed on the repositories that doesn't exist in praefect database. -type Action interface { - // Perform runs actual action for non-existing repositories. - Perform(ctx context.Context, notExisting []datastore.RepositoryClusterPath) error -} - -// Runner scans healthy gitaly nodes for the repositories, verifies if -// found repositories are known by praefect and runs a special action. -type Runner struct { - cfg Cfg - logger logrus.FieldLogger - healthChecker praefect.HealthChecker - conns praefect.Connections - stateOwner StateOwner - acquirer Acquirer - action Action -} - -// Cfg contains set of configuration parameters to run Runner. -type Cfg struct { - // RunInterval: the check runs if the previous operation was done at least RunInterval before. - RunInterval time.Duration - // LivenessInterval: an update runs on the locked entity with provided period to signal that entity is in use. - LivenessInterval time.Duration - // RepositoriesInBatch is the number of repositories to pass as a batch for processing. - RepositoriesInBatch int -} - -// NewRunner returns instance of the Runner. -func NewRunner(cfg Cfg, logger logrus.FieldLogger, healthChecker praefect.HealthChecker, conns praefect.Connections, stateOwner StateOwner, acquirer Acquirer, action Action) *Runner { - return &Runner{ - cfg: cfg, - logger: logger.WithField("component", "repocleaner.repository_existence"), - healthChecker: healthChecker, - conns: conns, - stateOwner: stateOwner, - acquirer: acquirer, - action: action, - } -} - -// Run scans healthy gitaly nodes for the repositories, verifies if -// found repositories are known by praefect and runs a special action. -// It runs on each tick of the provided ticker and finishes with context cancellation. -func (gs *Runner) Run(ctx context.Context, ticker helper.Ticker) error { - gs.logger.Info("started") - defer gs.logger.Info("completed") - - defer ticker.Stop() - - for virtualStorage, connByStorage := range gs.conns { - for storage := range connByStorage { - if err := gs.acquirer.Populate(ctx, virtualStorage, storage); err != nil { - return fmt.Errorf("populate database: %w", err) - } - } - } - - var tick helper.Ticker - for { - // We use a local tick variable to run the first cycle - // without wait. All the other iterations are waiting - // for the next tick or context cancellation. - if tick != nil { - tick.Reset() - select { - case <-ctx.Done(): - return ctx.Err() - case <-tick.C(): - } - } else { - tick = ticker - } - - gs.run(ctx) - } -} - -func (gs *Runner) run(ctx context.Context) { - clusterPath, release, err := gs.acquirer.AcquireNextStorage(ctx, gs.cfg.RunInterval, gs.cfg.LivenessInterval) - if err != nil { - gs.logger.WithError(err).Error("unable to acquire next storage to verify") - return - } - - logger := gs.logger - defer func() { - if err := release(); err != nil { - logger.WithError(err).Error("failed to release storage acquired to verify") - } - }() - - if clusterPath == nil { - gs.logger.Debug("no storages to verify") - return - } - - logger = gs.loggerWith(clusterPath.VirtualStorage, clusterPath.Storage) - err = gs.execOnRepositories(ctx, clusterPath.VirtualStorage, clusterPath.Storage, func(paths []datastore.RepositoryClusterPath) { - relativePaths := make([]string, len(paths)) - for i, path := range paths { - relativePaths[i] = path.RelativeReplicaPath - } - notExisting, err := gs.stateOwner.DoesntExist(ctx, clusterPath.VirtualStorage, clusterPath.Storage, relativePaths) - if err != nil { - logger.WithError(err).WithField("repositories", paths).Error("failed to check existence") - return - } - - if err := gs.action.Perform(ctx, notExisting); err != nil { - logger.WithError(err).WithField("existence", notExisting).Error("perform action") - return - } - }) - if err != nil { - logger.WithError(err).Error("failed to exec action on repositories") - return - } -} - -func (gs *Runner) loggerWith(virtualStorage, storage string) logrus.FieldLogger { - return gs.logger.WithFields(logrus.Fields{"virtual_storage": virtualStorage, "storage": storage}) -} - -func (gs *Runner) execOnRepositories(ctx context.Context, virtualStorage, storage string, action func([]datastore.RepositoryClusterPath)) error { - gclient, err := gs.getInternalGitalyClient(virtualStorage, storage) - if err != nil { - return fmt.Errorf("setup gitaly client: %w", err) - } - - resp, err := gclient.WalkRepos(ctx, &gitalypb.WalkReposRequest{StorageName: storage}) - if err != nil { - return fmt.Errorf("unable to walk repos: %w", err) - } - - batch := make([]datastore.RepositoryClusterPath, 0, gs.cfg.RepositoriesInBatch) - for { - res, err := resp.Recv() - if err != nil { - if !errors.Is(err, io.EOF) { - return fmt.Errorf("failure on walking repos: %w", err) - } - break - } - - batch = append(batch, datastore.RepositoryClusterPath{ - ClusterPath: datastore.ClusterPath{ - VirtualStorage: virtualStorage, - Storage: storage, - }, - RelativeReplicaPath: res.RelativePath, - }) - - if len(batch) == cap(batch) { - action(batch) - batch = batch[:0] - } - } - if len(batch) > 0 { - action(batch) - } - return nil -} - -func (gs *Runner) getInternalGitalyClient(virtualStorage, storage string) (gitalypb.InternalGitalyClient, error) { - conn, found := gs.conns[virtualStorage][storage] - if !found { - return nil, fmt.Errorf("no connection to the gitaly node %q/%q", virtualStorage, storage) - } - return gitalypb.NewInternalGitalyClient(conn), nil -} diff --git a/internal/praefect/repocleaner/repository_test.go b/internal/praefect/repocleaner/repository_test.go deleted file mode 100644 index 32e7d7ad5..000000000 --- a/internal/praefect/repocleaner/repository_test.go +++ /dev/null @@ -1,324 +0,0 @@ -package repocleaner - -import ( - "context" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/sirupsen/logrus" - "github.com/sirupsen/logrus/hooks/test" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" - "gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest" - "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/setup" - "gitlab.com/gitlab-org/gitaly/v14/internal/helper" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/datastore/glsql" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/protoregistry" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/service/transaction" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testcfg" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testserver" -) - -func TestRunner_Run(t *testing.T) { - t.Parallel() - - const ( - repo1RelPath = "repo-1.git" - repo2RelPath = "repo-2.git" - repo3RelPath = "repo-3.git" - - storage1 = "gitaly-1" - storage2 = "gitaly-2" - storage3 = "gitaly-3" - - virtualStorage = "praefect" - ) - - g1Cfg := testcfg.Build(t, testcfg.WithStorages(storage1)) - g2Cfg := testcfg.Build(t, testcfg.WithStorages(storage2)) - g3Cfg := testcfg.Build(t, testcfg.WithStorages(storage3)) - - g1Addr := testserver.RunGitalyServer(t, g1Cfg, nil, setup.RegisterAll, testserver.WithDisablePraefect()) - g2Addr := testserver.RunGitalyServer(t, g2Cfg, nil, setup.RegisterAll, testserver.WithDisablePraefect()) - g3Addr := testserver.RunGitalyServer(t, g3Cfg, nil, setup.RegisterAll, testserver.WithDisablePraefect()) - - db := glsql.NewDB(t) - var database string - require.NoError(t, db.QueryRow(`SELECT current_database()`).Scan(&database)) - dbConf := glsql.GetDBConfig(t, database) - - conf := config.Config{ - SocketPath: testhelper.GetTemporaryGitalySocketFileName(t), - VirtualStorages: []*config.VirtualStorage{ - { - Name: virtualStorage, - Nodes: []*config.Node{ - {Storage: g1Cfg.Storages[0].Name, Address: g1Addr}, - {Storage: g2Cfg.Storages[0].Name, Address: g2Addr}, - {Storage: g3Cfg.Storages[0].Name, Address: g3Addr}, - }, - }, - }, - DB: dbConf, - } - cfg := Cfg{ - RunInterval: time.Duration(1), - LivenessInterval: time.Duration(1), - RepositoriesInBatch: 2, - } - - gittest.CloneRepo(t, g1Cfg, g1Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo1RelPath}) - gittest.CloneRepo(t, g1Cfg, g1Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo2RelPath}) - gittest.CloneRepo(t, g1Cfg, g1Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo3RelPath}) - - // second gitaly is missing repo-3.git repository - gittest.CloneRepo(t, g2Cfg, g2Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo1RelPath}) - gittest.CloneRepo(t, g2Cfg, g2Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo2RelPath}) - - // third gitaly has an extra repo-4.git repository - gittest.CloneRepo(t, g3Cfg, g3Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo1RelPath}) - gittest.CloneRepo(t, g3Cfg, g3Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo2RelPath}) - gittest.CloneRepo(t, g3Cfg, g3Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo3RelPath}) - gittest.CloneRepo(t, g3Cfg, g3Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: "repo-4.git"}) - - ctx, cancel := testhelper.Context() - defer cancel() - - repoStore := datastore.NewPostgresRepositoryStore(db.DB, nil) - for i, set := range []struct { - relativePath string - primary string - secondaries []string - }{ - { - relativePath: repo1RelPath, - primary: storage1, - secondaries: []string{storage3}, - }, - { - relativePath: repo2RelPath, - primary: storage1, - secondaries: []string{storage2, storage3}, - }, - { - relativePath: repo3RelPath, - primary: storage1, - secondaries: []string{storage2, storage3}, - }, - } { - require.NoError(t, repoStore.CreateRepository(ctx, int64(i), conf.VirtualStorages[0].Name, set.relativePath, set.primary, set.secondaries, nil, false, false)) - } - - logger, loggerHook := test.NewNullLogger() - logger.SetLevel(logrus.DebugLevel) - - entry := logger.WithContext(ctx) - clientHandshaker := backchannel.NewClientHandshaker(entry, praefect.NewBackchannelServerFactory(entry, transaction.NewServer(nil))) - nodeSet, err := praefect.DialNodes(ctx, conf.VirtualStorages, protoregistry.GitalyProtoPreregistered, nil, clientHandshaker) - require.NoError(t, err) - defer nodeSet.Close() - - storageCleanup := datastore.NewStorageCleanup(db.DB) - - var iteration int32 - runner := NewRunner(cfg, logger, praefect.StaticHealthChecker{virtualStorage: []string{storage1, storage2, storage3}}, nodeSet.Connections(), storageCleanup, storageCleanup, actionStub{ - PerformMethod: func(ctx context.Context, notExisting []datastore.RepositoryClusterPath) error { - i := atomic.LoadInt32(&iteration) - switch i { - case 0: - assert.ElementsMatch(t, nil, notExisting) - case 1: - assert.ElementsMatch(t, nil, notExisting) - case 2: - assert.ElementsMatch( - t, - []datastore.RepositoryClusterPath{ - datastore.NewRepositoryClusterPath(virtualStorage, storage2, repo1RelPath), - }, - notExisting, - ) - case 3: - assert.ElementsMatch(t, nil, notExisting) - case 4: - assert.Equal( - t, - []datastore.RepositoryClusterPath{ - datastore.NewRepositoryClusterPath(virtualStorage, storage3, "repo-4.git"), - }, - notExisting, - ) - } - atomic.AddInt32(&iteration, 1) - return nil - }, - }) - - ticker := helper.NewManualTicker() - done := make(chan struct{}) - go func() { - defer close(done) - assert.Equal(t, context.Canceled, runner.Run(ctx, ticker)) - }() - // we need to trigger it 5 times to make sure the 4-th run is fully completed - for i := 0; i < 5; i++ { - ticker.Tick() - } - require.Greater(t, atomic.LoadInt32(&iteration), int32(4)) - require.Len(t, loggerHook.AllEntries(), 1) - require.Equal( - t, - map[string]interface{}{"Data": logrus.Fields{"component": "repocleaner.repository_existence"}, "Message": "started"}, - map[string]interface{}{"Data": loggerHook.AllEntries()[0].Data, "Message": loggerHook.AllEntries()[0].Message}, - ) - // Terminates the loop. - cancel() - <-done - require.Equal( - t, - map[string]interface{}{"Data": logrus.Fields{"component": "repocleaner.repository_existence"}, "Message": "completed"}, - map[string]interface{}{"Data": loggerHook.LastEntry().Data, "Message": loggerHook.LastEntry().Message}, - ) -} - -func TestRunner_Run_noAvailableStorages(t *testing.T) { - t.Parallel() - - const ( - repo1RelPath = "repo-1.git" - storage1 = "gitaly-1" - virtualStorage = "praefect" - ) - - g1Cfg := testcfg.Build(t, testcfg.WithStorages(storage1)) - g1Addr := testserver.RunGitalyServer(t, g1Cfg, nil, setup.RegisterAll, testserver.WithDisablePraefect()) - - db := glsql.NewDB(t) - var database string - require.NoError(t, db.QueryRow(`SELECT current_database()`).Scan(&database)) - dbConf := glsql.GetDBConfig(t, database) - - conf := config.Config{ - SocketPath: testhelper.GetTemporaryGitalySocketFileName(t), - VirtualStorages: []*config.VirtualStorage{ - { - Name: virtualStorage, - Nodes: []*config.Node{ - {Storage: g1Cfg.Storages[0].Name, Address: g1Addr}, - }, - }, - }, - DB: dbConf, - } - cfg := Cfg{ - RunInterval: time.Minute, - LivenessInterval: time.Second, - RepositoriesInBatch: 2, - } - - gittest.CloneRepo(t, g1Cfg, g1Cfg.Storages[0], gittest.CloneRepoOpts{RelativePath: repo1RelPath}) - - ctx, cancel := testhelper.Context() - defer cancel() - - repoStore := datastore.NewPostgresRepositoryStore(db.DB, nil) - for i, set := range []struct { - relativePath string - primary string - }{ - { - relativePath: repo1RelPath, - primary: storage1, - }, - } { - require.NoError(t, repoStore.CreateRepository(ctx, int64(i), conf.VirtualStorages[0].Name, set.relativePath, set.primary, nil, nil, false, false)) - } - - logger := testhelper.NewTestLogger(t) - entry := logger.WithContext(ctx) - clientHandshaker := backchannel.NewClientHandshaker(entry, praefect.NewBackchannelServerFactory(entry, transaction.NewServer(nil))) - nodeSet, err := praefect.DialNodes(ctx, conf.VirtualStorages, protoregistry.GitalyProtoPreregistered, nil, clientHandshaker) - require.NoError(t, err) - defer nodeSet.Close() - - storageCleanup := datastore.NewStorageCleanup(db.DB) - startSecond := make(chan struct{}) - releaseFirst := make(chan struct{}) - runner := NewRunner(cfg, logger, praefect.StaticHealthChecker{virtualStorage: []string{storage1}}, nodeSet.Connections(), storageCleanup, storageCleanup, actionStub{ - PerformMethod: func(ctx context.Context, notExisting []datastore.RepositoryClusterPath) error { - assert.Empty(t, notExisting) - // Block execution here until send instance completes its execution. - // It allows us to be sure the picked storage can't be picked once again by - // another instance as well as that it works without problems if there is - // nothing to pick up to process. - close(startSecond) - <-releaseFirst - return nil - }, - }) - - var wg sync.WaitGroup - wg.Add(2) - - go func() { - logger, loggerHook := test.NewNullLogger() - logger.SetLevel(logrus.DebugLevel) - - runner := NewRunner(cfg, logger, praefect.StaticHealthChecker{virtualStorage: []string{storage1}}, nodeSet.Connections(), storageCleanup, storageCleanup, actionStub{ - PerformMethod: func(ctx context.Context, notExisting []datastore.RepositoryClusterPath) error { - assert.FailNow(t, "should not be triggered as there is no available storages to acquire") - return nil - }, - }) - - ctx, cancel := testhelper.Context() - defer cancel() - ticker := helper.NewManualTicker() - - <-startSecond - go func() { - defer wg.Done() - assert.Equal(t, context.Canceled, runner.Run(ctx, ticker)) - }() - ticker.Tick() - ticker.Tick() - close(releaseFirst) - cancel() - wg.Wait() - - entries := loggerHook.AllEntries() - require.Greater(t, len(entries), 2) - require.Equal( - t, - map[string]interface{}{"Data": logrus.Fields{"component": "repocleaner.repository_existence"}, "Message": "no storages to verify"}, - map[string]interface{}{"Data": loggerHook.AllEntries()[1].Data, "Message": loggerHook.AllEntries()[1].Message}, - ) - }() - - ticker := helper.NewManualTicker() - go func() { - defer wg.Done() - assert.Equal(t, context.Canceled, runner.Run(ctx, ticker)) - }() - ticker.Tick() - ticker.Tick() // blocks until first processing cycle is done - cancel() - wg.Wait() -} - -type actionStub struct { - PerformMethod func(ctx context.Context, existence []datastore.RepositoryClusterPath) error -} - -func (as actionStub) Perform(ctx context.Context, existence []datastore.RepositoryClusterPath) error { - if as.PerformMethod != nil { - return as.PerformMethod(ctx, existence) - } - return nil -} diff --git a/internal/praefect/repository_exists.go b/internal/praefect/repository_exists.go index bbafff823..f8ae301cc 100644 --- a/internal/praefect/repository_exists.go +++ b/internal/praefect/repository_exists.go @@ -16,10 +16,14 @@ var ( errMissingRelativePath = status.Error(codes.InvalidArgument, "repository missing relative path") ) -// RepositoryExistsHandler handles /gitaly.RepositoryService/RepositoryExists calls by checking -// whether there is a record of the repository in the database. -func RepositoryExistsHandler(rs datastore.RepositoryStore) grpc.StreamHandler { - return func(srv interface{}, stream grpc.ServerStream) error { +// RepositoryExistsStreamInterceptor returns a stream interceptor that handles /gitaly.RepositoryService/RepositoryExists +// calls by checking whether there is a record of the repository in the database. +func RepositoryExistsStreamInterceptor(rs datastore.RepositoryStore) grpc.StreamServerInterceptor { + return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + if info.FullMethod != "/gitaly.RepositoryService/RepositoryExists" { + return handler(srv, stream) + } + var req gitalypb.RepositoryExistsRequest if err := stream.RecvMsg(&req); err != nil { return fmt.Errorf("receive request: %w", err) diff --git a/internal/praefect/repository_exists_test.go b/internal/praefect/repository_exists_test.go index 45e315299..a5e894eaf 100644 --- a/internal/praefect/repository_exists_test.go +++ b/internal/praefect/repository_exists_test.go @@ -20,7 +20,7 @@ import ( "google.golang.org/grpc/status" ) -func TestRepositoryExistsHandler(t *testing.T) { +func TestRepositoryExistsStreamInterceptor(t *testing.T) { t.Parallel() errServedByGitaly := status.Error(codes.Unknown, "request passed to Gitaly") @@ -76,18 +76,22 @@ func TestRepositoryExistsHandler(t *testing.T) { require.NoError(t, rs.CreateRepository(ctx, 0, "virtual-storage", "relative-path", "storage", nil, nil, false, false)) - tmp := testhelper.TempDir(t) - - ln, err := net.Listen("unix", filepath.Join(tmp, "praefect")) - require.NoError(t, err) - electionStrategy := config.ElectionStrategyPerRepository if tc.routeToGitaly { electionStrategy = config.ElectionStrategySQL } + tmp := testhelper.TempDir(t) + + ln, err := net.Listen("unix", filepath.Join(tmp, "praefect")) + require.NoError(t, err) + srv := NewGRPCServer( - config.Config{Failover: config.Failover{ElectionStrategy: electionStrategy}}, + config.Config{ + Failover: config.Failover{ + ElectionStrategy: electionStrategy, + }, + }, testhelper.DiscardTestEntry(t), protoregistry.GitalyProtoPreregistered, func(ctx context.Context, fullMethodName string, peeker proxy.StreamPeeker) (*proxy.StreamParameters, error) { diff --git a/internal/praefect/server.go b/internal/praefect/server.go index 7e9570a2e..4eb4b1c4c 100644 --- a/internal/praefect/server.go +++ b/internal/praefect/server.go @@ -106,6 +106,10 @@ func NewGRPCServer( panichandler.StreamPanicHandler, } + if conf.Failover.ElectionStrategy == config.ElectionStrategyPerRepository { + streamInterceptors = append(streamInterceptors, RepositoryExistsStreamInterceptor(rs)) + } + grpcOpts = append(grpcOpts, proxyRequiredOpts(director)...) grpcOpts = append(grpcOpts, []grpc.ServerOption{ grpc.StreamInterceptor(grpcmw.ChainStreamServer(streamInterceptors...)), @@ -126,13 +130,6 @@ func NewGRPCServer( srv := grpc.NewServer(grpcOpts...) registerServices(srv, nodeMgr, txMgr, conf, queue, rs, assignmentStore, service.Connections(conns), primaryGetter) - - if conf.Failover.ElectionStrategy == config.ElectionStrategyPerRepository { - proxy.RegisterStreamHandlers(srv, "gitaly.RepositoryService", map[string]grpc.StreamHandler{ - "RepositoryExists": RepositoryExistsHandler(rs), - }) - } - return srv } diff --git a/internal/praefect/server_test.go b/internal/praefect/server_test.go index e824cb600..4f95c1dee 100644 --- a/internal/praefect/server_test.go +++ b/internal/praefect/server_test.go @@ -534,7 +534,20 @@ func TestRemoveRepository(t *testing.T) { verifyReposExistence(t, codes.OK) + // TODO: once https://gitlab.com/gitlab-org/gitaly/-/issues/2703 is done and the replication manager supports + // graceful shutdown, we can remove this code that waits for jobs to be complete queueInterceptor := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(glsql.NewDB(t))) + jobsDoneCh := make(chan struct{}, 2) + queueInterceptor.OnAcknowledge(func(ctx context.Context, state datastore.JobState, ids []uint64, queue datastore.ReplicationEventQueue) ([]uint64, error) { + defer func() { + if state == datastore.JobStateCompleted { + jobsDoneCh <- struct{}{} + } + }() + + return queue.Acknowledge(ctx, state, ids) + }) + repoStore := defaultRepoStore(praefectCfg) txMgr := defaultTxMgr(praefectCfg) nodeMgr, err := nodes.NewManager(testhelper.DiscardTestEntry(t), praefectCfg, nil, @@ -566,15 +579,9 @@ func TestRemoveRepository(t *testing.T) { }) require.NoError(t, err) - require.NoError(t, queueInterceptor.Wait(time.Minute, func(i *datastore.ReplicationEventQueueInterceptor) bool { - var compl int - for _, ack := range i.GetAcknowledge() { - if ack.State == datastore.JobStateCompleted { - compl++ - } - } - return compl == 2 - })) + for i := 0; i < cap(jobsDoneCh); i++ { + <-jobsDoneCh + } verifyReposExistence(t, codes.NotFound) } @@ -601,7 +608,7 @@ func TestRenameRepository(t *testing.T) { repoPaths := make([]string, len(gitalyStorages)) praefectCfg := config.Config{ VirtualStorages: []*config.VirtualStorage{{Name: "praefect"}}, - Failover: config.Failover{Enabled: true, ElectionStrategy: config.ElectionStrategyPerRepository}, + Failover: config.Failover{Enabled: true}, } var repo *gitalypb.Repository @@ -625,14 +632,19 @@ func TestRenameRepository(t *testing.T) { repoPaths[i] = filepath.Join(gitalyCfg.Storages[0].Path, relativePath) } + var canCheckRepo sync.WaitGroup + canCheckRepo.Add(2) + evq := datastore.NewReplicationEventQueueInterceptor(datastore.NewPostgresReplicationEventQueue(glsql.NewDB(t))) + evq.OnAcknowledge(func(ctx context.Context, state datastore.JobState, ids []uint64, queue datastore.ReplicationEventQueue) ([]uint64, error) { + defer canCheckRepo.Done() + return queue.Acknowledge(ctx, state, ids) + }) + ctx, cancel := testhelper.Context() defer cancel() - cc, _, cleanup := runPraefectServer(t, ctx, praefectCfg, buildOptions{ - withQueue: evq, - withRepoStore: datastore.NewPostgresRepositoryStore(glsql.NewDB(t), nil), - }) + cc, _, cleanup := runPraefectServer(t, ctx, praefectCfg, buildOptions{withQueue: evq}) defer cleanup() // virtualRepo is a virtual repository all requests to it would be applied to the underline Gitaly nodes behind it @@ -662,9 +674,7 @@ func TestRenameRepository(t *testing.T) { // wait until replication jobs propagate changes to other storages // as we don't know which one will be used to check because of reads distribution - require.NoError(t, evq.Wait(time.Minute, func(i *datastore.ReplicationEventQueueInterceptor) bool { - return len(i.GetAcknowledge()) == 2 - })) + canCheckRepo.Wait() for _, oldLocation := range repoPaths { pollUntilRemoved(t, oldLocation, time.After(10*time.Second)) diff --git a/internal/protoutil/extension.go b/internal/protoutil/extension.go index 9e2e9f9a0..33a294716 100644 --- a/internal/protoutil/extension.go +++ b/internal/protoutil/extension.go @@ -21,19 +21,9 @@ func GetOpExtension(m *descriptorpb.MethodDescriptorProto) (*gitalypb.OperationM return ext.(*gitalypb.OperationMsg), nil } -// IsInterceptedMethod returns whether the RPC method is intercepted by Praefect. -func IsInterceptedMethod(s *descriptorpb.ServiceDescriptorProto, m *descriptorpb.MethodDescriptorProto) (bool, error) { - isServiceIntercepted, err := getBoolExtension(s.GetOptions(), gitalypb.E_Intercepted) - if err != nil { - return false, fmt.Errorf("is service intercepted: %w", err) - } - - isMethodIntercepted, err := getBoolExtension(m.GetOptions(), gitalypb.E_InterceptedMethod) - if err != nil { - return false, fmt.Errorf("is method intercepted: %w", err) - } - - return isServiceIntercepted || isMethodIntercepted, nil +// IsInterceptedService returns whether the serivce is intercepted by Praefect. +func IsInterceptedService(s *descriptorpb.ServiceDescriptorProto) (bool, error) { + return getBoolExtension(s.GetOptions(), gitalypb.E_Intercepted) } // GetRepositoryExtension gets the repository extension from a field descriptor diff --git a/internal/sidechannel/conn.go b/internal/sidechannel/conn.go deleted file mode 100644 index 5af660fab..000000000 --- a/internal/sidechannel/conn.go +++ /dev/null @@ -1,181 +0,0 @@ -package sidechannel - -import ( - "fmt" - "io" - "net" - - "gitlab.com/gitlab-org/gitaly/v14/internal/git/pktline" - "gitlab.com/gitlab-org/gitaly/v14/streamio" -) - -// ServerConn and ClientConn implement an asymmetric framing protocol to -// exchange data between clients and servers in Sidechannel. A typical flow -// looks like following: -// - The client writes data into the connecton. -// - The client half-closes the connection. The server is aware of this event -// when reading operations return EOF. -// - The server writes the data back to the client, then close the connection. -// - The client read the data until EOF -// -// Half-close ability is important to signal the server that the client -// finishes data transformation. As sidechannel is built on top of Yamux -// stream, half-close ability is not supported. Therefore, we apply a -// length-prefix framing protocol, simiarly to Git pktline protocol, except we -// omit the band number. The close or half-close event are signaled by sending -// a flush packet. -// -// This is an example of the data written into the wire: -// -// | 4-byte length, including size of length itself. -// v -// 0009Hello0000 -// ^ -// | Flush packet signaling a half-close event -// -// Many methods in battle-tested pktline package are re-used to save us some -// times. At the moment, we don't need server-client half-closed ability. And -// it may affect the performance when wrapping huge data sent from the server. - -const ( - // maxChunkSize is the maximum chunk size of data. The chunk size must include 4-byte - // length prefix. This constant is different from MaxSidebandData because - // we don't include the sideband number. - maxChunkSize = pktline.MaxPktSize - 4 -) - -// ServerConn is a wrapper around net.Conn with the support of half-closed -// capacity for sidechannel. This struct is expected to be used by -// sidechannel's server only. -type ServerConn struct { - conn net.Conn - r io.Reader -} - -func newServerConn(c net.Conn) *ServerConn { - scanner := pktline.NewScanner(c) - reader := streamio.NewReader(func() ([]byte, error) { - if !scanner.Scan() { - if err := scanner.Err(); err != nil { - return nil, err - } - // If there is any error while scanning, scanner.Err() returns a - // non-nil error. If scanner.Err() returns nil, the connection - // reaches end-of-file. However, the effect of returning io.EOF is - // that we allow two kinds of streams: "000fhello world0000" (with - // trailing 0000) and "000fhello world" (without trialing 0000). - // Having optional behaviors like this is a source of complexity. - // We should not allow "000fhello world" without the trailing 0000. - return nil, io.ErrUnexpectedEOF - } - - if pktline.IsFlush(scanner.Bytes()) { - return nil, io.EOF - } - - data := scanner.Bytes() - if len(data) < 4 { - return nil, fmt.Errorf("sidechannel: invalid packet %q", data) - } - - // pktline treats 0001, 0002, or 0003 as magic empty packets - // They are irrelevant to sidechannel, hence should be rejected - if len(data) == 4 { - if s := string(data); s == "0001" || s == "0002" || s == "0003" { - return nil, fmt.Errorf("sidechannel: invalid header %s", string(data[3])) - } - } - - return data[4:], nil - }) - - return &ServerConn{conn: c, r: reader} -} - -// Read reads up to len(p) bytes into p. It returns the number of bytes read or -// any error encountered. This struct overrides Read() to extract the data -// wrapped in a frame generated by ClientConn.Write(). -func (cc *ServerConn) Read(p []byte) (n int, err error) { - return cc.r.Read(p) -} - -// Write writes data to the connection. This method fallbacks to underlying -// connection without any modificiation. -func (cc *ServerConn) Write(b []byte) (n int, err error) { - return cc.conn.Write(b) -} - -// Close closes the connection. This method fallbacks to underlying -// connection without any modificiation. -func (cc *ServerConn) Close() error { - return cc.conn.Close() -} - -// ClientConn is a wrapper around net.Conn with the support of half-closed -// capacity for sidechannel. This struct is expected to use by sidechannel's -// client only. -type ClientConn struct { - conn net.Conn - writeClosed bool -} - -func newClientConn(c net.Conn) *ClientConn { - return &ClientConn{conn: c} -} - -// Read reads data from the connection. This method fallbacks to underlying -// connection without any modificiation. -func (cc *ClientConn) Read(b []byte) (n int, err error) { - return cc.conn.Read(b) -} - -// Write writes len(p) bytes from p to the underlying data stream. It returns -// the number of bytes written from p and any error encountered that caused the -// write to stop early. This method overrides Write() to wrap the writing data -// into a frame. The frame is then extracted and read by ServerConn.Read(). -func (cc *ClientConn) Write(p []byte) (int, error) { - if cc.writeClosed { - return 0, fmt.Errorf("sidechannel: write into a half-closed connection") - } - - var n int - - for len(p) > 0 { - chunk := maxChunkSize - if len(p) < chunk { - chunk = len(p) - } - - if _, err := fmt.Fprintf(cc.conn, "%04x", chunk+4); err != nil { - return n, err - } - if _, err := cc.conn.Write(p[:chunk]); err != nil { - return n, err - } - n += chunk - p = p[chunk:] - } - - return n, nil -} - -func (cc *ClientConn) close() error { - return cc.conn.Close() -} - -// CloseWrite shuts down the writing side of the connection. After this call, -// any read operations from the server return EOF. The reading side is still -// functional so that the server is still able to write back to the client. Any -// attempt to write into a half-closed connection returns an error. -func (cc *ClientConn) CloseWrite() error { - if cc.writeClosed { - return nil - } - - cc.writeClosed = true - if err := pktline.WriteFlush(cc.conn); err != nil { - return err - } - - return nil -} diff --git a/internal/sidechannel/conn_test.go b/internal/sidechannel/conn_test.go deleted file mode 100644 index 257fd4273..000000000 --- a/internal/sidechannel/conn_test.go +++ /dev/null @@ -1,179 +0,0 @@ -package sidechannel - -import ( - "fmt" - "io" - "net" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestClientWrite(t *testing.T) { - largeString := strings.Repeat("a", maxChunkSize) - - testCases := []struct { - desc string - in string - out string - err error - }{ - {desc: "empty", out: ""}, - {desc: "1-byte string", in: "h", out: "0005h"}, - {desc: "short string", in: "hello", out: "0009hello"}, - {desc: "short string 2", in: "hello this world", out: "0014hello this world"}, - { - desc: "large string", - in: largeString, - out: "fff0" + largeString, - }, - { - desc: "very large string", - in: largeString + "b", - out: "fff0" + largeString + "0005b", - }, - } - - type result struct { - data string - err error - } - - for _, tc := range testCases { - t.Run(tc.desc, func(t *testing.T) { - client, server := net.Pipe() - ch := make(chan result, 1) - go func() { - out, err := io.ReadAll(server) - ch <- result{data: string(out), err: err} - }() - - cc := newClientConn(client) - written, err := cc.Write([]byte(tc.in)) - if tc.err != nil { - require.Equal(t, tc.err, err) - return - } - - require.NoError(t, err) - require.NoError(t, cc.close()) - require.Equal(t, written, len(tc.in)) - - res := <-ch - require.NoError(t, res.err) - require.Equal(t, tc.out, res.data) - }) - } -} - -func TestServerRead(t *testing.T) { - largeString := strings.Repeat("a", maxChunkSize) - - testCases := []struct { - desc string - in string - out string - err error - }{ - {desc: "empty", in: "0000", out: ""}, - {desc: "empty 2", in: "00040000", out: ""}, - {desc: "1-byte string", in: "0005h0000", out: "h"}, - {desc: "short string", in: "0009hello0000", out: "hello"}, - {desc: "short string 2", in: "0014hello this world0000", out: "hello this world"}, - {desc: "invalid header 1", in: "0001", err: fmt.Errorf("sidechannel: invalid header 1")}, - {desc: "invalid header 2", in: "0002", err: fmt.Errorf("sidechannel: invalid header 2")}, - {desc: "invalid header 3", in: "0003", err: fmt.Errorf("sidechannel: invalid header 3")}, - {desc: "multiple short strings", in: "0009hello0008this0009world0000", out: "hellothisworld"}, - { - desc: "large string", - in: "fff0" + largeString + "0000", - out: largeString, - }, - { - desc: "very large string", - in: "fff0" + largeString + "0005b0000", - out: largeString + "b", - }, - {desc: "flush packet", in: "0009hello0000trashtrash", out: "hello"}, - {desc: "unexpected closed without trailing 0000", in: "0009hello", err: io.ErrUnexpectedEOF}, - } - - type result struct { - data string - err error - } - - for _, tc := range testCases { - t.Run(tc.desc, func(t *testing.T) { - client, server := net.Pipe() - ch := make(chan result, 1) - - go func() { - cc := newServerConn(server) - out, err := io.ReadAll(cc) - ch <- result{data: string(out), err: err} - }() - - written, err := client.Write([]byte(tc.in)) - require.Equal(t, written, len(tc.in)) - require.NoError(t, err) - - client.Close() - - res := <-ch - if tc.err != nil { - require.Equal(t, tc.err, res.err) - return - } - - require.NoError(t, res.err) - require.Equal(t, tc.out, res.data) - }) - } -} - -func TestHalfClose(t *testing.T) { - type result struct { - data string - err error - } - - client, server := net.Pipe() - clientCc := newClientConn(client) - serverCc := newServerConn(server) - - ch := make(chan result, 1) - - go func() { - out, err := io.ReadAll(serverCc) - ch <- result{data: string(out), err: err} - }() - - written, err := clientCc.Write([]byte("Ping")) - require.Equal(t, written, 4) - require.NoError(t, err) - - require.NoError(t, clientCc.CloseWrite()) - - res := <-ch - require.NoError(t, res.err) - require.Equal(t, "Ping", res.data) - - _, err = clientCc.Write([]byte("Should not be sent")) - require.EqualError(t, err, "sidechannel: write into a half-closed connection") - - go func() { - out, err := io.ReadAll(clientCc) - ch <- result{data: string(out), err: err} - }() - - _, err = serverCc.Write([]byte("Pong")) - require.NoError(t, err) - - serverCc.Close() - - res = <-ch - require.NoError(t, res.err) - require.Equal(t, "Pong", res.data) -} diff --git a/internal/sidechannel/proxy.go b/internal/sidechannel/proxy.go deleted file mode 100644 index 2302d44eb..000000000 --- a/internal/sidechannel/proxy.go +++ /dev/null @@ -1,126 +0,0 @@ -package sidechannel - -import ( - "context" - "fmt" - "io" - - "gitlab.com/gitlab-org/gitaly/v14/internal/metadata" - "google.golang.org/grpc" - grpcMetadata "google.golang.org/grpc/metadata" -) - -// NewUnaryProxy creates a gRPC client middleware that proxies sidechannels. -func NewUnaryProxy(registry *Registry) grpc.UnaryClientInterceptor { - return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - if !hasSidechannelMetadata(ctx) { - return invoker(ctx, method, req, reply, cc, opts...) - } - - ctx, waiter := RegisterSidechannel(ctx, registry, proxy(ctx)) - defer waiter.Close() - - if err := invoker(ctx, method, req, reply, cc, opts...); err != nil { - return err - } - if err := waiter.Close(); err != nil && err != ErrCallbackDidNotRun { - return fmt.Errorf("sidechannel: proxy callback: %w", err) - } - return nil - } -} - -// NewStreamProxy creates a gRPC client middleware that proxies sidechannels. -func NewStreamProxy(registry *Registry) grpc.StreamClientInterceptor { - return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { - if !hasSidechannelMetadata(ctx) { - return streamer(ctx, desc, cc, method, opts...) - } - - ctx, waiter := RegisterSidechannel(ctx, registry, proxy(ctx)) - go func() { - <-ctx.Done() - // The Close() error is checked and bubbled up in - // streamWrapper.RecvMsg(). This call is just for cleanup. - _ = waiter.Close() - }() - - cs, err := streamer(ctx, desc, cc, method, opts...) - if err != nil { - return nil, err - } - - return &streamWrapper{ClientStream: cs, waiter: waiter}, nil - } -} - -type streamWrapper struct { - grpc.ClientStream - waiter *Waiter -} - -func (sw *streamWrapper) RecvMsg(m interface{}) error { - if err := sw.ClientStream.RecvMsg(m); err != io.EOF { - return err - } - - if err := sw.waiter.Close(); err != nil && err != ErrCallbackDidNotRun { - return fmt.Errorf("sidechannel: proxy callback: %w", err) - } - - return io.EOF -} - -func hasSidechannelMetadata(ctx context.Context) bool { - md, ok := grpcMetadata.FromOutgoingContext(ctx) - return ok && len(md.Get(sidechannelMetadataKey)) > 0 -} - -func proxy(ctx context.Context) func(*ClientConn) error { - return func(upstream *ClientConn) error { - downstream, err := OpenSidechannel(metadata.OutgoingToIncoming(ctx)) - if err != nil { - return err - } - defer downstream.Close() - - const nStreams = 2 - errC := make(chan error, nStreams) - - go func() { - errC <- func() error { - if _, err := io.Copy(upstream, downstream); err != nil { - return err - } - - // Downstream.Read() has returned EOF. That means we are done proxying - // the request body from downstream to upstream. Propagate this EOF to - // upstream by calling CloseWrite(). Use CloseWrite(), not Close(), - // because we still want to read the response body from upstream in the - // other goroutine. - return upstream.CloseWrite() - }() - }() - - go func() { - errC <- func() error { - if _, err := io.Copy(downstream, upstream); err != nil { - return err - } - - // Upstream is now closed for both reads and writes. Propagate this state - // to downstream. This also happens via defer, but this way we can log - // the Close error if there is one. - return downstream.Close() - }() - }() - - for i := 0; i < nStreams; i++ { - if err := <-errC; err != nil { - return err - } - } - - return nil - } -} diff --git a/internal/sidechannel/proxy_test.go b/internal/sidechannel/proxy_test.go deleted file mode 100644 index 1501a02d3..000000000 --- a/internal/sidechannel/proxy_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package sidechannel - -import ( - "context" - "fmt" - "io" - "net" - "testing" - - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" - "gitlab.com/gitlab-org/gitaly/v14/internal/listenmux" - "gitlab.com/gitlab-org/gitaly/v14/internal/metadata" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" - "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - healthpb "google.golang.org/grpc/health/grpc_health_v1" -) - -func testProxyServer(ctx context.Context) (err error) { - conn, err := OpenSidechannel(ctx) - if err != nil { - return err - } - defer conn.Close() - - buf, err := io.ReadAll(conn) - if err != nil { - return fmt.Errorf("server read: %w", err) - } - if string(buf) != "hello" { - return fmt.Errorf("server: unexpected request: %q", buf) - } - - if _, err := io.WriteString(conn, "world"); err != nil { - return fmt.Errorf("server write: %w", err) - } - if err := conn.Close(); err != nil { - return fmt.Errorf("server close: %w", err) - } - - return nil -} - -func testProxyClient(conn *ClientConn) (err error) { - if _, err := io.WriteString(conn, "hello"); err != nil { - return fmt.Errorf("client write: %w", err) - } - if err := conn.CloseWrite(); err != nil { - return err - } - - buf, err := io.ReadAll(conn) - if err != nil { - return fmt.Errorf("client read: %w", err) - } - if string(buf) != "world" { - return fmt.Errorf("client: unexpected response: %q", buf) - } - - return nil -} - -func TestUnaryProxy(t *testing.T) { - upstreamAddr := startServer( - t, - func(ctx context.Context, request *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { - if err := testProxyServer(ctx); err != nil { - return nil, err - } - return &healthpb.HealthCheckResponse{}, nil - }, - ) - - proxyAddr := startServer( - t, - func(ctx context.Context, request *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) { - conn, err := dialProxy(upstreamAddr) - if err != nil { - return nil, err - } - defer conn.Close() - - ctxOut := metadata.IncomingToOutgoing(ctx) - return healthpb.NewHealthClient(conn).Check(ctxOut, request) - }, - ) - - ctx, cancel := testhelper.Context() - defer cancel() - - conn, registry := dial(t, proxyAddr) - require.NoError(t, call(ctx, conn, registry, testProxyClient)) -} - -func newLogger() *logrus.Entry { return logrus.NewEntry(logrus.New()) } - -func dialProxy(upstreamAddr string) (*grpc.ClientConn, error) { - registry := NewRegistry() - factory := func() backchannel.Server { - lm := listenmux.New(insecure.NewCredentials()) - lm.Register(NewServerHandshaker(registry)) - return grpc.NewServer(grpc.Creds(lm)) - } - - clientHandshaker := backchannel.NewClientHandshaker(newLogger(), factory) - dialOpts := []grpc.DialOption{ - grpc.WithTransportCredentials(clientHandshaker.ClientHandshake(insecure.NewCredentials())), - grpc.WithUnaryInterceptor(NewUnaryProxy(registry)), - grpc.WithStreamInterceptor(NewStreamProxy(registry)), - } - - return grpc.Dial(upstreamAddr, dialOpts...) -} - -func TestStreamProxy(t *testing.T) { - upstreamAddr := startStreamServer( - t, - func(stream gitalypb.SSHService_SSHUploadPackServer) error { - return testProxyServer(stream.Context()) - }, - ) - - proxyAddr := startStreamServer( - t, - func(stream gitalypb.SSHService_SSHUploadPackServer) error { - conn, err := dialProxy(upstreamAddr) - if err != nil { - return err - } - defer conn.Close() - - ctxOut := metadata.IncomingToOutgoing(stream.Context()) - client, err := gitalypb.NewSSHServiceClient(conn).SSHUploadPack(ctxOut) - if err != nil { - return err - } - - if _, err := client.Recv(); err != io.EOF { - return fmt.Errorf("grpc proxy recv: %w", err) - } - - return nil - }, - ) - - ctx, cancel := testhelper.Context() - defer cancel() - - conn, registry := dial(t, proxyAddr) - ctx, waiter := RegisterSidechannel(ctx, registry, testProxyClient) - defer waiter.Close() - - client, err := gitalypb.NewSSHServiceClient(conn).SSHUploadPack(ctx) - require.NoError(t, err) - - _, err = client.Recv() - require.Equal(t, io.EOF, err) - - require.NoError(t, waiter.Close()) -} - -type mockSSHService struct { - sshUploadPackFunc func(gitalypb.SSHService_SSHUploadPackServer) error - gitalypb.UnimplementedSSHServiceServer -} - -func (m mockSSHService) SSHUploadPack(stream gitalypb.SSHService_SSHUploadPackServer) error { - return m.sshUploadPackFunc(stream) -} - -func startStreamServer(t *testing.T, handler func(gitalypb.SSHService_SSHUploadPackServer) error) string { - t.Helper() - - lm := listenmux.New(insecure.NewCredentials()) - lm.Register(backchannel.NewServerHandshaker( - newLogger(), backchannel.NewRegistry(), nil, - )) - - srv := grpc.NewServer(grpc.Creds(lm)) - gitalypb.RegisterSSHServiceServer(srv, &mockSSHService{ - sshUploadPackFunc: handler, - }) - - ln, err := net.Listen("tcp", "localhost:0") - require.NoError(t, err) - - t.Cleanup(srv.Stop) - go srv.Serve(ln) - return ln.Addr().String() -} diff --git a/internal/sidechannel/registry.go b/internal/sidechannel/registry.go index 3148cb05d..32985a9a1 100644 --- a/internal/sidechannel/registry.go +++ b/internal/sidechannel/registry.go @@ -1,11 +1,9 @@ package sidechannel import ( - "errors" "fmt" "net" "sync" - "time" ) // sidechannelID is the type of ID used to differeniate sidechannel connections @@ -25,10 +23,9 @@ type Registry struct { type Waiter struct { id sidechannelID registry *Registry - err error - done chan struct{} + errC chan error accept chan net.Conn - callback func(*ClientConn) error + callback func(net.Conn) error } // NewRegistry returns a new Registry instance @@ -43,23 +40,20 @@ func NewRegistry() *Registry { // connection arrives, the callback function is executed with arrived // connection in a new goroutine. The caller receives execution result via // waiter.Wait(). -func (s *Registry) Register(callback func(*ClientConn) error) *Waiter { +func (s *Registry) Register(callback func(net.Conn) error) *Waiter { s.mu.Lock() defer s.mu.Unlock() waiter := &Waiter{ id: s.nextID, registry: s, - done: make(chan struct{}), + errC: make(chan error), accept: make(chan net.Conn), callback: callback, } s.nextID++ - go func() { - defer close(waiter.done) - waiter.err = waiter.run() - }() + go waiter.run() s.waiters[waiter.id] = waiter return waiter } @@ -105,37 +99,23 @@ func (s *Registry) waiting() int { return len(s.waiters) } -// ErrCallbackDidNotRun indicates that a sidechannel callback was -// de-registered without having run. This can happen if the server chose -// not to use the sidechannel. -var ErrCallbackDidNotRun = errors.New("sidechannel: callback de-registered without having run") - -func (w *Waiter) run() error { - conn := <-w.accept - if conn == nil { - return ErrCallbackDidNotRun - } - defer conn.Close() +func (w *Waiter) run() { + defer close(w.errC) - if err := conn.SetWriteDeadline(time.Now().Add(sidechannelTimeout)); err != nil { - return err - } - if _, err := conn.Write([]byte("ok")); err != nil { - return err + if conn := <-w.accept; conn != nil { + defer conn.Close() + w.errC <- w.callback(conn) } - if err := conn.SetWriteDeadline(time.Time{}); err != nil { - return err - } - - return w.callback(newClientConn(conn)) } -// Close de-registers the callback. If the callback got triggered, -// Close() will return its error return value. If the callback has not -// started by the time Close() is called, Close() returns -// ErrCallbackDidNotRun. +// Close cleans the waiter, removes it from the registry. If the callback is +// executing, this method is blocked until the callback is done. func (w *Waiter) Close() error { w.registry.removeWaiter(w) - <-w.done - return w.err + return <-w.errC +} + +// Wait waits until either the callback is executed, or the waiter is closed +func (w *Waiter) Wait() error { + return <-w.errC } diff --git a/internal/sidechannel/registry_test.go b/internal/sidechannel/registry_test.go index 032534a81..07d2f85c1 100644 --- a/internal/sidechannel/registry_test.go +++ b/internal/sidechannel/registry_test.go @@ -4,10 +4,8 @@ import ( "fmt" "io" "net" - "os" "strconv" "sync" - "syscall" "testing" "github.com/stretchr/testify/require" @@ -19,7 +17,7 @@ func TestRegistry(t *testing.T) { t.Run("waiter removed from the registry right after connection received", func(t *testing.T) { triggerCallback := make(chan struct{}) - waiter := registry.Register(func(conn *ClientConn) error { + waiter := registry.Register(func(conn net.Conn) error { <-triggerCallback return nil }) @@ -27,38 +25,34 @@ func TestRegistry(t *testing.T) { require.Equal(t, 1, registry.waiting()) - client, _ := socketPair(t) + client, _ := net.Pipe() require.NoError(t, registry.receive(waiter.id, client)) require.Equal(t, 0, registry.waiting()) close(triggerCallback) - require.NoError(t, waiter.Close()) + require.NoError(t, waiter.Wait()) requireConnClosed(t, client) }) - t.Run("receive connections successfully", func(t *testing.T) { + t.Run("pull connections successfully", func(t *testing.T) { wg := sync.WaitGroup{} - servers := make([]net.Conn, N) + var servers []net.Conn for i := 0; i < N; i++ { - client, server := socketPair(t) - servers[i] = server - defer server.Close() + client, server := net.Pipe() + servers = append(servers, server) wg.Add(1) go func(i int) { - waiter := registry.Register(func(conn *ClientConn) error { - if _, err := fmt.Fprintf(conn, "%d", i); err != nil { - return err - } - - return conn.CloseWrite() + waiter := registry.Register(func(conn net.Conn) error { + _, err := fmt.Fprintf(conn, "%d", i) + return err }) defer waiter.Close() require.NoError(t, registry.receive(waiter.id, client)) - require.NoError(t, waiter.Close()) + require.NoError(t, waiter.Wait()) requireConnClosed(t, client) wg.Done() @@ -66,14 +60,7 @@ func TestRegistry(t *testing.T) { } for i := 0; i < N; i++ { - // Read registry confirmation - buf := make([]byte, 2) - _, err := io.ReadFull(servers[i], buf) - require.NoError(t, err) - require.Equal(t, "ok", string(buf)) - - // Read data written by callback - out, err := io.ReadAll(newServerConn(servers[i])) + out, err := io.ReadAll(servers[i]) require.NoError(t, err) require.Equal(t, strconv.Itoa(i), string(out)) } @@ -82,16 +69,16 @@ func TestRegistry(t *testing.T) { require.Equal(t, 0, registry.waiting()) }) - t.Run("receive connection for non-existing ID", func(t *testing.T) { - client, _ := socketPair(t) + t.Run("push connection to non-existing ID", func(t *testing.T) { + client, _ := net.Pipe() err := registry.receive(registry.nextID+1, client) require.EqualError(t, err, "sidechannel registry: ID not registered") requireConnClosed(t, client) }) t.Run("pre-maturely close the waiter", func(t *testing.T) { - waiter := registry.Register(func(conn *ClientConn) error { panic("never execute") }) - require.Equal(t, ErrCallbackDidNotRun, waiter.Close()) + waiter := registry.Register(func(conn net.Conn) error { panic("never execute") }) + require.NoError(t, waiter.Close()) require.Equal(t, 0, registry.waiting()) }) } @@ -99,23 +86,7 @@ func TestRegistry(t *testing.T) { func requireConnClosed(t *testing.T, conn net.Conn) { one := make([]byte, 1) _, err := conn.Read(one) - require.Errorf(t, err, "use of closed network connection") + require.EqualError(t, err, "io: read/write on closed pipe") _, err = conn.Write(one) - require.Errorf(t, err, "use of closed network connection") -} - -func socketPair(t *testing.T) (net.Conn, net.Conn) { - conns := make([]net.Conn, 2) - fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) - require.NoError(t, err) - - for i, fd := range fds[:] { - f := os.NewFile(uintptr(fd), "socket pair") - c, err := net.FileConn(f) - require.NoError(t, err) - require.NoError(t, f.Close()) - t.Cleanup(func() { c.Close() }) - conns[i] = c - } - return conns[0], conns[1] + require.EqualError(t, err, "io: read/write on closed pipe") } diff --git a/internal/sidechannel/sidechannel.go b/internal/sidechannel/sidechannel.go index 74c7d0ab8..c133fcc6e 100644 --- a/internal/sidechannel/sidechannel.go +++ b/internal/sidechannel/sidechannel.go @@ -4,18 +4,12 @@ import ( "context" "encoding/binary" "fmt" - "io" "net" "strconv" "time" - "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" - "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/client" - "gitlab.com/gitlab-org/gitaly/v14/internal/listenmux" - "google.golang.org/grpc" "google.golang.org/grpc/credentials" - "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" ) @@ -32,7 +26,7 @@ const ( // OpenSidechannel opens a sidechannel connection from the stream opener // extracted from the current peer connection. -func OpenSidechannel(ctx context.Context) (_ *ServerConn, err error) { +func OpenSidechannel(ctx context.Context) (_ net.Conn, err error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, fmt.Errorf("sidechannel: failed to extract incoming metadata") @@ -70,19 +64,11 @@ func OpenSidechannel(ctx context.Context) (_ *ServerConn, err error) { return nil, fmt.Errorf("sidechannel: write stream id: %w", err) } - buf := make([]byte, 2) - if _, err := io.ReadFull(stream, buf); err != nil { - return nil, fmt.Errorf("sidechannel: receive confirmation: %w", err) - } - if string(buf) != "ok" { - return nil, fmt.Errorf("sidechannel: expected ok, got %q", buf) - } - if err := stream.SetDeadline(time.Time{}); err != nil { return nil, err } - return newServerConn(stream), nil + return stream, nil } // RegisterSidechannel registers the caller into the waiting list of the @@ -90,7 +76,7 @@ func OpenSidechannel(ctx context.Context) (_ *ServerConn, err error) { // The caller is expected to establish the request with the returned context. The // callback is executed automatically when the sidechannel connection arrives. // The result is pushed to the error channel of the returned waiter. -func RegisterSidechannel(ctx context.Context, registry *Registry, callback func(*ClientConn) error) (context.Context, *Waiter) { +func RegisterSidechannel(ctx context.Context, registry *Registry, callback func(net.Conn) error) (context.Context, *Waiter) { waiter := registry.Register(callback) ctxOut := metadata.AppendToOutgoingContext(ctx, sidechannelMetadataKey, fmt.Sprintf("%d", waiter.id)) return ctxOut, waiter @@ -129,16 +115,3 @@ func (s *ServerHandshaker) Handshake(conn net.Conn, authInfo credentials.AuthInf func NewServerHandshaker(registry *Registry) *ServerHandshaker { return &ServerHandshaker{registry: registry} } - -// NewClientHandshaker is used to enable sidechannel support on outbound -// gRPC connections. -func NewClientHandshaker(logger *logrus.Entry, registry *Registry) client.Handshaker { - return backchannel.NewClientHandshaker( - logger, - func() backchannel.Server { - lm := listenmux.New(insecure.NewCredentials()) - lm.Register(NewServerHandshaker(registry)) - return grpc.NewServer(grpc.Creds(lm)) - }, - ) -} diff --git a/internal/sidechannel/sidechannel_test.go b/internal/sidechannel/sidechannel_test.go index 285765b51..c85517952 100644 --- a/internal/sidechannel/sidechannel_test.go +++ b/internal/sidechannel/sidechannel_test.go @@ -9,6 +9,7 @@ import ( "sync" "testing" + "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" "gitlab.com/gitlab-org/gitaly/v14/internal/listenmux" @@ -46,7 +47,7 @@ func TestSidechannel(t *testing.T) { conn, registry := dial(t, addr) err = call( context.Background(), conn, registry, - func(conn *ClientConn) error { + func(conn net.Conn) error { errC := make(chan error, 1) go func() { var err error @@ -112,7 +113,7 @@ func TestSidechannelConcurrency(t *testing.T) { err := call( context.Background(), conn, registry, - func(conn *ClientConn) error { + func(conn net.Conn) error { errC := make(chan error, 1) go func() { var err error @@ -144,8 +145,10 @@ func TestSidechannelConcurrency(t *testing.T) { func startServer(t *testing.T, th testHandler, opts ...grpc.ServerOption) string { t.Helper() + logger := logrus.NewEntry(logrus.New()) + lm := listenmux.New(insecure.NewCredentials()) - lm.Register(backchannel.NewServerHandshaker(newLogger(), backchannel.NewRegistry(), nil)) + lm.Register(backchannel.NewServerHandshaker(logger, backchannel.NewRegistry(), nil)) opts = append(opts, grpc.Creds(lm)) @@ -166,7 +169,15 @@ func startServer(t *testing.T, th testHandler, opts ...grpc.ServerOption) string func dial(t *testing.T, addr string) (*grpc.ClientConn, *Registry) { registry := NewRegistry() - clientHandshaker := NewClientHandshaker(newLogger(), registry) + logger := logrus.NewEntry(logrus.New()) + + factory := func() backchannel.Server { + lm := listenmux.New(insecure.NewCredentials()) + lm.Register(NewServerHandshaker(registry)) + return grpc.NewServer(grpc.Creds(lm)) + } + + clientHandshaker := backchannel.NewClientHandshaker(logger, factory) dialOpt := grpc.WithTransportCredentials(clientHandshaker.ClientHandshake(insecure.NewCredentials())) conn, err := grpc.Dial(addr, dialOpt) @@ -176,7 +187,7 @@ func dial(t *testing.T, addr string) (*grpc.ClientConn, *Registry) { return conn, registry } -func call(ctx context.Context, conn *grpc.ClientConn, registry *Registry, handler func(*ClientConn) error) error { +func call(ctx context.Context, conn *grpc.ClientConn, registry *Registry, handler func(net.Conn) error) error { client := healthpb.NewHealthClient(conn) ctxOut, waiter := RegisterSidechannel(ctx, registry, handler) @@ -186,7 +197,7 @@ func call(ctx context.Context, conn *grpc.ClientConn, registry *Registry, handle return err } - if err := waiter.Close(); err != nil { + if err := waiter.Wait(); err != nil { return err } diff --git a/internal/testhelper/testhelper.go b/internal/testhelper/testhelper.go index 30bd253ac..1c452e85a 100644 --- a/internal/testhelper/testhelper.go +++ b/internal/testhelper/testhelper.go @@ -1,5 +1,6 @@ package testhelper +//nolint: gci import ( "context" "crypto/ecdsa" @@ -30,8 +31,11 @@ import ( "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v14/internal/helper/text" "gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag" - "go.uber.org/goleak" "google.golang.org/grpc/metadata" + + // The goleak import only exists such that this test-only dependency is properly being + // attributed in our NOTICE file. + _ "go.uber.org/goleak" ) const ( @@ -43,14 +47,6 @@ const ( DefaultStorageName = "default" ) -// SkipWithPraefect skips the test if it is being executed with Praefect in front -// of the Gitaly. -func SkipWithPraefect(t testing.TB, reason string) { - if os.Getenv("GITALY_TEST_WITH_PRAEFECT") == "YesPlease" { - t.Skipf(reason) - } -} - // MustReadFile returns the content of a file or fails at once. func MustReadFile(t testing.TB, filename string) []byte { content, err := os.ReadFile(filename) @@ -165,18 +161,6 @@ func GetLocalhostListener(t testing.TB) (net.Listener, string) { return l, addr } -// MustHaveNoGoroutines panics if it finds any Goroutines running. -func MustHaveNoGoroutines() { - if err := goleak.Find( - // opencensus has a "defaultWorker" which is started by the package's - // `init()` function. There is no way to stop this worker, so it will leak - // whenever we import the package. - goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), - ); err != nil { - panic(fmt.Errorf("goroutines running: %w", err)) - } -} - // MustHaveNoChildProcess panics if it finds a running or finished child // process. It waits for 2 seconds for processes to be cleaned up by other // goroutines. diff --git a/internal/testhelper/testserver/gitaly.go b/internal/testhelper/testserver/gitaly.go index 7dac962f3..da8ddd92f 100644 --- a/internal/testhelper/testserver/gitaly.go +++ b/internal/testhelper/testserver/gitaly.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "testing" "time" @@ -72,17 +73,30 @@ func runPraefectProxy(t testing.TB, cfg config.Cfg, gitalyAddr, praefectBinPath praefectServerSocketPath := "unix://" + testhelper.GetTemporaryGitalySocketFileName(t) + pgport := os.Getenv("PGPORT") + port, err := strconv.Atoi(pgport) + require.NoError(t, err) + dbName := createDatabase(t) conf := praefectconfig.Config{ - SocketPath: praefectServerSocketPath, + AllowLegacyElectors: true, + SocketPath: praefectServerSocketPath, Auth: auth.Config{ Token: cfg.Auth.Token, }, - DB: glsql.GetDBConfig(t, dbName), + DB: praefectconfig.DB{ + Host: os.Getenv("PGHOST"), + Port: port, + User: os.Getenv("PGUSER"), + DBName: dbName, + SSLMode: "disable", + }, Failover: praefectconfig.Failover{ - Enabled: true, - ElectionStrategy: praefectconfig.ElectionStrategyLocal, + Enabled: true, + ElectionStrategy: praefectconfig.ElectionStrategyLocal, + BootstrapInterval: config.Duration(time.Microsecond), + MonitorInterval: config.Duration(time.Second), }, Replication: praefectconfig.DefaultReplicationConfig(), Logging: gitalylog.Config{ diff --git a/proto/go/gitalypb/lint.pb.go b/proto/go/gitalypb/lint.pb.go index cb57cecac..b0c1343c7 100644 --- a/proto/go/gitalypb/lint.pb.go +++ b/proto/go/gitalypb/lint.pb.go @@ -193,14 +193,6 @@ var file_lint_proto_extTypes = []protoimpl.ExtensionInfo{ Filename: "lint.proto", }, { - ExtendedType: (*descriptorpb.MethodOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 82304, - Name: "gitaly.intercepted_method", - Tag: "varint,82304,opt,name=intercepted_method", - Filename: "lint.proto", - }, - { ExtendedType: (*descriptorpb.FieldOptions)(nil), ExtensionType: (*bool)(nil), Field: 91233, @@ -250,11 +242,6 @@ var ( // // optional gitaly.OperationMsg op_type = 82303; E_OpType = &file_lint_proto_extTypes[1] - // intercepted_method indicates whether the proxy intercepts and handles the method call - // instead of proxying. Intercepted methods do not require operation type annotations. - // - // optional bool intercepted_method = 82304; - E_InterceptedMethod = &file_lint_proto_extTypes[2] ) // Extension fields to descriptorpb.FieldOptions. @@ -262,7 +249,7 @@ var ( // Used to mark field containing name of affected storage. // // optional bool storage = 91233; - E_Storage = &file_lint_proto_extTypes[3] // Random high number.. + E_Storage = &file_lint_proto_extTypes[2] // Random high number.. // If this operation modifies a repository, this annotations // will specify the location of the Repository field within // the request message. @@ -271,15 +258,15 @@ var ( // when parent message is marked as target or additional repository // // optional bool repository = 91234; - E_Repository = &file_lint_proto_extTypes[4] + E_Repository = &file_lint_proto_extTypes[3] // Used to mark target repository // // optional bool target_repository = 91235; - E_TargetRepository = &file_lint_proto_extTypes[5] + E_TargetRepository = &file_lint_proto_extTypes[4] // Used to mark additional repository // // optional bool additional_repository = 91236; - E_AdditionalRepository = &file_lint_proto_extTypes[6] + E_AdditionalRepository = &file_lint_proto_extTypes[5] ) var File_lint_proto protoreflect.FileDescriptor @@ -312,34 +299,29 @@ var file_lint_proto_rawDesc = []byte{ 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xff, 0x82, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x52, 0x06, 0x6f, 0x70, 0x54, - 0x79, 0x70, 0x65, 0x3a, 0x4f, 0x0a, 0x12, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, - 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x80, 0x83, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x3a, 0x39, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, - 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe1, - 0xc8, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x3a, - 0x3f, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe2, 0xc8, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x3a, 0x4c, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe3, 0xc8, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x3a, 0x54, - 0x0a, 0x15, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe4, 0xc8, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, - 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 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, 0x34, 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, + 0x79, 0x70, 0x65, 0x3a, 0x39, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x1d, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe1, 0xc8, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x3a, 0x3f, + 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe2, 0xc8, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x3a, + 0x4c, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0xe3, 0xc8, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x3a, 0x54, 0x0a, + 0x15, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe4, 0xc8, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, + 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 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, 0x34, 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 ( @@ -365,21 +347,20 @@ var file_lint_proto_goTypes = []interface{}{ (*descriptorpb.FieldOptions)(nil), // 5: google.protobuf.FieldOptions } var file_lint_proto_depIdxs = []int32{ - 0, // 0: gitaly.OperationMsg.op:type_name -> gitaly.OperationMsg.Operation - 1, // 1: gitaly.OperationMsg.scope_level:type_name -> gitaly.OperationMsg.Scope - 3, // 2: gitaly.intercepted:extendee -> google.protobuf.ServiceOptions - 4, // 3: gitaly.op_type:extendee -> google.protobuf.MethodOptions - 4, // 4: gitaly.intercepted_method:extendee -> google.protobuf.MethodOptions - 5, // 5: gitaly.storage:extendee -> google.protobuf.FieldOptions - 5, // 6: gitaly.repository:extendee -> google.protobuf.FieldOptions - 5, // 7: gitaly.target_repository:extendee -> google.protobuf.FieldOptions - 5, // 8: gitaly.additional_repository:extendee -> google.protobuf.FieldOptions - 2, // 9: gitaly.op_type:type_name -> gitaly.OperationMsg - 10, // [10:10] is the sub-list for method output_type - 10, // [10:10] is the sub-list for method input_type - 9, // [9:10] is the sub-list for extension type_name - 2, // [2:9] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 0, // 0: gitaly.OperationMsg.op:type_name -> gitaly.OperationMsg.Operation + 1, // 1: gitaly.OperationMsg.scope_level:type_name -> gitaly.OperationMsg.Scope + 3, // 2: gitaly.intercepted:extendee -> google.protobuf.ServiceOptions + 4, // 3: gitaly.op_type:extendee -> google.protobuf.MethodOptions + 5, // 4: gitaly.storage:extendee -> google.protobuf.FieldOptions + 5, // 5: gitaly.repository:extendee -> google.protobuf.FieldOptions + 5, // 6: gitaly.target_repository:extendee -> google.protobuf.FieldOptions + 5, // 7: gitaly.additional_repository:extendee -> google.protobuf.FieldOptions + 2, // 8: gitaly.op_type:type_name -> gitaly.OperationMsg + 9, // [9:9] is the sub-list for method output_type + 9, // [9:9] is the sub-list for method input_type + 8, // [8:9] is the sub-list for extension type_name + 2, // [2:8] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_lint_proto_init() } @@ -408,7 +389,7 @@ func file_lint_proto_init() { RawDescriptor: file_lint_proto_rawDesc, NumEnums: 2, NumMessages: 1, - NumExtensions: 7, + NumExtensions: 6, NumServices: 0, }, GoTypes: file_lint_proto_goTypes, diff --git a/proto/go/gitalypb/protolist.go b/proto/go/gitalypb/protolist.go index afb0510ae..a15916f70 100644 --- a/proto/go/gitalypb/protolist.go +++ b/proto/go/gitalypb/protolist.go @@ -9,7 +9,6 @@ var GitalyProtos = []string{ "commit.proto", "conflicts.proto", "diff.proto", - "errors.proto", "hook.proto", "internal.proto", "lint.proto", diff --git a/proto/go/gitalypb/repository-service.pb.go b/proto/go/gitalypb/repository-service.pb.go index 4b921c9bb..8ae73f4e4 100644 --- a/proto/go/gitalypb/repository-service.pb.go +++ b/proto/go/gitalypb/repository-service.pb.go @@ -115,7 +115,7 @@ func (x GetArchiveRequest_Format) Number() protoreflect.EnumNumber { // Deprecated: Use GetArchiveRequest_Format.Descriptor instead. func (GetArchiveRequest_Format) EnumDescriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{24, 0} + return file_repository_service_proto_rawDescGZIP(), []int{22, 0} } type GetRawChangesResponse_RawChange_Operation int32 @@ -176,7 +176,7 @@ func (x GetRawChangesResponse_RawChange_Operation) Number() protoreflect.EnumNum // Deprecated: Use GetRawChangesResponse_RawChange_Operation.Descriptor instead. func (GetRawChangesResponse_RawChange_Operation) EnumDescriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{63, 0, 0} + return file_repository_service_proto_rawDescGZIP(), []int{61, 0, 0} } type RepositoryExistsRequest struct { @@ -1009,101 +1009,6 @@ func (*ApplyGitattributesResponse) Descriptor() ([]byte, []int) { return file_repository_service_proto_rawDescGZIP(), []int{17} } -type FetchBundleRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Repository into which the reference shall be fetched. - Repository *Repository `protobuf:"bytes,1,opt,name=repository,proto3" json:"repository,omitempty"` - // Data is the bundle file stream. - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *FetchBundleRequest) Reset() { - *x = FetchBundleRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FetchBundleRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FetchBundleRequest) ProtoMessage() {} - -func (x *FetchBundleRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[18] - 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 FetchBundleRequest.ProtoReflect.Descriptor instead. -func (*FetchBundleRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{18} -} - -func (x *FetchBundleRequest) GetRepository() *Repository { - if x != nil { - return x.Repository - } - return nil -} - -func (x *FetchBundleRequest) GetData() []byte { - if x != nil { - return x.Data - } - return nil -} - -type FetchBundleResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *FetchBundleResponse) Reset() { - *x = FetchBundleResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FetchBundleResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FetchBundleResponse) ProtoMessage() {} - -func (x *FetchBundleResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[19] - 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 FetchBundleResponse.ProtoReflect.Descriptor instead. -func (*FetchBundleResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{19} -} - type FetchRemoteRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1134,7 +1039,7 @@ type FetchRemoteRequest struct { func (x *FetchRemoteRequest) Reset() { *x = FetchRemoteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[20] + mi := &file_repository_service_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1147,7 +1052,7 @@ func (x *FetchRemoteRequest) String() string { func (*FetchRemoteRequest) ProtoMessage() {} func (x *FetchRemoteRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[20] + mi := &file_repository_service_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1160,7 +1065,7 @@ func (x *FetchRemoteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FetchRemoteRequest.ProtoReflect.Descriptor instead. func (*FetchRemoteRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{20} + return file_repository_service_proto_rawDescGZIP(), []int{18} } func (x *FetchRemoteRequest) GetRepository() *Repository { @@ -1240,7 +1145,7 @@ type FetchRemoteResponse struct { func (x *FetchRemoteResponse) Reset() { *x = FetchRemoteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[21] + mi := &file_repository_service_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1253,7 +1158,7 @@ func (x *FetchRemoteResponse) String() string { func (*FetchRemoteResponse) ProtoMessage() {} func (x *FetchRemoteResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[21] + mi := &file_repository_service_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1266,7 +1171,7 @@ func (x *FetchRemoteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FetchRemoteResponse.ProtoReflect.Descriptor instead. func (*FetchRemoteResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{21} + return file_repository_service_proto_rawDescGZIP(), []int{19} } func (x *FetchRemoteResponse) GetTagsChanged() bool { @@ -1287,7 +1192,7 @@ type CreateRepositoryRequest struct { func (x *CreateRepositoryRequest) Reset() { *x = CreateRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[22] + mi := &file_repository_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1300,7 +1205,7 @@ func (x *CreateRepositoryRequest) String() string { func (*CreateRepositoryRequest) ProtoMessage() {} func (x *CreateRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[22] + mi := &file_repository_service_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1313,7 +1218,7 @@ func (x *CreateRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRepositoryRequest.ProtoReflect.Descriptor instead. func (*CreateRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{22} + return file_repository_service_proto_rawDescGZIP(), []int{20} } func (x *CreateRepositoryRequest) GetRepository() *Repository { @@ -1332,7 +1237,7 @@ type CreateRepositoryResponse struct { func (x *CreateRepositoryResponse) Reset() { *x = CreateRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[23] + mi := &file_repository_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1345,7 +1250,7 @@ func (x *CreateRepositoryResponse) String() string { func (*CreateRepositoryResponse) ProtoMessage() {} func (x *CreateRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[23] + mi := &file_repository_service_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1358,7 +1263,7 @@ func (x *CreateRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRepositoryResponse.ProtoReflect.Descriptor instead. func (*CreateRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{23} + return file_repository_service_proto_rawDescGZIP(), []int{21} } type GetArchiveRequest struct { @@ -1385,7 +1290,7 @@ type GetArchiveRequest struct { func (x *GetArchiveRequest) Reset() { *x = GetArchiveRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[24] + mi := &file_repository_service_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1398,7 +1303,7 @@ func (x *GetArchiveRequest) String() string { func (*GetArchiveRequest) ProtoMessage() {} func (x *GetArchiveRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[24] + mi := &file_repository_service_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1411,7 +1316,7 @@ func (x *GetArchiveRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetArchiveRequest.ProtoReflect.Descriptor instead. func (*GetArchiveRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{24} + return file_repository_service_proto_rawDescGZIP(), []int{22} } func (x *GetArchiveRequest) GetRepository() *Repository { @@ -1481,7 +1386,7 @@ type GetArchiveResponse struct { func (x *GetArchiveResponse) Reset() { *x = GetArchiveResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[25] + mi := &file_repository_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1494,7 +1399,7 @@ func (x *GetArchiveResponse) String() string { func (*GetArchiveResponse) ProtoMessage() {} func (x *GetArchiveResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[25] + mi := &file_repository_service_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1507,7 +1412,7 @@ func (x *GetArchiveResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetArchiveResponse.ProtoReflect.Descriptor instead. func (*GetArchiveResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{25} + return file_repository_service_proto_rawDescGZIP(), []int{23} } func (x *GetArchiveResponse) GetData() []byte { @@ -1528,7 +1433,7 @@ type HasLocalBranchesRequest struct { func (x *HasLocalBranchesRequest) Reset() { *x = HasLocalBranchesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[26] + mi := &file_repository_service_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1541,7 +1446,7 @@ func (x *HasLocalBranchesRequest) String() string { func (*HasLocalBranchesRequest) ProtoMessage() {} func (x *HasLocalBranchesRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[26] + mi := &file_repository_service_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1554,7 +1459,7 @@ func (x *HasLocalBranchesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HasLocalBranchesRequest.ProtoReflect.Descriptor instead. func (*HasLocalBranchesRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{26} + return file_repository_service_proto_rawDescGZIP(), []int{24} } func (x *HasLocalBranchesRequest) GetRepository() *Repository { @@ -1575,7 +1480,7 @@ type HasLocalBranchesResponse struct { func (x *HasLocalBranchesResponse) Reset() { *x = HasLocalBranchesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[27] + mi := &file_repository_service_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1588,7 +1493,7 @@ func (x *HasLocalBranchesResponse) String() string { func (*HasLocalBranchesResponse) ProtoMessage() {} func (x *HasLocalBranchesResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[27] + mi := &file_repository_service_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1601,7 +1506,7 @@ func (x *HasLocalBranchesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HasLocalBranchesResponse.ProtoReflect.Descriptor instead. func (*HasLocalBranchesResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{27} + return file_repository_service_proto_rawDescGZIP(), []int{25} } func (x *HasLocalBranchesResponse) GetValue() bool { @@ -1632,7 +1537,7 @@ type FetchSourceBranchRequest struct { func (x *FetchSourceBranchRequest) Reset() { *x = FetchSourceBranchRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[28] + mi := &file_repository_service_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1645,7 +1550,7 @@ func (x *FetchSourceBranchRequest) String() string { func (*FetchSourceBranchRequest) ProtoMessage() {} func (x *FetchSourceBranchRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[28] + mi := &file_repository_service_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1658,7 +1563,7 @@ func (x *FetchSourceBranchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FetchSourceBranchRequest.ProtoReflect.Descriptor instead. func (*FetchSourceBranchRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{28} + return file_repository_service_proto_rawDescGZIP(), []int{26} } func (x *FetchSourceBranchRequest) GetRepository() *Repository { @@ -1702,7 +1607,7 @@ type FetchSourceBranchResponse struct { func (x *FetchSourceBranchResponse) Reset() { *x = FetchSourceBranchResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[29] + mi := &file_repository_service_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1715,7 +1620,7 @@ func (x *FetchSourceBranchResponse) String() string { func (*FetchSourceBranchResponse) ProtoMessage() {} func (x *FetchSourceBranchResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[29] + mi := &file_repository_service_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1728,7 +1633,7 @@ func (x *FetchSourceBranchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FetchSourceBranchResponse.ProtoReflect.Descriptor instead. func (*FetchSourceBranchResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{29} + return file_repository_service_proto_rawDescGZIP(), []int{27} } func (x *FetchSourceBranchResponse) GetResult() bool { @@ -1749,7 +1654,7 @@ type FsckRequest struct { func (x *FsckRequest) Reset() { *x = FsckRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[30] + mi := &file_repository_service_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1762,7 +1667,7 @@ func (x *FsckRequest) String() string { func (*FsckRequest) ProtoMessage() {} func (x *FsckRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[30] + mi := &file_repository_service_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1775,7 +1680,7 @@ func (x *FsckRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FsckRequest.ProtoReflect.Descriptor instead. func (*FsckRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{30} + return file_repository_service_proto_rawDescGZIP(), []int{28} } func (x *FsckRequest) GetRepository() *Repository { @@ -1796,7 +1701,7 @@ type FsckResponse struct { func (x *FsckResponse) Reset() { *x = FsckResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[31] + mi := &file_repository_service_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1809,7 +1714,7 @@ func (x *FsckResponse) String() string { func (*FsckResponse) ProtoMessage() {} func (x *FsckResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[31] + mi := &file_repository_service_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1822,7 +1727,7 @@ func (x *FsckResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FsckResponse.ProtoReflect.Descriptor instead. func (*FsckResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{31} + return file_repository_service_proto_rawDescGZIP(), []int{29} } func (x *FsckResponse) GetError() []byte { @@ -1847,7 +1752,7 @@ type WriteRefRequest struct { func (x *WriteRefRequest) Reset() { *x = WriteRefRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[32] + mi := &file_repository_service_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1860,7 +1765,7 @@ func (x *WriteRefRequest) String() string { func (*WriteRefRequest) ProtoMessage() {} func (x *WriteRefRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[32] + mi := &file_repository_service_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1873,7 +1778,7 @@ func (x *WriteRefRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WriteRefRequest.ProtoReflect.Descriptor instead. func (*WriteRefRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{32} + return file_repository_service_proto_rawDescGZIP(), []int{30} } func (x *WriteRefRequest) GetRepository() *Repository { @@ -1920,7 +1825,7 @@ type WriteRefResponse struct { func (x *WriteRefResponse) Reset() { *x = WriteRefResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[33] + mi := &file_repository_service_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1933,7 +1838,7 @@ func (x *WriteRefResponse) String() string { func (*WriteRefResponse) ProtoMessage() {} func (x *WriteRefResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[33] + mi := &file_repository_service_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1946,7 +1851,7 @@ func (x *WriteRefResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WriteRefResponse.ProtoReflect.Descriptor instead. func (*WriteRefResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{33} + return file_repository_service_proto_rawDescGZIP(), []int{31} } type FindMergeBaseRequest struct { @@ -1964,7 +1869,7 @@ type FindMergeBaseRequest struct { func (x *FindMergeBaseRequest) Reset() { *x = FindMergeBaseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[34] + mi := &file_repository_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1977,7 +1882,7 @@ func (x *FindMergeBaseRequest) String() string { func (*FindMergeBaseRequest) ProtoMessage() {} func (x *FindMergeBaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[34] + mi := &file_repository_service_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1990,7 +1895,7 @@ func (x *FindMergeBaseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FindMergeBaseRequest.ProtoReflect.Descriptor instead. func (*FindMergeBaseRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{34} + return file_repository_service_proto_rawDescGZIP(), []int{32} } func (x *FindMergeBaseRequest) GetRepository() *Repository { @@ -2018,7 +1923,7 @@ type FindMergeBaseResponse struct { func (x *FindMergeBaseResponse) Reset() { *x = FindMergeBaseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[35] + mi := &file_repository_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2031,7 +1936,7 @@ func (x *FindMergeBaseResponse) String() string { func (*FindMergeBaseResponse) ProtoMessage() {} func (x *FindMergeBaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[35] + mi := &file_repository_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2044,7 +1949,7 @@ func (x *FindMergeBaseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FindMergeBaseResponse.ProtoReflect.Descriptor instead. func (*FindMergeBaseResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{35} + return file_repository_service_proto_rawDescGZIP(), []int{33} } func (x *FindMergeBaseResponse) GetBase() string { @@ -2066,7 +1971,7 @@ type CreateForkRequest struct { func (x *CreateForkRequest) Reset() { *x = CreateForkRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[36] + mi := &file_repository_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2079,7 +1984,7 @@ func (x *CreateForkRequest) String() string { func (*CreateForkRequest) ProtoMessage() {} func (x *CreateForkRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[36] + mi := &file_repository_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2092,7 +1997,7 @@ func (x *CreateForkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateForkRequest.ProtoReflect.Descriptor instead. func (*CreateForkRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{36} + return file_repository_service_proto_rawDescGZIP(), []int{34} } func (x *CreateForkRequest) GetRepository() *Repository { @@ -2118,7 +2023,7 @@ type CreateForkResponse struct { func (x *CreateForkResponse) Reset() { *x = CreateForkResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[37] + mi := &file_repository_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2131,7 +2036,7 @@ func (x *CreateForkResponse) String() string { func (*CreateForkResponse) ProtoMessage() {} func (x *CreateForkResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[37] + mi := &file_repository_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2144,7 +2049,7 @@ func (x *CreateForkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateForkResponse.ProtoReflect.Descriptor instead. func (*CreateForkResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{37} + return file_repository_service_proto_rawDescGZIP(), []int{35} } type CreateRepositoryFromURLRequest struct { @@ -2159,7 +2064,7 @@ type CreateRepositoryFromURLRequest struct { func (x *CreateRepositoryFromURLRequest) Reset() { *x = CreateRepositoryFromURLRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[38] + mi := &file_repository_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2172,7 +2077,7 @@ func (x *CreateRepositoryFromURLRequest) String() string { func (*CreateRepositoryFromURLRequest) ProtoMessage() {} func (x *CreateRepositoryFromURLRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[38] + mi := &file_repository_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2185,7 +2090,7 @@ func (x *CreateRepositoryFromURLRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRepositoryFromURLRequest.ProtoReflect.Descriptor instead. func (*CreateRepositoryFromURLRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{38} + return file_repository_service_proto_rawDescGZIP(), []int{36} } func (x *CreateRepositoryFromURLRequest) GetRepository() *Repository { @@ -2211,7 +2116,7 @@ type CreateRepositoryFromURLResponse struct { func (x *CreateRepositoryFromURLResponse) Reset() { *x = CreateRepositoryFromURLResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[39] + mi := &file_repository_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2224,7 +2129,7 @@ func (x *CreateRepositoryFromURLResponse) String() string { func (*CreateRepositoryFromURLResponse) ProtoMessage() {} func (x *CreateRepositoryFromURLResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[39] + mi := &file_repository_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2237,7 +2142,7 @@ func (x *CreateRepositoryFromURLResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRepositoryFromURLResponse.ProtoReflect.Descriptor instead. func (*CreateRepositoryFromURLResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{39} + return file_repository_service_proto_rawDescGZIP(), []int{37} } type CreateBundleRequest struct { @@ -2251,7 +2156,7 @@ type CreateBundleRequest struct { func (x *CreateBundleRequest) Reset() { *x = CreateBundleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[40] + mi := &file_repository_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2264,7 +2169,7 @@ func (x *CreateBundleRequest) String() string { func (*CreateBundleRequest) ProtoMessage() {} func (x *CreateBundleRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[40] + mi := &file_repository_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2277,7 +2182,7 @@ func (x *CreateBundleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBundleRequest.ProtoReflect.Descriptor instead. func (*CreateBundleRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{40} + return file_repository_service_proto_rawDescGZIP(), []int{38} } func (x *CreateBundleRequest) GetRepository() *Repository { @@ -2298,7 +2203,7 @@ type CreateBundleResponse struct { func (x *CreateBundleResponse) Reset() { *x = CreateBundleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[41] + mi := &file_repository_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2311,7 +2216,7 @@ func (x *CreateBundleResponse) String() string { func (*CreateBundleResponse) ProtoMessage() {} func (x *CreateBundleResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[41] + mi := &file_repository_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2324,7 +2229,7 @@ func (x *CreateBundleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBundleResponse.ProtoReflect.Descriptor instead. func (*CreateBundleResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{41} + return file_repository_service_proto_rawDescGZIP(), []int{39} } func (x *CreateBundleResponse) GetData() []byte { @@ -2350,7 +2255,7 @@ type CreateBundleFromRefListRequest struct { func (x *CreateBundleFromRefListRequest) Reset() { *x = CreateBundleFromRefListRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[42] + mi := &file_repository_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2363,7 +2268,7 @@ func (x *CreateBundleFromRefListRequest) String() string { func (*CreateBundleFromRefListRequest) ProtoMessage() {} func (x *CreateBundleFromRefListRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[42] + mi := &file_repository_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2376,7 +2281,7 @@ func (x *CreateBundleFromRefListRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBundleFromRefListRequest.ProtoReflect.Descriptor instead. func (*CreateBundleFromRefListRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{42} + return file_repository_service_proto_rawDescGZIP(), []int{40} } func (x *CreateBundleFromRefListRequest) GetRepository() *Repository { @@ -2404,7 +2309,7 @@ type CreateBundleFromRefListResponse struct { func (x *CreateBundleFromRefListResponse) Reset() { *x = CreateBundleFromRefListResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[43] + mi := &file_repository_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2417,7 +2322,7 @@ func (x *CreateBundleFromRefListResponse) String() string { func (*CreateBundleFromRefListResponse) ProtoMessage() {} func (x *CreateBundleFromRefListResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[43] + mi := &file_repository_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2430,7 +2335,7 @@ func (x *CreateBundleFromRefListResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBundleFromRefListResponse.ProtoReflect.Descriptor instead. func (*CreateBundleFromRefListResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{43} + return file_repository_service_proto_rawDescGZIP(), []int{41} } func (x *CreateBundleFromRefListResponse) GetData() []byte { @@ -2454,7 +2359,7 @@ type GetConfigRequest struct { func (x *GetConfigRequest) Reset() { *x = GetConfigRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[44] + mi := &file_repository_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2467,7 +2372,7 @@ func (x *GetConfigRequest) String() string { func (*GetConfigRequest) ProtoMessage() {} func (x *GetConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[44] + mi := &file_repository_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2480,7 +2385,7 @@ func (x *GetConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetConfigRequest.ProtoReflect.Descriptor instead. func (*GetConfigRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{44} + return file_repository_service_proto_rawDescGZIP(), []int{42} } func (x *GetConfigRequest) GetRepository() *Repository { @@ -2503,7 +2408,7 @@ type GetConfigResponse struct { func (x *GetConfigResponse) Reset() { *x = GetConfigResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[45] + mi := &file_repository_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2516,7 +2421,7 @@ func (x *GetConfigResponse) String() string { func (*GetConfigResponse) ProtoMessage() {} func (x *GetConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[45] + mi := &file_repository_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2529,7 +2434,7 @@ func (x *GetConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetConfigResponse.ProtoReflect.Descriptor instead. func (*GetConfigResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{45} + return file_repository_service_proto_rawDescGZIP(), []int{43} } func (x *GetConfigResponse) GetData() []byte { @@ -2551,7 +2456,7 @@ type RestoreCustomHooksRequest struct { func (x *RestoreCustomHooksRequest) Reset() { *x = RestoreCustomHooksRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[46] + mi := &file_repository_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2564,7 +2469,7 @@ func (x *RestoreCustomHooksRequest) String() string { func (*RestoreCustomHooksRequest) ProtoMessage() {} func (x *RestoreCustomHooksRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[46] + mi := &file_repository_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2577,7 +2482,7 @@ func (x *RestoreCustomHooksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RestoreCustomHooksRequest.ProtoReflect.Descriptor instead. func (*RestoreCustomHooksRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{46} + return file_repository_service_proto_rawDescGZIP(), []int{44} } func (x *RestoreCustomHooksRequest) GetRepository() *Repository { @@ -2603,7 +2508,7 @@ type RestoreCustomHooksResponse struct { func (x *RestoreCustomHooksResponse) Reset() { *x = RestoreCustomHooksResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[47] + mi := &file_repository_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2616,7 +2521,7 @@ func (x *RestoreCustomHooksResponse) String() string { func (*RestoreCustomHooksResponse) ProtoMessage() {} func (x *RestoreCustomHooksResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[47] + mi := &file_repository_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2629,7 +2534,7 @@ func (x *RestoreCustomHooksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RestoreCustomHooksResponse.ProtoReflect.Descriptor instead. func (*RestoreCustomHooksResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{47} + return file_repository_service_proto_rawDescGZIP(), []int{45} } type BackupCustomHooksRequest struct { @@ -2643,7 +2548,7 @@ type BackupCustomHooksRequest struct { func (x *BackupCustomHooksRequest) Reset() { *x = BackupCustomHooksRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[48] + mi := &file_repository_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2656,7 +2561,7 @@ func (x *BackupCustomHooksRequest) String() string { func (*BackupCustomHooksRequest) ProtoMessage() {} func (x *BackupCustomHooksRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[48] + mi := &file_repository_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2669,7 +2574,7 @@ func (x *BackupCustomHooksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BackupCustomHooksRequest.ProtoReflect.Descriptor instead. func (*BackupCustomHooksRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{48} + return file_repository_service_proto_rawDescGZIP(), []int{46} } func (x *BackupCustomHooksRequest) GetRepository() *Repository { @@ -2690,7 +2595,7 @@ type BackupCustomHooksResponse struct { func (x *BackupCustomHooksResponse) Reset() { *x = BackupCustomHooksResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[49] + mi := &file_repository_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2703,7 +2608,7 @@ func (x *BackupCustomHooksResponse) String() string { func (*BackupCustomHooksResponse) ProtoMessage() {} func (x *BackupCustomHooksResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[49] + mi := &file_repository_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2716,7 +2621,7 @@ func (x *BackupCustomHooksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BackupCustomHooksResponse.ProtoReflect.Descriptor instead. func (*BackupCustomHooksResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{49} + return file_repository_service_proto_rawDescGZIP(), []int{47} } func (x *BackupCustomHooksResponse) GetData() []byte { @@ -2739,7 +2644,7 @@ type CreateRepositoryFromBundleRequest struct { func (x *CreateRepositoryFromBundleRequest) Reset() { *x = CreateRepositoryFromBundleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[50] + mi := &file_repository_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2752,7 +2657,7 @@ func (x *CreateRepositoryFromBundleRequest) String() string { func (*CreateRepositoryFromBundleRequest) ProtoMessage() {} func (x *CreateRepositoryFromBundleRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[50] + mi := &file_repository_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2765,7 +2670,7 @@ func (x *CreateRepositoryFromBundleRequest) ProtoReflect() protoreflect.Message // Deprecated: Use CreateRepositoryFromBundleRequest.ProtoReflect.Descriptor instead. func (*CreateRepositoryFromBundleRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{50} + return file_repository_service_proto_rawDescGZIP(), []int{48} } func (x *CreateRepositoryFromBundleRequest) GetRepository() *Repository { @@ -2791,7 +2696,7 @@ type CreateRepositoryFromBundleResponse struct { func (x *CreateRepositoryFromBundleResponse) Reset() { *x = CreateRepositoryFromBundleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[51] + mi := &file_repository_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2804,7 +2709,7 @@ func (x *CreateRepositoryFromBundleResponse) String() string { func (*CreateRepositoryFromBundleResponse) ProtoMessage() {} func (x *CreateRepositoryFromBundleResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[51] + mi := &file_repository_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2817,7 +2722,7 @@ func (x *CreateRepositoryFromBundleResponse) ProtoReflect() protoreflect.Message // Deprecated: Use CreateRepositoryFromBundleResponse.ProtoReflect.Descriptor instead. func (*CreateRepositoryFromBundleResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{51} + return file_repository_service_proto_rawDescGZIP(), []int{49} } type FindLicenseRequest struct { @@ -2831,7 +2736,7 @@ type FindLicenseRequest struct { func (x *FindLicenseRequest) Reset() { *x = FindLicenseRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[52] + mi := &file_repository_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2844,7 +2749,7 @@ func (x *FindLicenseRequest) String() string { func (*FindLicenseRequest) ProtoMessage() {} func (x *FindLicenseRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[52] + mi := &file_repository_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2857,7 +2762,7 @@ func (x *FindLicenseRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FindLicenseRequest.ProtoReflect.Descriptor instead. func (*FindLicenseRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{52} + return file_repository_service_proto_rawDescGZIP(), []int{50} } func (x *FindLicenseRequest) GetRepository() *Repository { @@ -2878,7 +2783,7 @@ type FindLicenseResponse struct { func (x *FindLicenseResponse) Reset() { *x = FindLicenseResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[53] + mi := &file_repository_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2891,7 +2796,7 @@ func (x *FindLicenseResponse) String() string { func (*FindLicenseResponse) ProtoMessage() {} func (x *FindLicenseResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[53] + mi := &file_repository_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2904,7 +2809,7 @@ func (x *FindLicenseResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FindLicenseResponse.ProtoReflect.Descriptor instead. func (*FindLicenseResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{53} + return file_repository_service_proto_rawDescGZIP(), []int{51} } func (x *FindLicenseResponse) GetLicenseShortName() string { @@ -2925,7 +2830,7 @@ type GetInfoAttributesRequest struct { func (x *GetInfoAttributesRequest) Reset() { *x = GetInfoAttributesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[54] + mi := &file_repository_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2938,7 +2843,7 @@ func (x *GetInfoAttributesRequest) String() string { func (*GetInfoAttributesRequest) ProtoMessage() {} func (x *GetInfoAttributesRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[54] + mi := &file_repository_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2951,7 +2856,7 @@ func (x *GetInfoAttributesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetInfoAttributesRequest.ProtoReflect.Descriptor instead. func (*GetInfoAttributesRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{54} + return file_repository_service_proto_rawDescGZIP(), []int{52} } func (x *GetInfoAttributesRequest) GetRepository() *Repository { @@ -2972,7 +2877,7 @@ type GetInfoAttributesResponse struct { func (x *GetInfoAttributesResponse) Reset() { *x = GetInfoAttributesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[55] + mi := &file_repository_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2985,7 +2890,7 @@ func (x *GetInfoAttributesResponse) String() string { func (*GetInfoAttributesResponse) ProtoMessage() {} func (x *GetInfoAttributesResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[55] + mi := &file_repository_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2998,7 +2903,7 @@ func (x *GetInfoAttributesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetInfoAttributesResponse.ProtoReflect.Descriptor instead. func (*GetInfoAttributesResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{55} + return file_repository_service_proto_rawDescGZIP(), []int{53} } func (x *GetInfoAttributesResponse) GetAttributes() []byte { @@ -3019,7 +2924,7 @@ type CalculateChecksumRequest struct { func (x *CalculateChecksumRequest) Reset() { *x = CalculateChecksumRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[56] + mi := &file_repository_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3032,7 +2937,7 @@ func (x *CalculateChecksumRequest) String() string { func (*CalculateChecksumRequest) ProtoMessage() {} func (x *CalculateChecksumRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[56] + mi := &file_repository_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3045,7 +2950,7 @@ func (x *CalculateChecksumRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CalculateChecksumRequest.ProtoReflect.Descriptor instead. func (*CalculateChecksumRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{56} + return file_repository_service_proto_rawDescGZIP(), []int{54} } func (x *CalculateChecksumRequest) GetRepository() *Repository { @@ -3066,7 +2971,7 @@ type CalculateChecksumResponse struct { func (x *CalculateChecksumResponse) Reset() { *x = CalculateChecksumResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[57] + mi := &file_repository_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3079,7 +2984,7 @@ func (x *CalculateChecksumResponse) String() string { func (*CalculateChecksumResponse) ProtoMessage() {} func (x *CalculateChecksumResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[57] + mi := &file_repository_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3092,7 +2997,7 @@ func (x *CalculateChecksumResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CalculateChecksumResponse.ProtoReflect.Descriptor instead. func (*CalculateChecksumResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{57} + return file_repository_service_proto_rawDescGZIP(), []int{55} } func (x *CalculateChecksumResponse) GetChecksum() string { @@ -3113,7 +3018,7 @@ type GetSnapshotRequest struct { func (x *GetSnapshotRequest) Reset() { *x = GetSnapshotRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[58] + mi := &file_repository_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3126,7 +3031,7 @@ func (x *GetSnapshotRequest) String() string { func (*GetSnapshotRequest) ProtoMessage() {} func (x *GetSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[58] + mi := &file_repository_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3139,7 +3044,7 @@ func (x *GetSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSnapshotRequest.ProtoReflect.Descriptor instead. func (*GetSnapshotRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{58} + return file_repository_service_proto_rawDescGZIP(), []int{56} } func (x *GetSnapshotRequest) GetRepository() *Repository { @@ -3160,7 +3065,7 @@ type GetSnapshotResponse struct { func (x *GetSnapshotResponse) Reset() { *x = GetSnapshotResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[59] + mi := &file_repository_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3173,7 +3078,7 @@ func (x *GetSnapshotResponse) String() string { func (*GetSnapshotResponse) ProtoMessage() {} func (x *GetSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[59] + mi := &file_repository_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3186,7 +3091,7 @@ func (x *GetSnapshotResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSnapshotResponse.ProtoReflect.Descriptor instead. func (*GetSnapshotResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{59} + return file_repository_service_proto_rawDescGZIP(), []int{57} } func (x *GetSnapshotResponse) GetData() []byte { @@ -3209,7 +3114,7 @@ type CreateRepositoryFromSnapshotRequest struct { func (x *CreateRepositoryFromSnapshotRequest) Reset() { *x = CreateRepositoryFromSnapshotRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[60] + mi := &file_repository_service_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3222,7 +3127,7 @@ func (x *CreateRepositoryFromSnapshotRequest) String() string { func (*CreateRepositoryFromSnapshotRequest) ProtoMessage() {} func (x *CreateRepositoryFromSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[60] + mi := &file_repository_service_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3235,7 +3140,7 @@ func (x *CreateRepositoryFromSnapshotRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use CreateRepositoryFromSnapshotRequest.ProtoReflect.Descriptor instead. func (*CreateRepositoryFromSnapshotRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{60} + return file_repository_service_proto_rawDescGZIP(), []int{58} } func (x *CreateRepositoryFromSnapshotRequest) GetRepository() *Repository { @@ -3268,7 +3173,7 @@ type CreateRepositoryFromSnapshotResponse struct { func (x *CreateRepositoryFromSnapshotResponse) Reset() { *x = CreateRepositoryFromSnapshotResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[61] + mi := &file_repository_service_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3281,7 +3186,7 @@ func (x *CreateRepositoryFromSnapshotResponse) String() string { func (*CreateRepositoryFromSnapshotResponse) ProtoMessage() {} func (x *CreateRepositoryFromSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[61] + mi := &file_repository_service_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3294,7 +3199,7 @@ func (x *CreateRepositoryFromSnapshotResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use CreateRepositoryFromSnapshotResponse.ProtoReflect.Descriptor instead. func (*CreateRepositoryFromSnapshotResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{61} + return file_repository_service_proto_rawDescGZIP(), []int{59} } type GetRawChangesRequest struct { @@ -3310,7 +3215,7 @@ type GetRawChangesRequest struct { func (x *GetRawChangesRequest) Reset() { *x = GetRawChangesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[62] + mi := &file_repository_service_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3323,7 +3228,7 @@ func (x *GetRawChangesRequest) String() string { func (*GetRawChangesRequest) ProtoMessage() {} func (x *GetRawChangesRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[62] + mi := &file_repository_service_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3336,7 +3241,7 @@ func (x *GetRawChangesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRawChangesRequest.ProtoReflect.Descriptor instead. func (*GetRawChangesRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{62} + return file_repository_service_proto_rawDescGZIP(), []int{60} } func (x *GetRawChangesRequest) GetRepository() *Repository { @@ -3371,7 +3276,7 @@ type GetRawChangesResponse struct { func (x *GetRawChangesResponse) Reset() { *x = GetRawChangesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[63] + mi := &file_repository_service_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3384,7 +3289,7 @@ func (x *GetRawChangesResponse) String() string { func (*GetRawChangesResponse) ProtoMessage() {} func (x *GetRawChangesResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[63] + mi := &file_repository_service_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3397,7 +3302,7 @@ func (x *GetRawChangesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRawChangesResponse.ProtoReflect.Descriptor instead. func (*GetRawChangesResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{63} + return file_repository_service_proto_rawDescGZIP(), []int{61} } func (x *GetRawChangesResponse) GetRawChanges() []*GetRawChangesResponse_RawChange { @@ -3426,7 +3331,7 @@ type SearchFilesByNameRequest struct { func (x *SearchFilesByNameRequest) Reset() { *x = SearchFilesByNameRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[64] + mi := &file_repository_service_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3439,7 +3344,7 @@ func (x *SearchFilesByNameRequest) String() string { func (*SearchFilesByNameRequest) ProtoMessage() {} func (x *SearchFilesByNameRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[64] + mi := &file_repository_service_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3452,7 +3357,7 @@ func (x *SearchFilesByNameRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchFilesByNameRequest.ProtoReflect.Descriptor instead. func (*SearchFilesByNameRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{64} + return file_repository_service_proto_rawDescGZIP(), []int{62} } func (x *SearchFilesByNameRequest) GetRepository() *Repository { @@ -3494,7 +3399,7 @@ type SearchFilesByNameResponse struct { func (x *SearchFilesByNameResponse) Reset() { *x = SearchFilesByNameResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[65] + mi := &file_repository_service_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3507,7 +3412,7 @@ func (x *SearchFilesByNameResponse) String() string { func (*SearchFilesByNameResponse) ProtoMessage() {} func (x *SearchFilesByNameResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[65] + mi := &file_repository_service_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3520,7 +3425,7 @@ func (x *SearchFilesByNameResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchFilesByNameResponse.ProtoReflect.Descriptor instead. func (*SearchFilesByNameResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{65} + return file_repository_service_proto_rawDescGZIP(), []int{63} } func (x *SearchFilesByNameResponse) GetFiles() [][]byte { @@ -3544,7 +3449,7 @@ type SearchFilesByContentRequest struct { func (x *SearchFilesByContentRequest) Reset() { *x = SearchFilesByContentRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[66] + mi := &file_repository_service_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3557,7 +3462,7 @@ func (x *SearchFilesByContentRequest) String() string { func (*SearchFilesByContentRequest) ProtoMessage() {} func (x *SearchFilesByContentRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[66] + mi := &file_repository_service_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3570,7 +3475,7 @@ func (x *SearchFilesByContentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchFilesByContentRequest.ProtoReflect.Descriptor instead. func (*SearchFilesByContentRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{66} + return file_repository_service_proto_rawDescGZIP(), []int{64} } func (x *SearchFilesByContentRequest) GetRepository() *Repository { @@ -3614,7 +3519,7 @@ type SearchFilesByContentResponse struct { func (x *SearchFilesByContentResponse) Reset() { *x = SearchFilesByContentResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[67] + mi := &file_repository_service_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3627,7 +3532,7 @@ func (x *SearchFilesByContentResponse) String() string { func (*SearchFilesByContentResponse) ProtoMessage() {} func (x *SearchFilesByContentResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[67] + mi := &file_repository_service_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3640,7 +3545,7 @@ func (x *SearchFilesByContentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchFilesByContentResponse.ProtoReflect.Descriptor instead. func (*SearchFilesByContentResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{67} + return file_repository_service_proto_rawDescGZIP(), []int{65} } func (x *SearchFilesByContentResponse) GetMatches() [][]byte { @@ -3692,7 +3597,7 @@ type Remote struct { func (x *Remote) Reset() { *x = Remote{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[68] + mi := &file_repository_service_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3705,7 +3610,7 @@ func (x *Remote) String() string { func (*Remote) ProtoMessage() {} func (x *Remote) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[68] + mi := &file_repository_service_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3718,7 +3623,7 @@ func (x *Remote) ProtoReflect() protoreflect.Message { // Deprecated: Use Remote.ProtoReflect.Descriptor instead. func (*Remote) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{68} + return file_repository_service_proto_rawDescGZIP(), []int{66} } func (x *Remote) GetUrl() string { @@ -3753,7 +3658,7 @@ type GetObjectDirectorySizeRequest struct { func (x *GetObjectDirectorySizeRequest) Reset() { *x = GetObjectDirectorySizeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[69] + mi := &file_repository_service_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3766,7 +3671,7 @@ func (x *GetObjectDirectorySizeRequest) String() string { func (*GetObjectDirectorySizeRequest) ProtoMessage() {} func (x *GetObjectDirectorySizeRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[69] + mi := &file_repository_service_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3779,7 +3684,7 @@ func (x *GetObjectDirectorySizeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetObjectDirectorySizeRequest.ProtoReflect.Descriptor instead. func (*GetObjectDirectorySizeRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{69} + return file_repository_service_proto_rawDescGZIP(), []int{67} } func (x *GetObjectDirectorySizeRequest) GetRepository() *Repository { @@ -3801,7 +3706,7 @@ type GetObjectDirectorySizeResponse struct { func (x *GetObjectDirectorySizeResponse) Reset() { *x = GetObjectDirectorySizeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[70] + mi := &file_repository_service_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3814,7 +3719,7 @@ func (x *GetObjectDirectorySizeResponse) String() string { func (*GetObjectDirectorySizeResponse) ProtoMessage() {} func (x *GetObjectDirectorySizeResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[70] + mi := &file_repository_service_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3827,7 +3732,7 @@ func (x *GetObjectDirectorySizeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetObjectDirectorySizeResponse.ProtoReflect.Descriptor instead. func (*GetObjectDirectorySizeResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{70} + return file_repository_service_proto_rawDescGZIP(), []int{68} } func (x *GetObjectDirectorySizeResponse) GetSize() int64 { @@ -3850,7 +3755,7 @@ type CloneFromPoolRequest struct { func (x *CloneFromPoolRequest) Reset() { *x = CloneFromPoolRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[71] + mi := &file_repository_service_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3863,7 +3768,7 @@ func (x *CloneFromPoolRequest) String() string { func (*CloneFromPoolRequest) ProtoMessage() {} func (x *CloneFromPoolRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[71] + mi := &file_repository_service_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3876,7 +3781,7 @@ func (x *CloneFromPoolRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CloneFromPoolRequest.ProtoReflect.Descriptor instead. func (*CloneFromPoolRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{71} + return file_repository_service_proto_rawDescGZIP(), []int{69} } func (x *CloneFromPoolRequest) GetRepository() *Repository { @@ -3909,7 +3814,7 @@ type CloneFromPoolResponse struct { func (x *CloneFromPoolResponse) Reset() { *x = CloneFromPoolResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[72] + mi := &file_repository_service_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3922,7 +3827,7 @@ func (x *CloneFromPoolResponse) String() string { func (*CloneFromPoolResponse) ProtoMessage() {} func (x *CloneFromPoolResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[72] + mi := &file_repository_service_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3935,7 +3840,7 @@ func (x *CloneFromPoolResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CloneFromPoolResponse.ProtoReflect.Descriptor instead. func (*CloneFromPoolResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{72} + return file_repository_service_proto_rawDescGZIP(), []int{70} } type CloneFromPoolInternalRequest struct { @@ -3951,7 +3856,7 @@ type CloneFromPoolInternalRequest struct { func (x *CloneFromPoolInternalRequest) Reset() { *x = CloneFromPoolInternalRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[73] + mi := &file_repository_service_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3964,7 +3869,7 @@ func (x *CloneFromPoolInternalRequest) String() string { func (*CloneFromPoolInternalRequest) ProtoMessage() {} func (x *CloneFromPoolInternalRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[73] + mi := &file_repository_service_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3977,7 +3882,7 @@ func (x *CloneFromPoolInternalRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CloneFromPoolInternalRequest.ProtoReflect.Descriptor instead. func (*CloneFromPoolInternalRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{73} + return file_repository_service_proto_rawDescGZIP(), []int{71} } func (x *CloneFromPoolInternalRequest) GetRepository() *Repository { @@ -4010,7 +3915,7 @@ type CloneFromPoolInternalResponse struct { func (x *CloneFromPoolInternalResponse) Reset() { *x = CloneFromPoolInternalResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[74] + mi := &file_repository_service_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4023,7 +3928,7 @@ func (x *CloneFromPoolInternalResponse) String() string { func (*CloneFromPoolInternalResponse) ProtoMessage() {} func (x *CloneFromPoolInternalResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[74] + mi := &file_repository_service_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4036,7 +3941,7 @@ func (x *CloneFromPoolInternalResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CloneFromPoolInternalResponse.ProtoReflect.Descriptor instead. func (*CloneFromPoolInternalResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{74} + return file_repository_service_proto_rawDescGZIP(), []int{72} } type RemoveRepositoryRequest struct { @@ -4050,7 +3955,7 @@ type RemoveRepositoryRequest struct { func (x *RemoveRepositoryRequest) Reset() { *x = RemoveRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[75] + mi := &file_repository_service_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4063,7 +3968,7 @@ func (x *RemoveRepositoryRequest) String() string { func (*RemoveRepositoryRequest) ProtoMessage() {} func (x *RemoveRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[75] + mi := &file_repository_service_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4076,7 +3981,7 @@ func (x *RemoveRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveRepositoryRequest.ProtoReflect.Descriptor instead. func (*RemoveRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{75} + return file_repository_service_proto_rawDescGZIP(), []int{73} } func (x *RemoveRepositoryRequest) GetRepository() *Repository { @@ -4095,7 +4000,7 @@ type RemoveRepositoryResponse struct { func (x *RemoveRepositoryResponse) Reset() { *x = RemoveRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[76] + mi := &file_repository_service_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4108,7 +4013,7 @@ func (x *RemoveRepositoryResponse) String() string { func (*RemoveRepositoryResponse) ProtoMessage() {} func (x *RemoveRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[76] + mi := &file_repository_service_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4121,7 +4026,7 @@ func (x *RemoveRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveRepositoryResponse.ProtoReflect.Descriptor instead. func (*RemoveRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{76} + return file_repository_service_proto_rawDescGZIP(), []int{74} } type RenameRepositoryRequest struct { @@ -4136,7 +4041,7 @@ type RenameRepositoryRequest struct { func (x *RenameRepositoryRequest) Reset() { *x = RenameRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[77] + mi := &file_repository_service_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4149,7 +4054,7 @@ func (x *RenameRepositoryRequest) String() string { func (*RenameRepositoryRequest) ProtoMessage() {} func (x *RenameRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[77] + mi := &file_repository_service_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4162,7 +4067,7 @@ func (x *RenameRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RenameRepositoryRequest.ProtoReflect.Descriptor instead. func (*RenameRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{77} + return file_repository_service_proto_rawDescGZIP(), []int{75} } func (x *RenameRepositoryRequest) GetRepository() *Repository { @@ -4188,7 +4093,7 @@ type RenameRepositoryResponse struct { func (x *RenameRepositoryResponse) Reset() { *x = RenameRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[78] + mi := &file_repository_service_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4201,7 +4106,7 @@ func (x *RenameRepositoryResponse) String() string { func (*RenameRepositoryResponse) ProtoMessage() {} func (x *RenameRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[78] + mi := &file_repository_service_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4214,7 +4119,7 @@ func (x *RenameRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RenameRepositoryResponse.ProtoReflect.Descriptor instead. func (*RenameRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{78} + return file_repository_service_proto_rawDescGZIP(), []int{76} } type ReplicateRepositoryRequest struct { @@ -4229,7 +4134,7 @@ type ReplicateRepositoryRequest struct { func (x *ReplicateRepositoryRequest) Reset() { *x = ReplicateRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[79] + mi := &file_repository_service_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4242,7 +4147,7 @@ func (x *ReplicateRepositoryRequest) String() string { func (*ReplicateRepositoryRequest) ProtoMessage() {} func (x *ReplicateRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[79] + mi := &file_repository_service_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4255,7 +4160,7 @@ func (x *ReplicateRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplicateRepositoryRequest.ProtoReflect.Descriptor instead. func (*ReplicateRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{79} + return file_repository_service_proto_rawDescGZIP(), []int{77} } func (x *ReplicateRepositoryRequest) GetRepository() *Repository { @@ -4281,7 +4186,7 @@ type ReplicateRepositoryResponse struct { func (x *ReplicateRepositoryResponse) Reset() { *x = ReplicateRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[80] + mi := &file_repository_service_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4294,7 +4199,7 @@ func (x *ReplicateRepositoryResponse) String() string { func (*ReplicateRepositoryResponse) ProtoMessage() {} func (x *ReplicateRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[80] + mi := &file_repository_service_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4307,7 +4212,7 @@ func (x *ReplicateRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplicateRepositoryResponse.ProtoReflect.Descriptor instead. func (*ReplicateRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{80} + return file_repository_service_proto_rawDescGZIP(), []int{78} } type OptimizeRepositoryRequest struct { @@ -4321,7 +4226,7 @@ type OptimizeRepositoryRequest struct { func (x *OptimizeRepositoryRequest) Reset() { *x = OptimizeRepositoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[81] + mi := &file_repository_service_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4334,7 +4239,7 @@ func (x *OptimizeRepositoryRequest) String() string { func (*OptimizeRepositoryRequest) ProtoMessage() {} func (x *OptimizeRepositoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[81] + mi := &file_repository_service_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4347,7 +4252,7 @@ func (x *OptimizeRepositoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use OptimizeRepositoryRequest.ProtoReflect.Descriptor instead. func (*OptimizeRepositoryRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{81} + return file_repository_service_proto_rawDescGZIP(), []int{79} } func (x *OptimizeRepositoryRequest) GetRepository() *Repository { @@ -4366,7 +4271,7 @@ type OptimizeRepositoryResponse struct { func (x *OptimizeRepositoryResponse) Reset() { *x = OptimizeRepositoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[82] + mi := &file_repository_service_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4379,7 +4284,7 @@ func (x *OptimizeRepositoryResponse) String() string { func (*OptimizeRepositoryResponse) ProtoMessage() {} func (x *OptimizeRepositoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[82] + mi := &file_repository_service_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4392,7 +4297,7 @@ func (x *OptimizeRepositoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use OptimizeRepositoryResponse.ProtoReflect.Descriptor instead. func (*OptimizeRepositoryResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{82} + return file_repository_service_proto_rawDescGZIP(), []int{80} } // SetFullPathRequest is a request for the SetFullPath RPC. @@ -4410,7 +4315,7 @@ type SetFullPathRequest struct { func (x *SetFullPathRequest) Reset() { *x = SetFullPathRequest{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[83] + mi := &file_repository_service_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4423,7 +4328,7 @@ func (x *SetFullPathRequest) String() string { func (*SetFullPathRequest) ProtoMessage() {} func (x *SetFullPathRequest) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[83] + mi := &file_repository_service_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4436,7 +4341,7 @@ func (x *SetFullPathRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetFullPathRequest.ProtoReflect.Descriptor instead. func (*SetFullPathRequest) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{83} + return file_repository_service_proto_rawDescGZIP(), []int{81} } func (x *SetFullPathRequest) GetRepository() *Repository { @@ -4463,7 +4368,7 @@ type SetFullPathResponse struct { func (x *SetFullPathResponse) Reset() { *x = SetFullPathResponse{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[84] + mi := &file_repository_service_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4476,7 +4381,7 @@ func (x *SetFullPathResponse) String() string { func (*SetFullPathResponse) ProtoMessage() {} func (x *SetFullPathResponse) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[84] + mi := &file_repository_service_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4489,7 +4394,7 @@ func (x *SetFullPathResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetFullPathResponse.ProtoReflect.Descriptor instead. func (*SetFullPathResponse) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{84} + return file_repository_service_proto_rawDescGZIP(), []int{82} } type GetRawChangesResponse_RawChange struct { @@ -4517,7 +4422,7 @@ type GetRawChangesResponse_RawChange struct { func (x *GetRawChangesResponse_RawChange) Reset() { *x = GetRawChangesResponse_RawChange{} if protoimpl.UnsafeEnabled { - mi := &file_repository_service_proto_msgTypes[85] + mi := &file_repository_service_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4530,7 +4435,7 @@ func (x *GetRawChangesResponse_RawChange) String() string { func (*GetRawChangesResponse_RawChange) ProtoMessage() {} func (x *GetRawChangesResponse_RawChange) ProtoReflect() protoreflect.Message { - mi := &file_repository_service_proto_msgTypes[85] + mi := &file_repository_service_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4543,7 +4448,7 @@ func (x *GetRawChangesResponse_RawChange) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRawChangesResponse_RawChange.ProtoReflect.Descriptor instead. func (*GetRawChangesResponse_RawChange) Descriptor() ([]byte, []int) { - return file_repository_service_proto_rawDescGZIP(), []int{63, 0} + return file_repository_service_proto_rawDescGZIP(), []int{61, 0} } func (x *GetRawChangesResponse_RawChange) GetBlobId() string { @@ -4703,660 +4608,648 @@ var file_repository_service_proto_rawDesc = []byte{ 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x1c, 0x0a, 0x1a, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x69, 0x74, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x62, 0x0a, 0x12, 0x46, - 0x65, 0x74, 0x63, 0x68, 0x42, 0x75, 0x6e, 0x64, 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, 0x12, 0x0a, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, - 0x15, 0x0a, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe3, 0x02, 0x0a, 0x12, 0x46, 0x65, 0x74, 0x63, 0x68, - 0x52, 0x65, 0x6d, 0x6f, 0x74, 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, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x17, 0x0a, - 0x07, 0x6e, 0x6f, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, - 0x6e, 0x6f, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x12, 0x17, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x6e, 0x6f, - 0x77, 0x6e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, - 0x5f, 0x70, 0x72, 0x75, 0x6e, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6e, 0x6f, - 0x50, 0x72, 0x75, 0x6e, 0x65, 0x12, 0x33, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x0c, 0x72, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x61, 0x67, - 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, - 0x08, 0x02, 0x10, 0x03, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x38, 0x0a, 0x13, - 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x61, 0x67, 0x73, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x53, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 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, 0x22, 0x1a, 0x0a, 0x18, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xea, 0x02, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, - 0x72, 0x63, 0x68, 0x69, 0x76, 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, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x38, 0x0a, 0x06, - 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, - 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x78, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6c, 0x69, 0x64, 0x65, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x6c, 0x69, 0x64, 0x65, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6c, - 0x66, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x66, 0x73, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x22, - 0x33, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x07, 0x0a, 0x03, 0x5a, 0x49, 0x50, - 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x41, 0x52, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x54, - 0x41, 0x52, 0x5f, 0x47, 0x5a, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x41, 0x52, 0x5f, 0x42, - 0x5a, 0x32, 0x10, 0x03, 0x22, 0x28, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x72, 0x63, 0x68, 0x69, - 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x53, - 0x0a, 0x17, 0x48, 0x61, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x65, 0x73, 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, 0x22, 0x30, 0x0a, 0x18, 0x48, 0x61, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x18, 0x46, 0x65, 0x74, 0x63, 0x68, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 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, 0x3f, 0x0a, 0x11, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x18, 0x02, 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, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x23, 0x0a, - 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, - 0x66, 0x22, 0x33, 0x0a, 0x19, 0x46, 0x65, 0x74, 0x63, 0x68, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x47, 0x0a, 0x0b, 0x46, 0x73, 0x63, 0x6b, 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, 0x22, - 0x24, 0x0a, 0x0c, 0x46, 0x73, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xb8, 0x01, 0x0a, 0x0f, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, - 0x65, 0x66, 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, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, - 0x22, 0x18, 0x0a, 0x10, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x6e, 0x0a, 0x14, 0x46, 0x69, - 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe3, 0x02, 0x0a, 0x12, + 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 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, 0x1c, 0x0a, 0x09, - 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x2b, 0x0a, 0x15, 0x46, 0x69, - 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 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, 0x3f, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 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, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x14, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6c, - 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 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, 0x10, 0x0a, 0x03, 0x75, 0x72, - 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x21, 0x0a, 0x1f, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x4f, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, + 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x6e, 0x6f, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x74, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x1f, + 0x0a, 0x0b, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, + 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x75, 0x6e, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x6e, 0x6f, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x12, 0x33, 0x0a, 0x0d, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, + 0x2c, 0x0a, 0x12, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x54, 0x61, 0x67, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4a, 0x04, 0x08, + 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x22, 0x38, 0x0a, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x67, 0x73, + 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x74, 0x61, 0x67, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x53, 0x0a, 0x17, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 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, - 0x22, 0x2a, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x76, 0x0a, 0x1e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, - 0x52, 0x65, 0x66, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, + 0x22, 0x1a, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xea, 0x02, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 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, 0x1b, 0x0a, 0x09, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x12, 0x38, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, + 0x18, 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, + 0x52, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6c, 0x69, + 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, + 0x6c, 0x69, 0x64, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x5f, 0x6c, 0x66, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x66, 0x73, 0x42, + 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x33, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x07, + 0x0a, 0x03, 0x5a, 0x49, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x41, 0x52, 0x10, 0x01, + 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x41, 0x52, 0x5f, 0x47, 0x5a, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, + 0x54, 0x41, 0x52, 0x5f, 0x42, 0x5a, 0x32, 0x10, 0x03, 0x22, 0x28, 0x0a, 0x12, 0x47, 0x65, 0x74, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x22, 0x53, 0x0a, 0x17, 0x48, 0x61, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 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, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x74, 0x74, - 0x65, 0x72, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x61, 0x74, 0x74, - 0x65, 0x72, 0x6e, 0x73, 0x22, 0x35, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x66, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x4c, 0x0a, 0x10, 0x47, - 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x22, 0x27, 0x0a, 0x11, 0x47, 0x65, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x22, 0x69, 0x0a, 0x19, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 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, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x1c, 0x0a, - 0x1a, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, - 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x0a, 0x18, 0x42, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x30, 0x0a, 0x18, 0x48, 0x61, 0x73, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x18, 0x46, + 0x65, 0x74, 0x63, 0x68, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 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, 0x22, 0x2f, 0x0a, 0x19, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, - 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x22, 0x71, 0x0a, 0x21, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, + 0x79, 0x12, 0x3f, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 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, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x62, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x52, 0x65, 0x66, 0x22, 0x33, 0x0a, 0x19, 0x46, 0x65, 0x74, 0x63, 0x68, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x47, 0x0a, 0x0b, 0x46, + 0x73, 0x63, 0x6b, 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, 0x22, 0x24, 0x0a, 0x0c, 0x46, 0x73, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xb8, 0x01, 0x0a, 0x0f, 0x57, + 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 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, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x6c, + 0x64, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x4a, + 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x18, 0x0a, 0x10, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, + 0x6e, 0x0a, 0x14, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 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, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x24, 0x0a, 0x22, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x0a, 0x12, 0x46, - 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0x2b, 0x0a, 0x15, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, + 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 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, 0x3f, 0x0a, 0x11, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x18, 0x02, 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, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x14, 0x0a, + 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x6c, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 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, + 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, + 0x6c, 0x22, 0x21, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, + 0x6e, 0x64, 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, 0x22, 0x2a, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, + 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x22, 0x76, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x66, 0x4c, 0x69, 0x73, 0x74, 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, 0x1a, 0x0a, + 0x08, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x08, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x22, 0x35, 0x0a, 0x1f, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x66, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x22, 0x4c, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x22, 0x27, + 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x69, 0x0a, 0x19, 0x52, 0x65, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 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, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x22, 0x1c, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x75, 0x73, + 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x54, 0x0a, 0x18, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x48, 0x6f, 0x6f, 0x6b, 0x73, 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, 0x22, 0x2f, 0x0a, 0x19, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x71, 0x0a, 0x21, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, + 0x75, 0x6e, 0x64, 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, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x24, 0x0a, 0x22, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, + 0x6f, 0x6d, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x4e, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 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, + 0x22, 0x43, 0x0a, 0x13, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65, 0x6e, + 0x73, 0x65, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x53, 0x68, 0x6f, 0x72, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x54, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 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, 0x22, 0x43, 0x0a, 0x13, 0x46, - 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x73, 0x68, - 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, - 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, - 0x22, 0x54, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0a, + 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x3b, 0x0a, 0x19, 0x47, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x18, 0x43, 0x61, 0x6c, 0x63, + 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 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, 0x22, 0x37, + 0x0a, 0x19, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x22, 0x4e, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 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, 0x22, 0x29, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x22, 0x97, 0x01, 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 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, 0x19, 0x0a, 0x08, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, 0x74, 0x74, 0x70, 0x55, 0x72, 0x6c, 0x12, + 0x1b, 0x0a, 0x09, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x68, 0x74, 0x74, 0x70, 0x41, 0x75, 0x74, 0x68, 0x22, 0x26, 0x0a, 0x24, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 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, 0x23, 0x0a, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x5f, + 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x66, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, + 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xbd, 0x04, + 0x0a, 0x15, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, + 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x61, 0x77, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0a, 0x72, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x1a, 0xd9, 0x03, 0x0a, 0x09, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, + 0x17, 0x0a, 0x07, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x08, + 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, + 0x18, 0x01, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x08, 0x6f, + 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, + 0x01, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x4f, 0x0a, 0x09, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x61, 0x77, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, + 0x61, 0x77, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x61, 0x77, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, + 0x65, 0x77, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6e, + 0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, + 0x74, 0x68, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, + 0x6e, 0x65, 0x77, 0x50, 0x61, 0x74, 0x68, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, + 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6f, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x42, 0x79, 0x74, + 0x65, 0x73, 0x22, 0x69, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, + 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x50, 0x49, 0x45, + 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, + 0x12, 0x0c, 0x0a, 0x08, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x04, 0x12, 0x0b, + 0x0a, 0x07, 0x52, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0x44, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x06, 0x22, 0x94, 0x01, + 0x0a, 0x18, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x4e, + 0x61, 0x6d, 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, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, + 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x16, 0x0a, 0x06, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x22, 0x31, 0x0a, 0x19, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, + 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xaa, 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 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, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x68, 0x75, + 0x6e, 0x6b, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a, 0x1c, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x1d, + 0x0a, 0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, + 0x0c, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x6e, 0x64, 0x4f, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, + 0x89, 0x01, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x3a, 0x0a, 0x19, + 0x68, 0x74, 0x74, 0x70, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x17, 0x68, 0x74, 0x74, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x69, 0x72, 0x72, + 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0d, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x66, 0x6d, 0x61, 0x70, 0x73, 0x4a, + 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x59, 0x0a, 0x1d, 0x47, + 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x53, 0x69, 0x7a, 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, 0x22, 0x3b, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x18, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 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, 0x22, 0x37, 0x0a, 0x19, 0x43, 0x61, 0x6c, - 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, - 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, - 0x75, 0x6d, 0x22, 0x4e, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 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, 0x22, 0x29, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x97, 0x01, - 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x34, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xa0, 0x01, 0x0a, + 0x14, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 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, - 0x19, 0x0a, 0x08, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x68, 0x74, 0x74, 0x70, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x74, - 0x74, 0x70, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, - 0x74, 0x74, 0x70, 0x41, 0x75, 0x74, 0x68, 0x22, 0x26, 0x0a, 0x24, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x53, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x96, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, + 0x26, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, + 0x6c, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x12, 0x26, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, + 0x17, 0x0a, 0x15, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x1c, 0x43, 0x6c, 0x6f, + 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 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, 0x26, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x12, 0x3f, 0x0a, 0x11, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x18, 0x03, 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, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x1f, 0x0a, 0x1d, + 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, + 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 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, 0x23, 0x0a, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x52, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x5f, 0x72, 0x65, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, - 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xbd, 0x04, 0x0a, 0x15, 0x47, 0x65, 0x74, - 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, - 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x52, 0x0a, 0x72, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x1a, 0xd9, 0x03, 0x0a, - 0x09, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x6c, - 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x6c, 0x6f, - 0x62, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x6e, - 0x65, 0x77, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x6f, 0x6c, - 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x4f, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x61, 0x77, 0x5f, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, - 0x61, 0x77, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6f, - 0x6c, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6f, - 0x6c, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x6f, - 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x50, 0x61, - 0x74, 0x68, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, 0x70, - 0x61, 0x74, 0x68, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0c, 0x6f, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x69, 0x0a, - 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x44, 0x44, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x50, 0x49, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, - 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4d, - 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x4e, - 0x41, 0x4d, 0x45, 0x44, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, - 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x06, 0x22, 0x94, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, + 0x72, 0x79, 0x22, 0x1a, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x78, + 0x0a, 0x17, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 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, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0x1a, 0x0a, 0x18, 0x52, 0x65, 0x6e, 0x61, + 0x6d, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 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, 0x2a, 0x0a, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 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, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0x0a, 0x19, 0x4f, 0x70, 0x74, 0x69, + 0x6d, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 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, - 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, - 0x31, 0x0a, 0x19, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, - 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x22, 0xaa, 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, - 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 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, 0x14, 0x0a, 0x05, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x03, 0x72, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x65, 0x64, 0x5f, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, - 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x79, 0x0a, 0x1c, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0c, 0x65, 0x6e, 0x64, 0x5f, - 0x6f, 0x66, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, - 0x65, 0x6e, 0x64, 0x4f, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x89, 0x01, 0x0a, 0x06, 0x52, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x68, 0x74, 0x74, 0x70, 0x5f, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x68, 0x74, 0x74, 0x70, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, - 0x66, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x69, 0x72, - 0x72, 0x6f, 0x72, 0x52, 0x65, 0x66, 0x6d, 0x61, 0x70, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x59, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 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, 0x22, 0x34, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x44, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xa0, 0x01, 0x0a, 0x14, 0x43, 0x6c, 0x6f, 0x6e, - 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 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, 0x26, 0x0a, 0x04, 0x70, 0x6f, - 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x04, 0x70, 0x6f, - 0x6f, 0x6c, 0x12, 0x26, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x43, 0x6c, - 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x1c, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, - 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 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, 0x26, - 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, - 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x12, 0x3f, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x03, 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, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x1f, 0x0a, 0x1d, 0x43, 0x6c, 0x6f, 0x6e, 0x65, - 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, + 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, + 0x1c, 0x0a, 0x1a, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x62, 0x0a, + 0x12, 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 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, 0x22, 0x1a, 0x0a, - 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x78, 0x0a, 0x17, 0x52, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 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, 0x23, - 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, - 0x61, 0x74, 0x68, 0x22, 0x1a, 0x0a, 0x18, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x82, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 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, 0x2a, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x02, 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, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x55, 0x0a, 0x19, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 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, 0x22, 0x1c, 0x0a, 0x1a, 0x4f, 0x70, - 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x62, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x46, - 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 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, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x15, 0x0a, 0x13, - 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0xda, 0x1e, 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, - 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x60, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x61, - 0x63, 0x6b, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x12, 0x20, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x63, - 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x49, - 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x4b, 0x0a, 0x0a, 0x52, 0x65, - 0x70, 0x61, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x6c, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, - 0x61, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x4b, 0x0a, 0x0a, 0x4d, 0x69, 0x64, 0x78, 0x52, - 0x65, 0x70, 0x61, 0x63, 0x6b, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, - 0x69, 0x64, 0x78, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, 0x69, 0x64, 0x78, 0x52, 0x65, - 0x70, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, - 0x28, 0x02, 0x08, 0x01, 0x12, 0x57, 0x0a, 0x0e, 0x47, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x43, - 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x47, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, - 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, - 0x10, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x47, 0x72, 0x61, 0x70, - 0x68, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x57, 0x0a, 0x0e, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, - 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x63, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x69, - 0x74, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x69, 0x74, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x69, 0x74, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x4e, 0x0a, 0x0b, 0x46, 0x65, - 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, - 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, + 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x88, 0x1e, 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, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x60, 0x0a, + 0x11, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x61, + 0x63, 0x6b, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, + 0x70, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, + 0x4b, 0x0a, 0x0a, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x6c, 0x12, 0x19, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x46, 0x75, 0x6c, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x4b, 0x0a, 0x0a, + 0x4d, 0x69, 0x64, 0x78, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x4d, 0x69, 0x64, 0x78, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4d, + 0x69, 0x64, 0x78, 0x52, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x57, 0x0a, 0x0e, 0x47, 0x61, 0x72, + 0x62, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x61, 0x72, 0x62, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, + 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, + 0x01, 0x12, 0x57, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x63, 0x0a, 0x12, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x47, 0x69, 0x74, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x12, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, + 0x69, 0x74, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x47, 0x69, 0x74, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, + 0x4e, 0x0a, 0x0b, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x1a, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, + 0x5d, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x4d, + 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x19, 0x2e, 0x67, + 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x5d, 0x0a, + 0x10, 0x48, 0x61, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, + 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x48, 0x61, 0x73, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x48, 0x61, 0x73, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x60, 0x0a, 0x11, + 0x46, 0x65, 0x74, 0x63, 0x68, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, + 0x63, 0x68, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x39, + 0x0a, 0x04, 0x46, 0x73, 0x63, 0x6b, 0x12, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, + 0x46, 0x73, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x73, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x45, 0x0a, 0x08, 0x57, 0x72, 0x69, + 0x74, 0x65, 0x52, 0x65, 0x66, 0x12, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x57, + 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, + 0x12, 0x54, 0x0a, 0x0d, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, + 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, + 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x72, + 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, + 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x4b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, + 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, + 0x02, 0x08, 0x01, 0x12, 0x72, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x4d, 0x0a, 0x0a, 0x47, 0x65, 0x74, - 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, - 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x48, 0x61, 0x73, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x48, 0x61, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x48, 0x61, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x60, 0x0a, 0x11, 0x46, 0x65, 0x74, 0x63, 0x68, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x20, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x39, 0x0a, 0x04, 0x46, 0x73, 0x63, - 0x6b, 0x12, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x73, 0x63, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x46, 0x73, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, - 0x28, 0x02, 0x08, 0x02, 0x12, 0x45, 0x0a, 0x08, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, - 0x12, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, - 0x65, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x46, - 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x12, 0x1c, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, - 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x42, 0x61, 0x73, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x53, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x76, 0x0a, 0x17, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, + 0x52, 0x65, 0x66, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, + 0x6d, 0x52, 0x65, 0x66, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x27, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, + 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x66, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, + 0x28, 0x01, 0x30, 0x01, 0x12, 0x7d, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x12, 0x29, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, - 0x02, 0x12, 0x4b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x12, - 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, - 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x72, - 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x55, - 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, - 0x08, 0x01, 0x12, 0x53, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, - 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x76, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x66, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x66, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x66, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x28, 0x01, 0x30, 0x01, 0x12, - 0x50, 0x0a, 0x0b, 0x46, 0x65, 0x74, 0x63, 0x68, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1a, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, - 0x01, 0x12, 0x7d, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, - 0x29, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, - 0x12, 0x4a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x4e, 0x0a, 0x0b, - 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, - 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x62, 0x0a, 0x11, + 0x01, 0x28, 0x01, 0x12, 0x4a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, + 0x4e, 0x0a, 0x0b, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x1a, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, + 0x62, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 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, 0x49, 0x6e, 0x66, 0x6f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 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, - 0x49, 0x6e, 0x66, 0x6f, 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, 0x30, 0x01, - 0x12, 0x60, 0x0a, 0x11, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, - 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, - 0x2e, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, - 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, - 0x08, 0x02, 0x12, 0x42, 0x0a, 0x07, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x16, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, - 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, - 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x50, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, - 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x81, 0x01, 0x0a, 0x1c, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, - 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x2b, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, + 0x02, 0x30, 0x01, 0x12, 0x60, 0x0a, 0x11, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, + 0x97, 0x28, 0x02, 0x08, 0x02, 0x12, 0x42, 0x0a, 0x07, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, + 0x12, 0x16, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x50, 0x0a, 0x0b, 0x47, 0x65, 0x74, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x79, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, + 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x81, 0x01, 0x0a, 0x1c, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x2b, 0x2e, 0x67, + 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x56, 0x0a, 0x0d, - 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, - 0x08, 0x02, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, - 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, - 0x01, 0x12, 0x62, 0x0a, 0x11, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, - 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x4e, 0x61, 0x6d, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, - 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x65, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x21, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, + 0x56, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, + 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x77, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, + 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, + 0x23, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, + 0x08, 0x02, 0x30, 0x01, 0x12, 0x62, 0x0a, 0x11, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x79, + 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, + 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x65, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, 0x12, 0x62, 0x0a, 0x11, + 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, 0x12, + 0x62, 0x0a, 0x11, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, + 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, - 0x73, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, - 0x12, 0x6f, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x25, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, - 0x02, 0x12, 0x54, 0x0a, 0x0d, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, - 0x6f, 0x6c, 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, - 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, - 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x6c, 0x0a, 0x15, 0x43, 0x6c, 0x6f, 0x6e, 0x65, - 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x12, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, - 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, - 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 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, 0x52, 0x65, 0x6d, 0x6f, 0x76, 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, 0x5d, 0x0a, 0x10, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, - 0x79, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 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, 0x52, 0x65, 0x6e, 0x61, 0x6d, 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, 0x66, 0x0a, 0x13, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x22, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, - 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 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, 0x63, 0x0a, 0x12, 0x4f, - 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x12, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, - 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, + 0x02, 0x30, 0x01, 0x12, 0x6f, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x25, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, + 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, + 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, + 0x28, 0x02, 0x08, 0x02, 0x12, 0x54, 0x0a, 0x0d, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, + 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, + 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x6f, + 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x6c, 0x0a, 0x15, 0x43, 0x6c, + 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x12, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x6f, + 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x67, + 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 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, 0x52, 0x65, 0x6d, 0x6f, 0x76, 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, 0x5d, 0x0a, 0x10, 0x52, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 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, 0x52, 0x65, 0x6e, 0x61, 0x6d, 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, 0x66, 0x0a, 0x13, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x22, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 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, 0x63, + 0x0a, 0x12, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 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, 0x4e, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, - 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, - 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, 0x34, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 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, 0x4e, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x74, 0x46, + 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x53, 0x65, 0x74, 0x46, 0x75, 0x6c, 0x6c, 0x50, + 0x61, 0x74, 0x68, 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, 0x34, 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 ( @@ -5372,7 +5265,7 @@ func file_repository_service_proto_rawDescGZIP() []byte { } var file_repository_service_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_repository_service_proto_msgTypes = make([]protoimpl.MessageInfo, 86) +var file_repository_service_proto_msgTypes = make([]protoimpl.MessageInfo, 84) var file_repository_service_proto_goTypes = []interface{}{ (WriteCommitGraphRequest_SplitStrategy)(0), // 0: gitaly.WriteCommitGraphRequest.SplitStrategy (GetArchiveRequest_Format)(0), // 1: gitaly.GetArchiveRequest.Format @@ -5395,221 +5288,216 @@ var file_repository_service_proto_goTypes = []interface{}{ (*RepositorySizeResponse)(nil), // 18: gitaly.RepositorySizeResponse (*ApplyGitattributesRequest)(nil), // 19: gitaly.ApplyGitattributesRequest (*ApplyGitattributesResponse)(nil), // 20: gitaly.ApplyGitattributesResponse - (*FetchBundleRequest)(nil), // 21: gitaly.FetchBundleRequest - (*FetchBundleResponse)(nil), // 22: gitaly.FetchBundleResponse - (*FetchRemoteRequest)(nil), // 23: gitaly.FetchRemoteRequest - (*FetchRemoteResponse)(nil), // 24: gitaly.FetchRemoteResponse - (*CreateRepositoryRequest)(nil), // 25: gitaly.CreateRepositoryRequest - (*CreateRepositoryResponse)(nil), // 26: gitaly.CreateRepositoryResponse - (*GetArchiveRequest)(nil), // 27: gitaly.GetArchiveRequest - (*GetArchiveResponse)(nil), // 28: gitaly.GetArchiveResponse - (*HasLocalBranchesRequest)(nil), // 29: gitaly.HasLocalBranchesRequest - (*HasLocalBranchesResponse)(nil), // 30: gitaly.HasLocalBranchesResponse - (*FetchSourceBranchRequest)(nil), // 31: gitaly.FetchSourceBranchRequest - (*FetchSourceBranchResponse)(nil), // 32: gitaly.FetchSourceBranchResponse - (*FsckRequest)(nil), // 33: gitaly.FsckRequest - (*FsckResponse)(nil), // 34: gitaly.FsckResponse - (*WriteRefRequest)(nil), // 35: gitaly.WriteRefRequest - (*WriteRefResponse)(nil), // 36: gitaly.WriteRefResponse - (*FindMergeBaseRequest)(nil), // 37: gitaly.FindMergeBaseRequest - (*FindMergeBaseResponse)(nil), // 38: gitaly.FindMergeBaseResponse - (*CreateForkRequest)(nil), // 39: gitaly.CreateForkRequest - (*CreateForkResponse)(nil), // 40: gitaly.CreateForkResponse - (*CreateRepositoryFromURLRequest)(nil), // 41: gitaly.CreateRepositoryFromURLRequest - (*CreateRepositoryFromURLResponse)(nil), // 42: gitaly.CreateRepositoryFromURLResponse - (*CreateBundleRequest)(nil), // 43: gitaly.CreateBundleRequest - (*CreateBundleResponse)(nil), // 44: gitaly.CreateBundleResponse - (*CreateBundleFromRefListRequest)(nil), // 45: gitaly.CreateBundleFromRefListRequest - (*CreateBundleFromRefListResponse)(nil), // 46: gitaly.CreateBundleFromRefListResponse - (*GetConfigRequest)(nil), // 47: gitaly.GetConfigRequest - (*GetConfigResponse)(nil), // 48: gitaly.GetConfigResponse - (*RestoreCustomHooksRequest)(nil), // 49: gitaly.RestoreCustomHooksRequest - (*RestoreCustomHooksResponse)(nil), // 50: gitaly.RestoreCustomHooksResponse - (*BackupCustomHooksRequest)(nil), // 51: gitaly.BackupCustomHooksRequest - (*BackupCustomHooksResponse)(nil), // 52: gitaly.BackupCustomHooksResponse - (*CreateRepositoryFromBundleRequest)(nil), // 53: gitaly.CreateRepositoryFromBundleRequest - (*CreateRepositoryFromBundleResponse)(nil), // 54: gitaly.CreateRepositoryFromBundleResponse - (*FindLicenseRequest)(nil), // 55: gitaly.FindLicenseRequest - (*FindLicenseResponse)(nil), // 56: gitaly.FindLicenseResponse - (*GetInfoAttributesRequest)(nil), // 57: gitaly.GetInfoAttributesRequest - (*GetInfoAttributesResponse)(nil), // 58: gitaly.GetInfoAttributesResponse - (*CalculateChecksumRequest)(nil), // 59: gitaly.CalculateChecksumRequest - (*CalculateChecksumResponse)(nil), // 60: gitaly.CalculateChecksumResponse - (*GetSnapshotRequest)(nil), // 61: gitaly.GetSnapshotRequest - (*GetSnapshotResponse)(nil), // 62: gitaly.GetSnapshotResponse - (*CreateRepositoryFromSnapshotRequest)(nil), // 63: gitaly.CreateRepositoryFromSnapshotRequest - (*CreateRepositoryFromSnapshotResponse)(nil), // 64: gitaly.CreateRepositoryFromSnapshotResponse - (*GetRawChangesRequest)(nil), // 65: gitaly.GetRawChangesRequest - (*GetRawChangesResponse)(nil), // 66: gitaly.GetRawChangesResponse - (*SearchFilesByNameRequest)(nil), // 67: gitaly.SearchFilesByNameRequest - (*SearchFilesByNameResponse)(nil), // 68: gitaly.SearchFilesByNameResponse - (*SearchFilesByContentRequest)(nil), // 69: gitaly.SearchFilesByContentRequest - (*SearchFilesByContentResponse)(nil), // 70: gitaly.SearchFilesByContentResponse - (*Remote)(nil), // 71: gitaly.Remote - (*GetObjectDirectorySizeRequest)(nil), // 72: gitaly.GetObjectDirectorySizeRequest - (*GetObjectDirectorySizeResponse)(nil), // 73: gitaly.GetObjectDirectorySizeResponse - (*CloneFromPoolRequest)(nil), // 74: gitaly.CloneFromPoolRequest - (*CloneFromPoolResponse)(nil), // 75: gitaly.CloneFromPoolResponse - (*CloneFromPoolInternalRequest)(nil), // 76: gitaly.CloneFromPoolInternalRequest - (*CloneFromPoolInternalResponse)(nil), // 77: gitaly.CloneFromPoolInternalResponse - (*RemoveRepositoryRequest)(nil), // 78: gitaly.RemoveRepositoryRequest - (*RemoveRepositoryResponse)(nil), // 79: gitaly.RemoveRepositoryResponse - (*RenameRepositoryRequest)(nil), // 80: gitaly.RenameRepositoryRequest - (*RenameRepositoryResponse)(nil), // 81: gitaly.RenameRepositoryResponse - (*ReplicateRepositoryRequest)(nil), // 82: gitaly.ReplicateRepositoryRequest - (*ReplicateRepositoryResponse)(nil), // 83: gitaly.ReplicateRepositoryResponse - (*OptimizeRepositoryRequest)(nil), // 84: gitaly.OptimizeRepositoryRequest - (*OptimizeRepositoryResponse)(nil), // 85: gitaly.OptimizeRepositoryResponse - (*SetFullPathRequest)(nil), // 86: gitaly.SetFullPathRequest - (*SetFullPathResponse)(nil), // 87: gitaly.SetFullPathResponse - (*GetRawChangesResponse_RawChange)(nil), // 88: gitaly.GetRawChangesResponse.RawChange - (*Repository)(nil), // 89: gitaly.Repository - (*ObjectPool)(nil), // 90: gitaly.ObjectPool + (*FetchRemoteRequest)(nil), // 21: gitaly.FetchRemoteRequest + (*FetchRemoteResponse)(nil), // 22: gitaly.FetchRemoteResponse + (*CreateRepositoryRequest)(nil), // 23: gitaly.CreateRepositoryRequest + (*CreateRepositoryResponse)(nil), // 24: gitaly.CreateRepositoryResponse + (*GetArchiveRequest)(nil), // 25: gitaly.GetArchiveRequest + (*GetArchiveResponse)(nil), // 26: gitaly.GetArchiveResponse + (*HasLocalBranchesRequest)(nil), // 27: gitaly.HasLocalBranchesRequest + (*HasLocalBranchesResponse)(nil), // 28: gitaly.HasLocalBranchesResponse + (*FetchSourceBranchRequest)(nil), // 29: gitaly.FetchSourceBranchRequest + (*FetchSourceBranchResponse)(nil), // 30: gitaly.FetchSourceBranchResponse + (*FsckRequest)(nil), // 31: gitaly.FsckRequest + (*FsckResponse)(nil), // 32: gitaly.FsckResponse + (*WriteRefRequest)(nil), // 33: gitaly.WriteRefRequest + (*WriteRefResponse)(nil), // 34: gitaly.WriteRefResponse + (*FindMergeBaseRequest)(nil), // 35: gitaly.FindMergeBaseRequest + (*FindMergeBaseResponse)(nil), // 36: gitaly.FindMergeBaseResponse + (*CreateForkRequest)(nil), // 37: gitaly.CreateForkRequest + (*CreateForkResponse)(nil), // 38: gitaly.CreateForkResponse + (*CreateRepositoryFromURLRequest)(nil), // 39: gitaly.CreateRepositoryFromURLRequest + (*CreateRepositoryFromURLResponse)(nil), // 40: gitaly.CreateRepositoryFromURLResponse + (*CreateBundleRequest)(nil), // 41: gitaly.CreateBundleRequest + (*CreateBundleResponse)(nil), // 42: gitaly.CreateBundleResponse + (*CreateBundleFromRefListRequest)(nil), // 43: gitaly.CreateBundleFromRefListRequest + (*CreateBundleFromRefListResponse)(nil), // 44: gitaly.CreateBundleFromRefListResponse + (*GetConfigRequest)(nil), // 45: gitaly.GetConfigRequest + (*GetConfigResponse)(nil), // 46: gitaly.GetConfigResponse + (*RestoreCustomHooksRequest)(nil), // 47: gitaly.RestoreCustomHooksRequest + (*RestoreCustomHooksResponse)(nil), // 48: gitaly.RestoreCustomHooksResponse + (*BackupCustomHooksRequest)(nil), // 49: gitaly.BackupCustomHooksRequest + (*BackupCustomHooksResponse)(nil), // 50: gitaly.BackupCustomHooksResponse + (*CreateRepositoryFromBundleRequest)(nil), // 51: gitaly.CreateRepositoryFromBundleRequest + (*CreateRepositoryFromBundleResponse)(nil), // 52: gitaly.CreateRepositoryFromBundleResponse + (*FindLicenseRequest)(nil), // 53: gitaly.FindLicenseRequest + (*FindLicenseResponse)(nil), // 54: gitaly.FindLicenseResponse + (*GetInfoAttributesRequest)(nil), // 55: gitaly.GetInfoAttributesRequest + (*GetInfoAttributesResponse)(nil), // 56: gitaly.GetInfoAttributesResponse + (*CalculateChecksumRequest)(nil), // 57: gitaly.CalculateChecksumRequest + (*CalculateChecksumResponse)(nil), // 58: gitaly.CalculateChecksumResponse + (*GetSnapshotRequest)(nil), // 59: gitaly.GetSnapshotRequest + (*GetSnapshotResponse)(nil), // 60: gitaly.GetSnapshotResponse + (*CreateRepositoryFromSnapshotRequest)(nil), // 61: gitaly.CreateRepositoryFromSnapshotRequest + (*CreateRepositoryFromSnapshotResponse)(nil), // 62: gitaly.CreateRepositoryFromSnapshotResponse + (*GetRawChangesRequest)(nil), // 63: gitaly.GetRawChangesRequest + (*GetRawChangesResponse)(nil), // 64: gitaly.GetRawChangesResponse + (*SearchFilesByNameRequest)(nil), // 65: gitaly.SearchFilesByNameRequest + (*SearchFilesByNameResponse)(nil), // 66: gitaly.SearchFilesByNameResponse + (*SearchFilesByContentRequest)(nil), // 67: gitaly.SearchFilesByContentRequest + (*SearchFilesByContentResponse)(nil), // 68: gitaly.SearchFilesByContentResponse + (*Remote)(nil), // 69: gitaly.Remote + (*GetObjectDirectorySizeRequest)(nil), // 70: gitaly.GetObjectDirectorySizeRequest + (*GetObjectDirectorySizeResponse)(nil), // 71: gitaly.GetObjectDirectorySizeResponse + (*CloneFromPoolRequest)(nil), // 72: gitaly.CloneFromPoolRequest + (*CloneFromPoolResponse)(nil), // 73: gitaly.CloneFromPoolResponse + (*CloneFromPoolInternalRequest)(nil), // 74: gitaly.CloneFromPoolInternalRequest + (*CloneFromPoolInternalResponse)(nil), // 75: gitaly.CloneFromPoolInternalResponse + (*RemoveRepositoryRequest)(nil), // 76: gitaly.RemoveRepositoryRequest + (*RemoveRepositoryResponse)(nil), // 77: gitaly.RemoveRepositoryResponse + (*RenameRepositoryRequest)(nil), // 78: gitaly.RenameRepositoryRequest + (*RenameRepositoryResponse)(nil), // 79: gitaly.RenameRepositoryResponse + (*ReplicateRepositoryRequest)(nil), // 80: gitaly.ReplicateRepositoryRequest + (*ReplicateRepositoryResponse)(nil), // 81: gitaly.ReplicateRepositoryResponse + (*OptimizeRepositoryRequest)(nil), // 82: gitaly.OptimizeRepositoryRequest + (*OptimizeRepositoryResponse)(nil), // 83: gitaly.OptimizeRepositoryResponse + (*SetFullPathRequest)(nil), // 84: gitaly.SetFullPathRequest + (*SetFullPathResponse)(nil), // 85: gitaly.SetFullPathResponse + (*GetRawChangesResponse_RawChange)(nil), // 86: gitaly.GetRawChangesResponse.RawChange + (*Repository)(nil), // 87: gitaly.Repository + (*ObjectPool)(nil), // 88: gitaly.ObjectPool } var file_repository_service_proto_depIdxs = []int32{ - 89, // 0: gitaly.RepositoryExistsRequest.repository:type_name -> gitaly.Repository - 89, // 1: gitaly.RepackIncrementalRequest.repository:type_name -> gitaly.Repository - 89, // 2: gitaly.RepackFullRequest.repository:type_name -> gitaly.Repository - 89, // 3: gitaly.MidxRepackRequest.repository:type_name -> gitaly.Repository - 89, // 4: gitaly.GarbageCollectRequest.repository:type_name -> gitaly.Repository - 89, // 5: gitaly.WriteCommitGraphRequest.repository:type_name -> gitaly.Repository + 87, // 0: gitaly.RepositoryExistsRequest.repository:type_name -> gitaly.Repository + 87, // 1: gitaly.RepackIncrementalRequest.repository:type_name -> gitaly.Repository + 87, // 2: gitaly.RepackFullRequest.repository:type_name -> gitaly.Repository + 87, // 3: gitaly.MidxRepackRequest.repository:type_name -> gitaly.Repository + 87, // 4: gitaly.GarbageCollectRequest.repository:type_name -> gitaly.Repository + 87, // 5: gitaly.WriteCommitGraphRequest.repository:type_name -> gitaly.Repository 0, // 6: gitaly.WriteCommitGraphRequest.splitStrategy:type_name -> gitaly.WriteCommitGraphRequest.SplitStrategy - 89, // 7: gitaly.CleanupRequest.repository:type_name -> gitaly.Repository - 89, // 8: gitaly.RepositorySizeRequest.repository:type_name -> gitaly.Repository - 89, // 9: gitaly.ApplyGitattributesRequest.repository:type_name -> gitaly.Repository - 89, // 10: gitaly.FetchBundleRequest.repository:type_name -> gitaly.Repository - 89, // 11: gitaly.FetchRemoteRequest.repository:type_name -> gitaly.Repository - 71, // 12: gitaly.FetchRemoteRequest.remote_params:type_name -> gitaly.Remote - 89, // 13: gitaly.CreateRepositoryRequest.repository:type_name -> gitaly.Repository - 89, // 14: gitaly.GetArchiveRequest.repository:type_name -> gitaly.Repository - 1, // 15: gitaly.GetArchiveRequest.format:type_name -> gitaly.GetArchiveRequest.Format - 89, // 16: gitaly.HasLocalBranchesRequest.repository:type_name -> gitaly.Repository - 89, // 17: gitaly.FetchSourceBranchRequest.repository:type_name -> gitaly.Repository - 89, // 18: gitaly.FetchSourceBranchRequest.source_repository:type_name -> gitaly.Repository - 89, // 19: gitaly.FsckRequest.repository:type_name -> gitaly.Repository - 89, // 20: gitaly.WriteRefRequest.repository:type_name -> gitaly.Repository - 89, // 21: gitaly.FindMergeBaseRequest.repository:type_name -> gitaly.Repository - 89, // 22: gitaly.CreateForkRequest.repository:type_name -> gitaly.Repository - 89, // 23: gitaly.CreateForkRequest.source_repository:type_name -> gitaly.Repository - 89, // 24: gitaly.CreateRepositoryFromURLRequest.repository:type_name -> gitaly.Repository - 89, // 25: gitaly.CreateBundleRequest.repository:type_name -> gitaly.Repository - 89, // 26: gitaly.CreateBundleFromRefListRequest.repository:type_name -> gitaly.Repository - 89, // 27: gitaly.GetConfigRequest.repository:type_name -> gitaly.Repository - 89, // 28: gitaly.RestoreCustomHooksRequest.repository:type_name -> gitaly.Repository - 89, // 29: gitaly.BackupCustomHooksRequest.repository:type_name -> gitaly.Repository - 89, // 30: gitaly.CreateRepositoryFromBundleRequest.repository:type_name -> gitaly.Repository - 89, // 31: gitaly.FindLicenseRequest.repository:type_name -> gitaly.Repository - 89, // 32: gitaly.GetInfoAttributesRequest.repository:type_name -> gitaly.Repository - 89, // 33: gitaly.CalculateChecksumRequest.repository:type_name -> gitaly.Repository - 89, // 34: gitaly.GetSnapshotRequest.repository:type_name -> gitaly.Repository - 89, // 35: gitaly.CreateRepositoryFromSnapshotRequest.repository:type_name -> gitaly.Repository - 89, // 36: gitaly.GetRawChangesRequest.repository:type_name -> gitaly.Repository - 88, // 37: gitaly.GetRawChangesResponse.raw_changes:type_name -> gitaly.GetRawChangesResponse.RawChange - 89, // 38: gitaly.SearchFilesByNameRequest.repository:type_name -> gitaly.Repository - 89, // 39: gitaly.SearchFilesByContentRequest.repository:type_name -> gitaly.Repository - 89, // 40: gitaly.GetObjectDirectorySizeRequest.repository:type_name -> gitaly.Repository - 89, // 41: gitaly.CloneFromPoolRequest.repository:type_name -> gitaly.Repository - 90, // 42: gitaly.CloneFromPoolRequest.pool:type_name -> gitaly.ObjectPool - 71, // 43: gitaly.CloneFromPoolRequest.remote:type_name -> gitaly.Remote - 89, // 44: gitaly.CloneFromPoolInternalRequest.repository:type_name -> gitaly.Repository - 90, // 45: gitaly.CloneFromPoolInternalRequest.pool:type_name -> gitaly.ObjectPool - 89, // 46: gitaly.CloneFromPoolInternalRequest.source_repository:type_name -> gitaly.Repository - 89, // 47: gitaly.RemoveRepositoryRequest.repository:type_name -> gitaly.Repository - 89, // 48: gitaly.RenameRepositoryRequest.repository:type_name -> gitaly.Repository - 89, // 49: gitaly.ReplicateRepositoryRequest.repository:type_name -> gitaly.Repository - 89, // 50: gitaly.ReplicateRepositoryRequest.source:type_name -> gitaly.Repository - 89, // 51: gitaly.OptimizeRepositoryRequest.repository:type_name -> gitaly.Repository - 89, // 52: gitaly.SetFullPathRequest.repository:type_name -> gitaly.Repository - 2, // 53: gitaly.GetRawChangesResponse.RawChange.operation:type_name -> gitaly.GetRawChangesResponse.RawChange.Operation - 3, // 54: gitaly.RepositoryService.RepositoryExists:input_type -> gitaly.RepositoryExistsRequest - 5, // 55: gitaly.RepositoryService.RepackIncremental:input_type -> gitaly.RepackIncrementalRequest - 7, // 56: gitaly.RepositoryService.RepackFull:input_type -> gitaly.RepackFullRequest - 9, // 57: gitaly.RepositoryService.MidxRepack:input_type -> gitaly.MidxRepackRequest - 11, // 58: gitaly.RepositoryService.GarbageCollect:input_type -> gitaly.GarbageCollectRequest - 13, // 59: gitaly.RepositoryService.WriteCommitGraph:input_type -> gitaly.WriteCommitGraphRequest - 17, // 60: gitaly.RepositoryService.RepositorySize:input_type -> gitaly.RepositorySizeRequest - 19, // 61: gitaly.RepositoryService.ApplyGitattributes:input_type -> gitaly.ApplyGitattributesRequest - 23, // 62: gitaly.RepositoryService.FetchRemote:input_type -> gitaly.FetchRemoteRequest - 25, // 63: gitaly.RepositoryService.CreateRepository:input_type -> gitaly.CreateRepositoryRequest - 27, // 64: gitaly.RepositoryService.GetArchive:input_type -> gitaly.GetArchiveRequest - 29, // 65: gitaly.RepositoryService.HasLocalBranches:input_type -> gitaly.HasLocalBranchesRequest - 31, // 66: gitaly.RepositoryService.FetchSourceBranch:input_type -> gitaly.FetchSourceBranchRequest - 33, // 67: gitaly.RepositoryService.Fsck:input_type -> gitaly.FsckRequest - 35, // 68: gitaly.RepositoryService.WriteRef:input_type -> gitaly.WriteRefRequest - 37, // 69: gitaly.RepositoryService.FindMergeBase:input_type -> gitaly.FindMergeBaseRequest - 39, // 70: gitaly.RepositoryService.CreateFork:input_type -> gitaly.CreateForkRequest - 41, // 71: gitaly.RepositoryService.CreateRepositoryFromURL:input_type -> gitaly.CreateRepositoryFromURLRequest - 43, // 72: gitaly.RepositoryService.CreateBundle:input_type -> gitaly.CreateBundleRequest - 45, // 73: gitaly.RepositoryService.CreateBundleFromRefList:input_type -> gitaly.CreateBundleFromRefListRequest - 21, // 74: gitaly.RepositoryService.FetchBundle:input_type -> gitaly.FetchBundleRequest - 53, // 75: gitaly.RepositoryService.CreateRepositoryFromBundle:input_type -> gitaly.CreateRepositoryFromBundleRequest - 47, // 76: gitaly.RepositoryService.GetConfig:input_type -> gitaly.GetConfigRequest - 55, // 77: gitaly.RepositoryService.FindLicense:input_type -> gitaly.FindLicenseRequest - 57, // 78: gitaly.RepositoryService.GetInfoAttributes:input_type -> gitaly.GetInfoAttributesRequest - 59, // 79: gitaly.RepositoryService.CalculateChecksum:input_type -> gitaly.CalculateChecksumRequest - 15, // 80: gitaly.RepositoryService.Cleanup:input_type -> gitaly.CleanupRequest - 61, // 81: gitaly.RepositoryService.GetSnapshot:input_type -> gitaly.GetSnapshotRequest - 63, // 82: gitaly.RepositoryService.CreateRepositoryFromSnapshot:input_type -> gitaly.CreateRepositoryFromSnapshotRequest - 65, // 83: gitaly.RepositoryService.GetRawChanges:input_type -> gitaly.GetRawChangesRequest - 69, // 84: gitaly.RepositoryService.SearchFilesByContent:input_type -> gitaly.SearchFilesByContentRequest - 67, // 85: gitaly.RepositoryService.SearchFilesByName:input_type -> gitaly.SearchFilesByNameRequest - 49, // 86: gitaly.RepositoryService.RestoreCustomHooks:input_type -> gitaly.RestoreCustomHooksRequest - 51, // 87: gitaly.RepositoryService.BackupCustomHooks:input_type -> gitaly.BackupCustomHooksRequest - 72, // 88: gitaly.RepositoryService.GetObjectDirectorySize:input_type -> gitaly.GetObjectDirectorySizeRequest - 74, // 89: gitaly.RepositoryService.CloneFromPool:input_type -> gitaly.CloneFromPoolRequest - 76, // 90: gitaly.RepositoryService.CloneFromPoolInternal:input_type -> gitaly.CloneFromPoolInternalRequest - 78, // 91: gitaly.RepositoryService.RemoveRepository:input_type -> gitaly.RemoveRepositoryRequest - 80, // 92: gitaly.RepositoryService.RenameRepository:input_type -> gitaly.RenameRepositoryRequest - 82, // 93: gitaly.RepositoryService.ReplicateRepository:input_type -> gitaly.ReplicateRepositoryRequest - 84, // 94: gitaly.RepositoryService.OptimizeRepository:input_type -> gitaly.OptimizeRepositoryRequest - 86, // 95: gitaly.RepositoryService.SetFullPath:input_type -> gitaly.SetFullPathRequest - 4, // 96: gitaly.RepositoryService.RepositoryExists:output_type -> gitaly.RepositoryExistsResponse - 6, // 97: gitaly.RepositoryService.RepackIncremental:output_type -> gitaly.RepackIncrementalResponse - 8, // 98: gitaly.RepositoryService.RepackFull:output_type -> gitaly.RepackFullResponse - 10, // 99: gitaly.RepositoryService.MidxRepack:output_type -> gitaly.MidxRepackResponse - 12, // 100: gitaly.RepositoryService.GarbageCollect:output_type -> gitaly.GarbageCollectResponse - 14, // 101: gitaly.RepositoryService.WriteCommitGraph:output_type -> gitaly.WriteCommitGraphResponse - 18, // 102: gitaly.RepositoryService.RepositorySize:output_type -> gitaly.RepositorySizeResponse - 20, // 103: gitaly.RepositoryService.ApplyGitattributes:output_type -> gitaly.ApplyGitattributesResponse - 24, // 104: gitaly.RepositoryService.FetchRemote:output_type -> gitaly.FetchRemoteResponse - 26, // 105: gitaly.RepositoryService.CreateRepository:output_type -> gitaly.CreateRepositoryResponse - 28, // 106: gitaly.RepositoryService.GetArchive:output_type -> gitaly.GetArchiveResponse - 30, // 107: gitaly.RepositoryService.HasLocalBranches:output_type -> gitaly.HasLocalBranchesResponse - 32, // 108: gitaly.RepositoryService.FetchSourceBranch:output_type -> gitaly.FetchSourceBranchResponse - 34, // 109: gitaly.RepositoryService.Fsck:output_type -> gitaly.FsckResponse - 36, // 110: gitaly.RepositoryService.WriteRef:output_type -> gitaly.WriteRefResponse - 38, // 111: gitaly.RepositoryService.FindMergeBase:output_type -> gitaly.FindMergeBaseResponse - 40, // 112: gitaly.RepositoryService.CreateFork:output_type -> gitaly.CreateForkResponse - 42, // 113: gitaly.RepositoryService.CreateRepositoryFromURL:output_type -> gitaly.CreateRepositoryFromURLResponse - 44, // 114: gitaly.RepositoryService.CreateBundle:output_type -> gitaly.CreateBundleResponse - 46, // 115: gitaly.RepositoryService.CreateBundleFromRefList:output_type -> gitaly.CreateBundleFromRefListResponse - 22, // 116: gitaly.RepositoryService.FetchBundle:output_type -> gitaly.FetchBundleResponse - 54, // 117: gitaly.RepositoryService.CreateRepositoryFromBundle:output_type -> gitaly.CreateRepositoryFromBundleResponse - 48, // 118: gitaly.RepositoryService.GetConfig:output_type -> gitaly.GetConfigResponse - 56, // 119: gitaly.RepositoryService.FindLicense:output_type -> gitaly.FindLicenseResponse - 58, // 120: gitaly.RepositoryService.GetInfoAttributes:output_type -> gitaly.GetInfoAttributesResponse - 60, // 121: gitaly.RepositoryService.CalculateChecksum:output_type -> gitaly.CalculateChecksumResponse - 16, // 122: gitaly.RepositoryService.Cleanup:output_type -> gitaly.CleanupResponse - 62, // 123: gitaly.RepositoryService.GetSnapshot:output_type -> gitaly.GetSnapshotResponse - 64, // 124: gitaly.RepositoryService.CreateRepositoryFromSnapshot:output_type -> gitaly.CreateRepositoryFromSnapshotResponse - 66, // 125: gitaly.RepositoryService.GetRawChanges:output_type -> gitaly.GetRawChangesResponse - 70, // 126: gitaly.RepositoryService.SearchFilesByContent:output_type -> gitaly.SearchFilesByContentResponse - 68, // 127: gitaly.RepositoryService.SearchFilesByName:output_type -> gitaly.SearchFilesByNameResponse - 50, // 128: gitaly.RepositoryService.RestoreCustomHooks:output_type -> gitaly.RestoreCustomHooksResponse - 52, // 129: gitaly.RepositoryService.BackupCustomHooks:output_type -> gitaly.BackupCustomHooksResponse - 73, // 130: gitaly.RepositoryService.GetObjectDirectorySize:output_type -> gitaly.GetObjectDirectorySizeResponse - 75, // 131: gitaly.RepositoryService.CloneFromPool:output_type -> gitaly.CloneFromPoolResponse - 77, // 132: gitaly.RepositoryService.CloneFromPoolInternal:output_type -> gitaly.CloneFromPoolInternalResponse - 79, // 133: gitaly.RepositoryService.RemoveRepository:output_type -> gitaly.RemoveRepositoryResponse - 81, // 134: gitaly.RepositoryService.RenameRepository:output_type -> gitaly.RenameRepositoryResponse - 83, // 135: gitaly.RepositoryService.ReplicateRepository:output_type -> gitaly.ReplicateRepositoryResponse - 85, // 136: gitaly.RepositoryService.OptimizeRepository:output_type -> gitaly.OptimizeRepositoryResponse - 87, // 137: gitaly.RepositoryService.SetFullPath:output_type -> gitaly.SetFullPathResponse - 96, // [96:138] is the sub-list for method output_type - 54, // [54:96] is the sub-list for method input_type - 54, // [54:54] is the sub-list for extension type_name - 54, // [54:54] is the sub-list for extension extendee - 0, // [0:54] is the sub-list for field type_name + 87, // 7: gitaly.CleanupRequest.repository:type_name -> gitaly.Repository + 87, // 8: gitaly.RepositorySizeRequest.repository:type_name -> gitaly.Repository + 87, // 9: gitaly.ApplyGitattributesRequest.repository:type_name -> gitaly.Repository + 87, // 10: gitaly.FetchRemoteRequest.repository:type_name -> gitaly.Repository + 69, // 11: gitaly.FetchRemoteRequest.remote_params:type_name -> gitaly.Remote + 87, // 12: gitaly.CreateRepositoryRequest.repository:type_name -> gitaly.Repository + 87, // 13: gitaly.GetArchiveRequest.repository:type_name -> gitaly.Repository + 1, // 14: gitaly.GetArchiveRequest.format:type_name -> gitaly.GetArchiveRequest.Format + 87, // 15: gitaly.HasLocalBranchesRequest.repository:type_name -> gitaly.Repository + 87, // 16: gitaly.FetchSourceBranchRequest.repository:type_name -> gitaly.Repository + 87, // 17: gitaly.FetchSourceBranchRequest.source_repository:type_name -> gitaly.Repository + 87, // 18: gitaly.FsckRequest.repository:type_name -> gitaly.Repository + 87, // 19: gitaly.WriteRefRequest.repository:type_name -> gitaly.Repository + 87, // 20: gitaly.FindMergeBaseRequest.repository:type_name -> gitaly.Repository + 87, // 21: gitaly.CreateForkRequest.repository:type_name -> gitaly.Repository + 87, // 22: gitaly.CreateForkRequest.source_repository:type_name -> gitaly.Repository + 87, // 23: gitaly.CreateRepositoryFromURLRequest.repository:type_name -> gitaly.Repository + 87, // 24: gitaly.CreateBundleRequest.repository:type_name -> gitaly.Repository + 87, // 25: gitaly.CreateBundleFromRefListRequest.repository:type_name -> gitaly.Repository + 87, // 26: gitaly.GetConfigRequest.repository:type_name -> gitaly.Repository + 87, // 27: gitaly.RestoreCustomHooksRequest.repository:type_name -> gitaly.Repository + 87, // 28: gitaly.BackupCustomHooksRequest.repository:type_name -> gitaly.Repository + 87, // 29: gitaly.CreateRepositoryFromBundleRequest.repository:type_name -> gitaly.Repository + 87, // 30: gitaly.FindLicenseRequest.repository:type_name -> gitaly.Repository + 87, // 31: gitaly.GetInfoAttributesRequest.repository:type_name -> gitaly.Repository + 87, // 32: gitaly.CalculateChecksumRequest.repository:type_name -> gitaly.Repository + 87, // 33: gitaly.GetSnapshotRequest.repository:type_name -> gitaly.Repository + 87, // 34: gitaly.CreateRepositoryFromSnapshotRequest.repository:type_name -> gitaly.Repository + 87, // 35: gitaly.GetRawChangesRequest.repository:type_name -> gitaly.Repository + 86, // 36: gitaly.GetRawChangesResponse.raw_changes:type_name -> gitaly.GetRawChangesResponse.RawChange + 87, // 37: gitaly.SearchFilesByNameRequest.repository:type_name -> gitaly.Repository + 87, // 38: gitaly.SearchFilesByContentRequest.repository:type_name -> gitaly.Repository + 87, // 39: gitaly.GetObjectDirectorySizeRequest.repository:type_name -> gitaly.Repository + 87, // 40: gitaly.CloneFromPoolRequest.repository:type_name -> gitaly.Repository + 88, // 41: gitaly.CloneFromPoolRequest.pool:type_name -> gitaly.ObjectPool + 69, // 42: gitaly.CloneFromPoolRequest.remote:type_name -> gitaly.Remote + 87, // 43: gitaly.CloneFromPoolInternalRequest.repository:type_name -> gitaly.Repository + 88, // 44: gitaly.CloneFromPoolInternalRequest.pool:type_name -> gitaly.ObjectPool + 87, // 45: gitaly.CloneFromPoolInternalRequest.source_repository:type_name -> gitaly.Repository + 87, // 46: gitaly.RemoveRepositoryRequest.repository:type_name -> gitaly.Repository + 87, // 47: gitaly.RenameRepositoryRequest.repository:type_name -> gitaly.Repository + 87, // 48: gitaly.ReplicateRepositoryRequest.repository:type_name -> gitaly.Repository + 87, // 49: gitaly.ReplicateRepositoryRequest.source:type_name -> gitaly.Repository + 87, // 50: gitaly.OptimizeRepositoryRequest.repository:type_name -> gitaly.Repository + 87, // 51: gitaly.SetFullPathRequest.repository:type_name -> gitaly.Repository + 2, // 52: gitaly.GetRawChangesResponse.RawChange.operation:type_name -> gitaly.GetRawChangesResponse.RawChange.Operation + 3, // 53: gitaly.RepositoryService.RepositoryExists:input_type -> gitaly.RepositoryExistsRequest + 5, // 54: gitaly.RepositoryService.RepackIncremental:input_type -> gitaly.RepackIncrementalRequest + 7, // 55: gitaly.RepositoryService.RepackFull:input_type -> gitaly.RepackFullRequest + 9, // 56: gitaly.RepositoryService.MidxRepack:input_type -> gitaly.MidxRepackRequest + 11, // 57: gitaly.RepositoryService.GarbageCollect:input_type -> gitaly.GarbageCollectRequest + 13, // 58: gitaly.RepositoryService.WriteCommitGraph:input_type -> gitaly.WriteCommitGraphRequest + 17, // 59: gitaly.RepositoryService.RepositorySize:input_type -> gitaly.RepositorySizeRequest + 19, // 60: gitaly.RepositoryService.ApplyGitattributes:input_type -> gitaly.ApplyGitattributesRequest + 21, // 61: gitaly.RepositoryService.FetchRemote:input_type -> gitaly.FetchRemoteRequest + 23, // 62: gitaly.RepositoryService.CreateRepository:input_type -> gitaly.CreateRepositoryRequest + 25, // 63: gitaly.RepositoryService.GetArchive:input_type -> gitaly.GetArchiveRequest + 27, // 64: gitaly.RepositoryService.HasLocalBranches:input_type -> gitaly.HasLocalBranchesRequest + 29, // 65: gitaly.RepositoryService.FetchSourceBranch:input_type -> gitaly.FetchSourceBranchRequest + 31, // 66: gitaly.RepositoryService.Fsck:input_type -> gitaly.FsckRequest + 33, // 67: gitaly.RepositoryService.WriteRef:input_type -> gitaly.WriteRefRequest + 35, // 68: gitaly.RepositoryService.FindMergeBase:input_type -> gitaly.FindMergeBaseRequest + 37, // 69: gitaly.RepositoryService.CreateFork:input_type -> gitaly.CreateForkRequest + 39, // 70: gitaly.RepositoryService.CreateRepositoryFromURL:input_type -> gitaly.CreateRepositoryFromURLRequest + 41, // 71: gitaly.RepositoryService.CreateBundle:input_type -> gitaly.CreateBundleRequest + 43, // 72: gitaly.RepositoryService.CreateBundleFromRefList:input_type -> gitaly.CreateBundleFromRefListRequest + 51, // 73: gitaly.RepositoryService.CreateRepositoryFromBundle:input_type -> gitaly.CreateRepositoryFromBundleRequest + 45, // 74: gitaly.RepositoryService.GetConfig:input_type -> gitaly.GetConfigRequest + 53, // 75: gitaly.RepositoryService.FindLicense:input_type -> gitaly.FindLicenseRequest + 55, // 76: gitaly.RepositoryService.GetInfoAttributes:input_type -> gitaly.GetInfoAttributesRequest + 57, // 77: gitaly.RepositoryService.CalculateChecksum:input_type -> gitaly.CalculateChecksumRequest + 15, // 78: gitaly.RepositoryService.Cleanup:input_type -> gitaly.CleanupRequest + 59, // 79: gitaly.RepositoryService.GetSnapshot:input_type -> gitaly.GetSnapshotRequest + 61, // 80: gitaly.RepositoryService.CreateRepositoryFromSnapshot:input_type -> gitaly.CreateRepositoryFromSnapshotRequest + 63, // 81: gitaly.RepositoryService.GetRawChanges:input_type -> gitaly.GetRawChangesRequest + 67, // 82: gitaly.RepositoryService.SearchFilesByContent:input_type -> gitaly.SearchFilesByContentRequest + 65, // 83: gitaly.RepositoryService.SearchFilesByName:input_type -> gitaly.SearchFilesByNameRequest + 47, // 84: gitaly.RepositoryService.RestoreCustomHooks:input_type -> gitaly.RestoreCustomHooksRequest + 49, // 85: gitaly.RepositoryService.BackupCustomHooks:input_type -> gitaly.BackupCustomHooksRequest + 70, // 86: gitaly.RepositoryService.GetObjectDirectorySize:input_type -> gitaly.GetObjectDirectorySizeRequest + 72, // 87: gitaly.RepositoryService.CloneFromPool:input_type -> gitaly.CloneFromPoolRequest + 74, // 88: gitaly.RepositoryService.CloneFromPoolInternal:input_type -> gitaly.CloneFromPoolInternalRequest + 76, // 89: gitaly.RepositoryService.RemoveRepository:input_type -> gitaly.RemoveRepositoryRequest + 78, // 90: gitaly.RepositoryService.RenameRepository:input_type -> gitaly.RenameRepositoryRequest + 80, // 91: gitaly.RepositoryService.ReplicateRepository:input_type -> gitaly.ReplicateRepositoryRequest + 82, // 92: gitaly.RepositoryService.OptimizeRepository:input_type -> gitaly.OptimizeRepositoryRequest + 84, // 93: gitaly.RepositoryService.SetFullPath:input_type -> gitaly.SetFullPathRequest + 4, // 94: gitaly.RepositoryService.RepositoryExists:output_type -> gitaly.RepositoryExistsResponse + 6, // 95: gitaly.RepositoryService.RepackIncremental:output_type -> gitaly.RepackIncrementalResponse + 8, // 96: gitaly.RepositoryService.RepackFull:output_type -> gitaly.RepackFullResponse + 10, // 97: gitaly.RepositoryService.MidxRepack:output_type -> gitaly.MidxRepackResponse + 12, // 98: gitaly.RepositoryService.GarbageCollect:output_type -> gitaly.GarbageCollectResponse + 14, // 99: gitaly.RepositoryService.WriteCommitGraph:output_type -> gitaly.WriteCommitGraphResponse + 18, // 100: gitaly.RepositoryService.RepositorySize:output_type -> gitaly.RepositorySizeResponse + 20, // 101: gitaly.RepositoryService.ApplyGitattributes:output_type -> gitaly.ApplyGitattributesResponse + 22, // 102: gitaly.RepositoryService.FetchRemote:output_type -> gitaly.FetchRemoteResponse + 24, // 103: gitaly.RepositoryService.CreateRepository:output_type -> gitaly.CreateRepositoryResponse + 26, // 104: gitaly.RepositoryService.GetArchive:output_type -> gitaly.GetArchiveResponse + 28, // 105: gitaly.RepositoryService.HasLocalBranches:output_type -> gitaly.HasLocalBranchesResponse + 30, // 106: gitaly.RepositoryService.FetchSourceBranch:output_type -> gitaly.FetchSourceBranchResponse + 32, // 107: gitaly.RepositoryService.Fsck:output_type -> gitaly.FsckResponse + 34, // 108: gitaly.RepositoryService.WriteRef:output_type -> gitaly.WriteRefResponse + 36, // 109: gitaly.RepositoryService.FindMergeBase:output_type -> gitaly.FindMergeBaseResponse + 38, // 110: gitaly.RepositoryService.CreateFork:output_type -> gitaly.CreateForkResponse + 40, // 111: gitaly.RepositoryService.CreateRepositoryFromURL:output_type -> gitaly.CreateRepositoryFromURLResponse + 42, // 112: gitaly.RepositoryService.CreateBundle:output_type -> gitaly.CreateBundleResponse + 44, // 113: gitaly.RepositoryService.CreateBundleFromRefList:output_type -> gitaly.CreateBundleFromRefListResponse + 52, // 114: gitaly.RepositoryService.CreateRepositoryFromBundle:output_type -> gitaly.CreateRepositoryFromBundleResponse + 46, // 115: gitaly.RepositoryService.GetConfig:output_type -> gitaly.GetConfigResponse + 54, // 116: gitaly.RepositoryService.FindLicense:output_type -> gitaly.FindLicenseResponse + 56, // 117: gitaly.RepositoryService.GetInfoAttributes:output_type -> gitaly.GetInfoAttributesResponse + 58, // 118: gitaly.RepositoryService.CalculateChecksum:output_type -> gitaly.CalculateChecksumResponse + 16, // 119: gitaly.RepositoryService.Cleanup:output_type -> gitaly.CleanupResponse + 60, // 120: gitaly.RepositoryService.GetSnapshot:output_type -> gitaly.GetSnapshotResponse + 62, // 121: gitaly.RepositoryService.CreateRepositoryFromSnapshot:output_type -> gitaly.CreateRepositoryFromSnapshotResponse + 64, // 122: gitaly.RepositoryService.GetRawChanges:output_type -> gitaly.GetRawChangesResponse + 68, // 123: gitaly.RepositoryService.SearchFilesByContent:output_type -> gitaly.SearchFilesByContentResponse + 66, // 124: gitaly.RepositoryService.SearchFilesByName:output_type -> gitaly.SearchFilesByNameResponse + 48, // 125: gitaly.RepositoryService.RestoreCustomHooks:output_type -> gitaly.RestoreCustomHooksResponse + 50, // 126: gitaly.RepositoryService.BackupCustomHooks:output_type -> gitaly.BackupCustomHooksResponse + 71, // 127: gitaly.RepositoryService.GetObjectDirectorySize:output_type -> gitaly.GetObjectDirectorySizeResponse + 73, // 128: gitaly.RepositoryService.CloneFromPool:output_type -> gitaly.CloneFromPoolResponse + 75, // 129: gitaly.RepositoryService.CloneFromPoolInternal:output_type -> gitaly.CloneFromPoolInternalResponse + 77, // 130: gitaly.RepositoryService.RemoveRepository:output_type -> gitaly.RemoveRepositoryResponse + 79, // 131: gitaly.RepositoryService.RenameRepository:output_type -> gitaly.RenameRepositoryResponse + 81, // 132: gitaly.RepositoryService.ReplicateRepository:output_type -> gitaly.ReplicateRepositoryResponse + 83, // 133: gitaly.RepositoryService.OptimizeRepository:output_type -> gitaly.OptimizeRepositoryResponse + 85, // 134: gitaly.RepositoryService.SetFullPath:output_type -> gitaly.SetFullPathResponse + 94, // [94:135] is the sub-list for method output_type + 53, // [53:94] is the sub-list for method input_type + 53, // [53:53] is the sub-list for extension type_name + 53, // [53:53] is the sub-list for extension extendee + 0, // [0:53] is the sub-list for field type_name } func init() { file_repository_service_proto_init() } @@ -5837,30 +5725,6 @@ func file_repository_service_proto_init() { } } file_repository_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FetchBundleRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_repository_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FetchBundleResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_repository_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FetchRemoteRequest); i { case 0: return &v.state @@ -5872,7 +5736,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FetchRemoteResponse); i { case 0: return &v.state @@ -5884,7 +5748,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryRequest); i { case 0: return &v.state @@ -5896,7 +5760,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryResponse); i { case 0: return &v.state @@ -5908,7 +5772,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetArchiveRequest); i { case 0: return &v.state @@ -5920,7 +5784,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetArchiveResponse); i { case 0: return &v.state @@ -5932,7 +5796,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HasLocalBranchesRequest); i { case 0: return &v.state @@ -5944,7 +5808,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HasLocalBranchesResponse); i { case 0: return &v.state @@ -5956,7 +5820,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FetchSourceBranchRequest); i { case 0: return &v.state @@ -5968,7 +5832,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FetchSourceBranchResponse); i { case 0: return &v.state @@ -5980,7 +5844,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FsckRequest); i { case 0: return &v.state @@ -5992,7 +5856,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FsckResponse); i { case 0: return &v.state @@ -6004,7 +5868,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WriteRefRequest); i { case 0: return &v.state @@ -6016,7 +5880,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WriteRefResponse); i { case 0: return &v.state @@ -6028,7 +5892,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FindMergeBaseRequest); i { case 0: return &v.state @@ -6040,7 +5904,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FindMergeBaseResponse); i { case 0: return &v.state @@ -6052,7 +5916,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateForkRequest); i { case 0: return &v.state @@ -6064,7 +5928,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateForkResponse); i { case 0: return &v.state @@ -6076,7 +5940,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryFromURLRequest); i { case 0: return &v.state @@ -6088,7 +5952,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryFromURLResponse); i { case 0: return &v.state @@ -6100,7 +5964,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateBundleRequest); i { case 0: return &v.state @@ -6112,7 +5976,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateBundleResponse); i { case 0: return &v.state @@ -6124,7 +5988,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateBundleFromRefListRequest); i { case 0: return &v.state @@ -6136,7 +6000,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateBundleFromRefListResponse); i { case 0: return &v.state @@ -6148,7 +6012,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetConfigRequest); i { case 0: return &v.state @@ -6160,7 +6024,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetConfigResponse); i { case 0: return &v.state @@ -6172,7 +6036,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RestoreCustomHooksRequest); i { case 0: return &v.state @@ -6184,7 +6048,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RestoreCustomHooksResponse); i { case 0: return &v.state @@ -6196,7 +6060,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BackupCustomHooksRequest); i { case 0: return &v.state @@ -6208,7 +6072,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BackupCustomHooksResponse); i { case 0: return &v.state @@ -6220,7 +6084,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryFromBundleRequest); i { case 0: return &v.state @@ -6232,7 +6096,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryFromBundleResponse); i { case 0: return &v.state @@ -6244,7 +6108,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FindLicenseRequest); i { case 0: return &v.state @@ -6256,7 +6120,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FindLicenseResponse); i { case 0: return &v.state @@ -6268,7 +6132,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetInfoAttributesRequest); i { case 0: return &v.state @@ -6280,7 +6144,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetInfoAttributesResponse); i { case 0: return &v.state @@ -6292,7 +6156,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CalculateChecksumRequest); i { case 0: return &v.state @@ -6304,7 +6168,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CalculateChecksumResponse); i { case 0: return &v.state @@ -6316,7 +6180,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetSnapshotRequest); i { case 0: return &v.state @@ -6328,7 +6192,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetSnapshotResponse); i { case 0: return &v.state @@ -6340,7 +6204,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryFromSnapshotRequest); i { case 0: return &v.state @@ -6352,7 +6216,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRepositoryFromSnapshotResponse); i { case 0: return &v.state @@ -6364,7 +6228,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRawChangesRequest); i { case 0: return &v.state @@ -6376,7 +6240,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRawChangesResponse); i { case 0: return &v.state @@ -6388,7 +6252,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SearchFilesByNameRequest); i { case 0: return &v.state @@ -6400,7 +6264,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SearchFilesByNameResponse); i { case 0: return &v.state @@ -6412,7 +6276,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SearchFilesByContentRequest); i { case 0: return &v.state @@ -6424,7 +6288,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SearchFilesByContentResponse); i { case 0: return &v.state @@ -6436,7 +6300,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Remote); i { case 0: return &v.state @@ -6448,7 +6312,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetObjectDirectorySizeRequest); i { case 0: return &v.state @@ -6460,7 +6324,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetObjectDirectorySizeResponse); i { case 0: return &v.state @@ -6472,7 +6336,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloneFromPoolRequest); i { case 0: return &v.state @@ -6484,7 +6348,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloneFromPoolResponse); i { case 0: return &v.state @@ -6496,7 +6360,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloneFromPoolInternalRequest); i { case 0: return &v.state @@ -6508,7 +6372,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloneFromPoolInternalResponse); i { case 0: return &v.state @@ -6520,7 +6384,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoveRepositoryRequest); i { case 0: return &v.state @@ -6532,7 +6396,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoveRepositoryResponse); i { case 0: return &v.state @@ -6544,7 +6408,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RenameRepositoryRequest); i { case 0: return &v.state @@ -6556,7 +6420,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RenameRepositoryResponse); i { case 0: return &v.state @@ -6568,7 +6432,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReplicateRepositoryRequest); i { case 0: return &v.state @@ -6580,7 +6444,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReplicateRepositoryResponse); i { case 0: return &v.state @@ -6592,7 +6456,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OptimizeRepositoryRequest); i { case 0: return &v.state @@ -6604,7 +6468,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OptimizeRepositoryResponse); i { case 0: return &v.state @@ -6616,7 +6480,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SetFullPathRequest); i { case 0: return &v.state @@ -6628,7 +6492,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SetFullPathResponse); i { case 0: return &v.state @@ -6640,7 +6504,7 @@ func file_repository_service_proto_init() { return nil } } - file_repository_service_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { + file_repository_service_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRawChangesResponse_RawChange); i { case 0: return &v.state @@ -6659,7 +6523,7 @@ func file_repository_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_repository_service_proto_rawDesc, NumEnums: 3, - NumMessages: 86, + NumMessages: 84, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/go/gitalypb/repository-service_grpc.pb.go b/proto/go/gitalypb/repository-service_grpc.pb.go index 50da376fa..e871e3f0d 100644 --- a/proto/go/gitalypb/repository-service_grpc.pb.go +++ b/proto/go/gitalypb/repository-service_grpc.pb.go @@ -42,13 +42,8 @@ type RepositoryServiceClient interface { CreateRepositoryFromURL(ctx context.Context, in *CreateRepositoryFromURLRequest, opts ...grpc.CallOption) (*CreateRepositoryFromURLResponse, error) // CreateBundle creates a bundle from all refs CreateBundle(ctx context.Context, in *CreateBundleRequest, opts ...grpc.CallOption) (RepositoryService_CreateBundleClient, error) - // CreateBundleFromRefList creates a bundle from a stream of ref patterns. - // When the bundle would be empty the FailedPrecondition error code is returned. + // CreateBundleFromRefList creates a bundle from a stream of ref patterns CreateBundleFromRefList(ctx context.Context, opts ...grpc.CallOption) (RepositoryService_CreateBundleFromRefListClient, error) - // FetchBundle fetches references from a bundle into the local repository. - // Refs will be mirrored to the target repository with the refspec - // "+refs/*:refs/*" and refs that do not exist in the bundle will be removed. - FetchBundle(ctx context.Context, opts ...grpc.CallOption) (RepositoryService_FetchBundleClient, error) CreateRepositoryFromBundle(ctx context.Context, opts ...grpc.CallOption) (RepositoryService_CreateRepositoryFromBundleClient, error) // GetConfig reads the target repository's gitconfig and streams its contents // back. Returns a NotFound error in case no gitconfig was found. @@ -337,42 +332,8 @@ func (x *repositoryServiceCreateBundleFromRefListClient) Recv() (*CreateBundleFr return m, nil } -func (c *repositoryServiceClient) FetchBundle(ctx context.Context, opts ...grpc.CallOption) (RepositoryService_FetchBundleClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[3], "/gitaly.RepositoryService/FetchBundle", opts...) - if err != nil { - return nil, err - } - x := &repositoryServiceFetchBundleClient{stream} - return x, nil -} - -type RepositoryService_FetchBundleClient interface { - Send(*FetchBundleRequest) error - CloseAndRecv() (*FetchBundleResponse, error) - grpc.ClientStream -} - -type repositoryServiceFetchBundleClient struct { - grpc.ClientStream -} - -func (x *repositoryServiceFetchBundleClient) Send(m *FetchBundleRequest) error { - return x.ClientStream.SendMsg(m) -} - -func (x *repositoryServiceFetchBundleClient) CloseAndRecv() (*FetchBundleResponse, error) { - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - m := new(FetchBundleResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - func (c *repositoryServiceClient) CreateRepositoryFromBundle(ctx context.Context, opts ...grpc.CallOption) (RepositoryService_CreateRepositoryFromBundleClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[4], "/gitaly.RepositoryService/CreateRepositoryFromBundle", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[3], "/gitaly.RepositoryService/CreateRepositoryFromBundle", opts...) if err != nil { return nil, err } @@ -406,7 +367,7 @@ func (x *repositoryServiceCreateRepositoryFromBundleClient) CloseAndRecv() (*Cre } func (c *repositoryServiceClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (RepositoryService_GetConfigClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[5], "/gitaly.RepositoryService/GetConfig", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[4], "/gitaly.RepositoryService/GetConfig", opts...) if err != nil { return nil, err } @@ -447,7 +408,7 @@ func (c *repositoryServiceClient) FindLicense(ctx context.Context, in *FindLicen } func (c *repositoryServiceClient) GetInfoAttributes(ctx context.Context, in *GetInfoAttributesRequest, opts ...grpc.CallOption) (RepositoryService_GetInfoAttributesClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[6], "/gitaly.RepositoryService/GetInfoAttributes", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[5], "/gitaly.RepositoryService/GetInfoAttributes", opts...) if err != nil { return nil, err } @@ -497,7 +458,7 @@ func (c *repositoryServiceClient) Cleanup(ctx context.Context, in *CleanupReques } func (c *repositoryServiceClient) GetSnapshot(ctx context.Context, in *GetSnapshotRequest, opts ...grpc.CallOption) (RepositoryService_GetSnapshotClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[7], "/gitaly.RepositoryService/GetSnapshot", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[6], "/gitaly.RepositoryService/GetSnapshot", opts...) if err != nil { return nil, err } @@ -538,7 +499,7 @@ func (c *repositoryServiceClient) CreateRepositoryFromSnapshot(ctx context.Conte } func (c *repositoryServiceClient) GetRawChanges(ctx context.Context, in *GetRawChangesRequest, opts ...grpc.CallOption) (RepositoryService_GetRawChangesClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[8], "/gitaly.RepositoryService/GetRawChanges", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[7], "/gitaly.RepositoryService/GetRawChanges", opts...) if err != nil { return nil, err } @@ -570,7 +531,7 @@ func (x *repositoryServiceGetRawChangesClient) Recv() (*GetRawChangesResponse, e } func (c *repositoryServiceClient) SearchFilesByContent(ctx context.Context, in *SearchFilesByContentRequest, opts ...grpc.CallOption) (RepositoryService_SearchFilesByContentClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[9], "/gitaly.RepositoryService/SearchFilesByContent", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[8], "/gitaly.RepositoryService/SearchFilesByContent", opts...) if err != nil { return nil, err } @@ -602,7 +563,7 @@ func (x *repositoryServiceSearchFilesByContentClient) Recv() (*SearchFilesByCont } func (c *repositoryServiceClient) SearchFilesByName(ctx context.Context, in *SearchFilesByNameRequest, opts ...grpc.CallOption) (RepositoryService_SearchFilesByNameClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[10], "/gitaly.RepositoryService/SearchFilesByName", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[9], "/gitaly.RepositoryService/SearchFilesByName", opts...) if err != nil { return nil, err } @@ -634,7 +595,7 @@ func (x *repositoryServiceSearchFilesByNameClient) Recv() (*SearchFilesByNameRes } func (c *repositoryServiceClient) RestoreCustomHooks(ctx context.Context, opts ...grpc.CallOption) (RepositoryService_RestoreCustomHooksClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[11], "/gitaly.RepositoryService/RestoreCustomHooks", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[10], "/gitaly.RepositoryService/RestoreCustomHooks", opts...) if err != nil { return nil, err } @@ -668,7 +629,7 @@ func (x *repositoryServiceRestoreCustomHooksClient) CloseAndRecv() (*RestoreCust } func (c *repositoryServiceClient) BackupCustomHooks(ctx context.Context, in *BackupCustomHooksRequest, opts ...grpc.CallOption) (RepositoryService_BackupCustomHooksClient, error) { - stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[12], "/gitaly.RepositoryService/BackupCustomHooks", opts...) + stream, err := c.cc.NewStream(ctx, &RepositoryService_ServiceDesc.Streams[11], "/gitaly.RepositoryService/BackupCustomHooks", opts...) if err != nil { return nil, err } @@ -799,13 +760,8 @@ type RepositoryServiceServer interface { CreateRepositoryFromURL(context.Context, *CreateRepositoryFromURLRequest) (*CreateRepositoryFromURLResponse, error) // CreateBundle creates a bundle from all refs CreateBundle(*CreateBundleRequest, RepositoryService_CreateBundleServer) error - // CreateBundleFromRefList creates a bundle from a stream of ref patterns. - // When the bundle would be empty the FailedPrecondition error code is returned. + // CreateBundleFromRefList creates a bundle from a stream of ref patterns CreateBundleFromRefList(RepositoryService_CreateBundleFromRefListServer) error - // FetchBundle fetches references from a bundle into the local repository. - // Refs will be mirrored to the target repository with the refspec - // "+refs/*:refs/*" and refs that do not exist in the bundle will be removed. - FetchBundle(RepositoryService_FetchBundleServer) error CreateRepositoryFromBundle(RepositoryService_CreateRepositoryFromBundleServer) error // GetConfig reads the target repository's gitconfig and streams its contents // back. Returns a NotFound error in case no gitconfig was found. @@ -903,9 +859,6 @@ func (UnimplementedRepositoryServiceServer) CreateBundle(*CreateBundleRequest, R func (UnimplementedRepositoryServiceServer) CreateBundleFromRefList(RepositoryService_CreateBundleFromRefListServer) error { return status.Errorf(codes.Unimplemented, "method CreateBundleFromRefList not implemented") } -func (UnimplementedRepositoryServiceServer) FetchBundle(RepositoryService_FetchBundleServer) error { - return status.Errorf(codes.Unimplemented, "method FetchBundle not implemented") -} func (UnimplementedRepositoryServiceServer) CreateRepositoryFromBundle(RepositoryService_CreateRepositoryFromBundleServer) error { return status.Errorf(codes.Unimplemented, "method CreateRepositoryFromBundle not implemented") } @@ -1356,32 +1309,6 @@ func (x *repositoryServiceCreateBundleFromRefListServer) Recv() (*CreateBundleFr return m, nil } -func _RepositoryService_FetchBundle_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(RepositoryServiceServer).FetchBundle(&repositoryServiceFetchBundleServer{stream}) -} - -type RepositoryService_FetchBundleServer interface { - SendAndClose(*FetchBundleResponse) error - Recv() (*FetchBundleRequest, error) - grpc.ServerStream -} - -type repositoryServiceFetchBundleServer struct { - grpc.ServerStream -} - -func (x *repositoryServiceFetchBundleServer) SendAndClose(m *FetchBundleResponse) error { - return x.ServerStream.SendMsg(m) -} - -func (x *repositoryServiceFetchBundleServer) Recv() (*FetchBundleRequest, error) { - m := new(FetchBundleRequest) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - func _RepositoryService_CreateRepositoryFromBundle_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(RepositoryServiceServer).CreateRepositoryFromBundle(&repositoryServiceCreateRepositoryFromBundleServer{stream}) } @@ -1939,11 +1866,6 @@ var RepositoryService_ServiceDesc = grpc.ServiceDesc{ ClientStreams: true, }, { - StreamName: "FetchBundle", - Handler: _RepositoryService_FetchBundle_Handler, - ClientStreams: true, - }, - { StreamName: "CreateRepositoryFromBundle", Handler: _RepositoryService_CreateRepositoryFromBundle_Handler, ClientStreams: true, diff --git a/proto/go/gitalypb/smarthttp.pb.go b/proto/go/gitalypb/smarthttp.pb.go index e7ec4a48a..bbedd31b2 100644 --- a/proto/go/gitalypb/smarthttp.pb.go +++ b/proto/go/gitalypb/smarthttp.pb.go @@ -255,110 +255,6 @@ func (x *PostUploadPackResponse) GetData() []byte { return nil } -type PostUploadPackWithSidechannelRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // repository should only be present in the first message of the stream - Repository *Repository `protobuf:"bytes,1,opt,name=repository,proto3" json:"repository,omitempty"` - // Parameters to use with git -c (key=value pairs) - GitConfigOptions []string `protobuf:"bytes,2,rep,name=git_config_options,json=gitConfigOptions,proto3" json:"git_config_options,omitempty"` - // Git protocol version - GitProtocol string `protobuf:"bytes,3,opt,name=git_protocol,json=gitProtocol,proto3" json:"git_protocol,omitempty"` -} - -func (x *PostUploadPackWithSidechannelRequest) Reset() { - *x = PostUploadPackWithSidechannelRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_smarthttp_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PostUploadPackWithSidechannelRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PostUploadPackWithSidechannelRequest) ProtoMessage() {} - -func (x *PostUploadPackWithSidechannelRequest) ProtoReflect() protoreflect.Message { - mi := &file_smarthttp_proto_msgTypes[4] - 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 PostUploadPackWithSidechannelRequest.ProtoReflect.Descriptor instead. -func (*PostUploadPackWithSidechannelRequest) Descriptor() ([]byte, []int) { - return file_smarthttp_proto_rawDescGZIP(), []int{4} -} - -func (x *PostUploadPackWithSidechannelRequest) GetRepository() *Repository { - if x != nil { - return x.Repository - } - return nil -} - -func (x *PostUploadPackWithSidechannelRequest) GetGitConfigOptions() []string { - if x != nil { - return x.GitConfigOptions - } - return nil -} - -func (x *PostUploadPackWithSidechannelRequest) GetGitProtocol() string { - if x != nil { - return x.GitProtocol - } - return "" -} - -type PostUploadPackWithSidechannelResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *PostUploadPackWithSidechannelResponse) Reset() { - *x = PostUploadPackWithSidechannelResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_smarthttp_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PostUploadPackWithSidechannelResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PostUploadPackWithSidechannelResponse) ProtoMessage() {} - -func (x *PostUploadPackWithSidechannelResponse) ProtoReflect() protoreflect.Message { - mi := &file_smarthttp_proto_msgTypes[5] - 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 PostUploadPackWithSidechannelResponse.ProtoReflect.Descriptor instead. -func (*PostUploadPackWithSidechannelResponse) Descriptor() ([]byte, []int) { - return file_smarthttp_proto_rawDescGZIP(), []int{5} -} - type PostReceivePackRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -382,7 +278,7 @@ type PostReceivePackRequest struct { func (x *PostReceivePackRequest) Reset() { *x = PostReceivePackRequest{} if protoimpl.UnsafeEnabled { - mi := &file_smarthttp_proto_msgTypes[6] + mi := &file_smarthttp_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -395,7 +291,7 @@ func (x *PostReceivePackRequest) String() string { func (*PostReceivePackRequest) ProtoMessage() {} func (x *PostReceivePackRequest) ProtoReflect() protoreflect.Message { - mi := &file_smarthttp_proto_msgTypes[6] + mi := &file_smarthttp_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -408,7 +304,7 @@ func (x *PostReceivePackRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PostReceivePackRequest.ProtoReflect.Descriptor instead. func (*PostReceivePackRequest) Descriptor() ([]byte, []int) { - return file_smarthttp_proto_rawDescGZIP(), []int{6} + return file_smarthttp_proto_rawDescGZIP(), []int{4} } func (x *PostReceivePackRequest) GetRepository() *Repository { @@ -472,7 +368,7 @@ type PostReceivePackResponse struct { func (x *PostReceivePackResponse) Reset() { *x = PostReceivePackResponse{} if protoimpl.UnsafeEnabled { - mi := &file_smarthttp_proto_msgTypes[7] + mi := &file_smarthttp_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -485,7 +381,7 @@ func (x *PostReceivePackResponse) String() string { func (*PostReceivePackResponse) ProtoMessage() {} func (x *PostReceivePackResponse) ProtoReflect() protoreflect.Message { - mi := &file_smarthttp_proto_msgTypes[7] + mi := &file_smarthttp_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -498,7 +394,7 @@ func (x *PostReceivePackResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PostReceivePackResponse.ProtoReflect.Descriptor instead. func (*PostReceivePackResponse) Descriptor() ([]byte, []int) { - return file_smarthttp_proto_rawDescGZIP(), []int{7} + return file_smarthttp_proto_rawDescGZIP(), []int{5} } func (x *PostReceivePackResponse) GetData() []byte { @@ -541,76 +437,54 @@ var file_smarthttp_proto_rawDesc = []byte{ 0x63, 0x6f, 0x6c, 0x22, 0x2c, 0x0a, 0x16, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x22, 0xb1, 0x01, 0x0a, 0x24, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, - 0x50, 0x61, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 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, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x10, 0x67, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x69, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x69, 0x74, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x27, 0x0a, 0x25, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, - 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x64, 0x65, 0x63, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x92, - 0x02, 0x0a, 0x16, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, - 0x63, 0x6b, 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, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x13, 0x0a, 0x05, 0x67, 0x6c, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6c, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, - 0x67, 0x6c, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x6c, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x69, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x69, 0x74, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x2d, 0x0a, 0x17, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x32, 0xfd, 0x03, 0x0a, 0x10, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x48, 0x54, 0x54, 0x50, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x12, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x66, 0x73, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x17, 0x2e, + 0x61, 0x22, 0x92, 0x02, 0x0a, 0x16, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x65, 0x50, 0x61, 0x63, 0x6b, 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, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x13, 0x0a, 0x05, 0x67, 0x6c, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6c, 0x49, 0x64, 0x12, + 0x23, 0x0a, 0x0d, 0x67, 0x6c, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x6c, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x6c, 0x55, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x69, 0x74, 0x5f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x69, 0x74, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x2d, 0x0a, 0x17, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xf6, 0x02, 0x0a, 0x10, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x48, + 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x12, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, + 0x12, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x66, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, + 0x6c, 0x79, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x52, 0x0a, + 0x13, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x50, 0x61, 0x63, 0x6b, 0x12, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x13, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x63, - 0x6b, 0x12, 0x17, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x66, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x69, 0x74, - 0x61, 0x6c, 0x79, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x66, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x5b, - 0x0a, 0x0e, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, - 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, - 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x28, 0x01, 0x30, 0x01, 0x12, 0x84, 0x01, 0x0a, 0x1d, - 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x57, 0x69, - 0x74, 0x68, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x2c, 0x2e, - 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, - 0x64, 0x50, 0x61, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x69, - 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, - 0x61, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, - 0x08, 0x02, 0x12, 0x5e, 0x0a, 0x0f, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, - 0x6f, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, - 0x6f, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, - 0x30, 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, 0x34, 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, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, + 0x01, 0x12, 0x5b, 0x0a, 0x0e, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, + 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, + 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, + 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x28, 0x01, 0x30, 0x01, 0x12, 0x5e, + 0x0a, 0x0f, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x63, + 0x6b, 0x12, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x28, 0x01, 0x30, 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, 0x34, 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 ( @@ -625,38 +499,33 @@ func file_smarthttp_proto_rawDescGZIP() []byte { return file_smarthttp_proto_rawDescData } -var file_smarthttp_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_smarthttp_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_smarthttp_proto_goTypes = []interface{}{ - (*InfoRefsRequest)(nil), // 0: gitaly.InfoRefsRequest - (*InfoRefsResponse)(nil), // 1: gitaly.InfoRefsResponse - (*PostUploadPackRequest)(nil), // 2: gitaly.PostUploadPackRequest - (*PostUploadPackResponse)(nil), // 3: gitaly.PostUploadPackResponse - (*PostUploadPackWithSidechannelRequest)(nil), // 4: gitaly.PostUploadPackWithSidechannelRequest - (*PostUploadPackWithSidechannelResponse)(nil), // 5: gitaly.PostUploadPackWithSidechannelResponse - (*PostReceivePackRequest)(nil), // 6: gitaly.PostReceivePackRequest - (*PostReceivePackResponse)(nil), // 7: gitaly.PostReceivePackResponse - (*Repository)(nil), // 8: gitaly.Repository + (*InfoRefsRequest)(nil), // 0: gitaly.InfoRefsRequest + (*InfoRefsResponse)(nil), // 1: gitaly.InfoRefsResponse + (*PostUploadPackRequest)(nil), // 2: gitaly.PostUploadPackRequest + (*PostUploadPackResponse)(nil), // 3: gitaly.PostUploadPackResponse + (*PostReceivePackRequest)(nil), // 4: gitaly.PostReceivePackRequest + (*PostReceivePackResponse)(nil), // 5: gitaly.PostReceivePackResponse + (*Repository)(nil), // 6: gitaly.Repository } var file_smarthttp_proto_depIdxs = []int32{ - 8, // 0: gitaly.InfoRefsRequest.repository:type_name -> gitaly.Repository - 8, // 1: gitaly.PostUploadPackRequest.repository:type_name -> gitaly.Repository - 8, // 2: gitaly.PostUploadPackWithSidechannelRequest.repository:type_name -> gitaly.Repository - 8, // 3: gitaly.PostReceivePackRequest.repository:type_name -> gitaly.Repository - 0, // 4: gitaly.SmartHTTPService.InfoRefsUploadPack:input_type -> gitaly.InfoRefsRequest - 0, // 5: gitaly.SmartHTTPService.InfoRefsReceivePack:input_type -> gitaly.InfoRefsRequest - 2, // 6: gitaly.SmartHTTPService.PostUploadPack:input_type -> gitaly.PostUploadPackRequest - 4, // 7: gitaly.SmartHTTPService.PostUploadPackWithSidechannel:input_type -> gitaly.PostUploadPackWithSidechannelRequest - 6, // 8: gitaly.SmartHTTPService.PostReceivePack:input_type -> gitaly.PostReceivePackRequest - 1, // 9: gitaly.SmartHTTPService.InfoRefsUploadPack:output_type -> gitaly.InfoRefsResponse - 1, // 10: gitaly.SmartHTTPService.InfoRefsReceivePack:output_type -> gitaly.InfoRefsResponse - 3, // 11: gitaly.SmartHTTPService.PostUploadPack:output_type -> gitaly.PostUploadPackResponse - 5, // 12: gitaly.SmartHTTPService.PostUploadPackWithSidechannel:output_type -> gitaly.PostUploadPackWithSidechannelResponse - 7, // 13: gitaly.SmartHTTPService.PostReceivePack:output_type -> gitaly.PostReceivePackResponse - 9, // [9:14] is the sub-list for method output_type - 4, // [4:9] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 6, // 0: gitaly.InfoRefsRequest.repository:type_name -> gitaly.Repository + 6, // 1: gitaly.PostUploadPackRequest.repository:type_name -> gitaly.Repository + 6, // 2: gitaly.PostReceivePackRequest.repository:type_name -> gitaly.Repository + 0, // 3: gitaly.SmartHTTPService.InfoRefsUploadPack:input_type -> gitaly.InfoRefsRequest + 0, // 4: gitaly.SmartHTTPService.InfoRefsReceivePack:input_type -> gitaly.InfoRefsRequest + 2, // 5: gitaly.SmartHTTPService.PostUploadPack:input_type -> gitaly.PostUploadPackRequest + 4, // 6: gitaly.SmartHTTPService.PostReceivePack:input_type -> gitaly.PostReceivePackRequest + 1, // 7: gitaly.SmartHTTPService.InfoRefsUploadPack:output_type -> gitaly.InfoRefsResponse + 1, // 8: gitaly.SmartHTTPService.InfoRefsReceivePack:output_type -> gitaly.InfoRefsResponse + 3, // 9: gitaly.SmartHTTPService.PostUploadPack:output_type -> gitaly.PostUploadPackResponse + 5, // 10: gitaly.SmartHTTPService.PostReceivePack:output_type -> gitaly.PostReceivePackResponse + 7, // [7:11] is the sub-list for method output_type + 3, // [3:7] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_smarthttp_proto_init() } @@ -716,30 +585,6 @@ func file_smarthttp_proto_init() { } } file_smarthttp_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostUploadPackWithSidechannelRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_smarthttp_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostUploadPackWithSidechannelResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_smarthttp_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostReceivePackRequest); i { case 0: return &v.state @@ -751,7 +596,7 @@ func file_smarthttp_proto_init() { return nil } } - file_smarthttp_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_smarthttp_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostReceivePackResponse); i { case 0: return &v.state @@ -770,7 +615,7 @@ func file_smarthttp_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_smarthttp_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 6, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/go/gitalypb/smarthttp_grpc.pb.go b/proto/go/gitalypb/smarthttp_grpc.pb.go index 523303520..da3528e32 100644 --- a/proto/go/gitalypb/smarthttp_grpc.pb.go +++ b/proto/go/gitalypb/smarthttp_grpc.pb.go @@ -28,8 +28,6 @@ type SmartHTTPServiceClient interface { InfoRefsReceivePack(ctx context.Context, in *InfoRefsRequest, opts ...grpc.CallOption) (SmartHTTPService_InfoRefsReceivePackClient, error) // Request and response body for POST /upload-pack PostUploadPack(ctx context.Context, opts ...grpc.CallOption) (SmartHTTPService_PostUploadPackClient, error) - // Request and response body for POST /upload-pack using sidechannel protocol - PostUploadPackWithSidechannel(ctx context.Context, in *PostUploadPackWithSidechannelRequest, opts ...grpc.CallOption) (*PostUploadPackWithSidechannelResponse, error) // Request and response body for POST /receive-pack PostReceivePack(ctx context.Context, opts ...grpc.CallOption) (SmartHTTPService_PostReceivePackClient, error) } @@ -137,15 +135,6 @@ func (x *smartHTTPServicePostUploadPackClient) Recv() (*PostUploadPackResponse, return m, nil } -func (c *smartHTTPServiceClient) PostUploadPackWithSidechannel(ctx context.Context, in *PostUploadPackWithSidechannelRequest, opts ...grpc.CallOption) (*PostUploadPackWithSidechannelResponse, error) { - out := new(PostUploadPackWithSidechannelResponse) - err := c.cc.Invoke(ctx, "/gitaly.SmartHTTPService/PostUploadPackWithSidechannel", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *smartHTTPServiceClient) PostReceivePack(ctx context.Context, opts ...grpc.CallOption) (SmartHTTPService_PostReceivePackClient, error) { stream, err := c.cc.NewStream(ctx, &SmartHTTPService_ServiceDesc.Streams[3], "/gitaly.SmartHTTPService/PostReceivePack", opts...) if err != nil { @@ -191,8 +180,6 @@ type SmartHTTPServiceServer interface { InfoRefsReceivePack(*InfoRefsRequest, SmartHTTPService_InfoRefsReceivePackServer) error // Request and response body for POST /upload-pack PostUploadPack(SmartHTTPService_PostUploadPackServer) error - // Request and response body for POST /upload-pack using sidechannel protocol - PostUploadPackWithSidechannel(context.Context, *PostUploadPackWithSidechannelRequest) (*PostUploadPackWithSidechannelResponse, error) // Request and response body for POST /receive-pack PostReceivePack(SmartHTTPService_PostReceivePackServer) error mustEmbedUnimplementedSmartHTTPServiceServer() @@ -211,9 +198,6 @@ func (UnimplementedSmartHTTPServiceServer) InfoRefsReceivePack(*InfoRefsRequest, func (UnimplementedSmartHTTPServiceServer) PostUploadPack(SmartHTTPService_PostUploadPackServer) error { return status.Errorf(codes.Unimplemented, "method PostUploadPack not implemented") } -func (UnimplementedSmartHTTPServiceServer) PostUploadPackWithSidechannel(context.Context, *PostUploadPackWithSidechannelRequest) (*PostUploadPackWithSidechannelResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method PostUploadPackWithSidechannel not implemented") -} func (UnimplementedSmartHTTPServiceServer) PostReceivePack(SmartHTTPService_PostReceivePackServer) error { return status.Errorf(codes.Unimplemented, "method PostReceivePack not implemented") } @@ -298,24 +282,6 @@ func (x *smartHTTPServicePostUploadPackServer) Recv() (*PostUploadPackRequest, e return m, nil } -func _SmartHTTPService_PostUploadPackWithSidechannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PostUploadPackWithSidechannelRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(SmartHTTPServiceServer).PostUploadPackWithSidechannel(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/gitaly.SmartHTTPService/PostUploadPackWithSidechannel", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(SmartHTTPServiceServer).PostUploadPackWithSidechannel(ctx, req.(*PostUploadPackWithSidechannelRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _SmartHTTPService_PostReceivePack_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(SmartHTTPServiceServer).PostReceivePack(&smartHTTPServicePostReceivePackServer{stream}) } @@ -348,12 +314,7 @@ func (x *smartHTTPServicePostReceivePackServer) Recv() (*PostReceivePackRequest, var SmartHTTPService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "gitaly.SmartHTTPService", HandlerType: (*SmartHTTPServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "PostUploadPackWithSidechannel", - Handler: _SmartHTTPService_PostUploadPackWithSidechannel_Handler, - }, - }, + Methods: []grpc.MethodDesc{}, Streams: []grpc.StreamDesc{ { StreamName: "InfoRefsUploadPack", diff --git a/proto/go/internal/linter/lint.go b/proto/go/internal/linter/lint.go index 6d8ed34b6..ea84fd34e 100644 --- a/proto/go/internal/linter/lint.go +++ b/proto/go/internal/linter/lint.go @@ -52,8 +52,8 @@ func ensureMethodOpType(fileDesc *descriptorpb.FileDescriptorProto, m *descripto } func validateMethod(file *descriptorpb.FileDescriptorProto, service *descriptorpb.ServiceDescriptorProto, method *descriptorpb.MethodDescriptorProto, req *pluginpb.CodeGeneratorRequest) error { - if intercepted, err := protoutil.IsInterceptedMethod(service, method); err != nil { - return fmt.Errorf("is intercepted method: %w", err) + if intercepted, err := protoutil.IsInterceptedService(service); err != nil { + return fmt.Errorf("is intercepted service: %w", err) } else if intercepted { if _, err := protoutil.GetOpExtension(method); err != nil { if errors.Is(err, protoregistry.NotFound) { diff --git a/proto/go/internal/linter/lint_test.go b/proto/go/internal/linter/lint_test.go index bbf868d20..b6631cd0d 100644 --- a/proto/go/internal/linter/lint_test.go +++ b/proto/go/internal/linter/lint_test.go @@ -38,7 +38,6 @@ func TestLintFile(t *testing.T) { formatError("go/internal/linter/testdata/invalid.proto", "InvalidService", "InvalidMethod11", errors.New("unexpected count of storage field 1, expected 0, found storage label at: [RequestWithNestedStorageAndRepo.inner_message.storage_name]")), formatError("go/internal/linter/testdata/invalid.proto", "InvalidService", "InvalidMethod13", errors.New("unexpected count of storage field 0, expected 1, found storage label at: []")), formatError("go/internal/linter/testdata/invalid.proto", "InvalidService", "InvalidMethod14", errors.New("unexpected count of storage field 2, expected 1, found storage label at: [RequestWithMultipleNestedStorage.inner_message.storage_name RequestWithMultipleNestedStorage.storage_name]")), - formatError("go/internal/linter/testdata/invalid.proto", "InvalidService", "InvalidMethod15", errors.New("operation type defined on an intercepted method")), }, }, } { diff --git a/proto/go/internal/linter/testdata/invalid.pb.go b/proto/go/internal/linter/testdata/invalid.pb.go index cc379716f..97f9aa49d 100644 --- a/proto/go/internal/linter/testdata/invalid.pb.go +++ b/proto/go/internal/linter/testdata/invalid.pb.go @@ -828,7 +828,7 @@ var file_go_internal_linter_testdata_invalid_proto_rawDesc = []byte{ 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x1a, 0x04, 0xf0, 0x97, 0x28, 0x01, - 0x32, 0xd9, 0x09, 0x0a, 0x0e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x32, 0xfe, 0x08, 0x0a, 0x0e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x30, 0x12, 0x1a, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, @@ -900,17 +900,11 @@ var file_go_internal_linter_testdata_invalid_proto_rawDesc = []byte{ 0x74, 0x65, 0x64, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x1a, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xfa, 0x97, 0x28, 0x04, 0x08, 0x01, 0x10, - 0x02, 0x12, 0x59, 0x0a, 0x0f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x31, 0x35, 0x12, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x41, 0x6e, - 0x64, 0x52, 0x65, 0x70, 0x6f, 0x1a, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x6e, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x08, 0x80, 0x98, 0x28, 0x01, 0xfa, 0x97, 0x28, 0x00, 0x42, 0x44, 0x5a, 0x42, - 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, 0x34, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2f, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, - 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x02, 0x42, 0x44, 0x5a, 0x42, 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, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2f, 0x74, + 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -970,24 +964,22 @@ var file_go_internal_linter_testdata_invalid_proto_depIdxs = []int32{ 7, // 22: test.InvalidService.InvalidMethod11:input_type -> test.RequestWithNestedStorageAndRepo 2, // 23: test.InvalidService.InvalidMethod13:input_type -> test.InvalidTargetType 8, // 24: test.InvalidService.InvalidMethod14:input_type -> test.RequestWithMultipleNestedStorage - 6, // 25: test.InvalidService.InvalidMethod15:input_type -> test.RequestWithStorageAndRepo - 3, // 26: test.InterceptedWithOperationType.InvalidMethod:output_type -> test.InvalidMethodResponse - 3, // 27: test.InvalidService.InvalidMethod0:output_type -> test.InvalidMethodResponse - 3, // 28: test.InvalidService.InvalidMethod1:output_type -> test.InvalidMethodResponse - 3, // 29: test.InvalidService.InvalidMethod2:output_type -> test.InvalidMethodResponse - 3, // 30: test.InvalidService.InvalidMethod4:output_type -> test.InvalidMethodResponse - 3, // 31: test.InvalidService.InvalidMethod5:output_type -> test.InvalidMethodResponse - 3, // 32: test.InvalidService.InvalidMethod6:output_type -> test.InvalidMethodResponse - 3, // 33: test.InvalidService.InvalidMethod7:output_type -> test.InvalidMethodResponse - 3, // 34: test.InvalidService.InvalidMethod8:output_type -> test.InvalidMethodResponse - 3, // 35: test.InvalidService.InvalidMethod9:output_type -> test.InvalidMethodResponse - 3, // 36: test.InvalidService.InvalidMethod10:output_type -> test.InvalidMethodResponse - 3, // 37: test.InvalidService.InvalidMethod11:output_type -> test.InvalidMethodResponse - 3, // 38: test.InvalidService.InvalidMethod13:output_type -> test.InvalidMethodResponse - 3, // 39: test.InvalidService.InvalidMethod14:output_type -> test.InvalidMethodResponse - 3, // 40: test.InvalidService.InvalidMethod15:output_type -> test.InvalidMethodResponse - 26, // [26:41] is the sub-list for method output_type - 11, // [11:26] is the sub-list for method input_type + 3, // 25: test.InterceptedWithOperationType.InvalidMethod:output_type -> test.InvalidMethodResponse + 3, // 26: test.InvalidService.InvalidMethod0:output_type -> test.InvalidMethodResponse + 3, // 27: test.InvalidService.InvalidMethod1:output_type -> test.InvalidMethodResponse + 3, // 28: test.InvalidService.InvalidMethod2:output_type -> test.InvalidMethodResponse + 3, // 29: test.InvalidService.InvalidMethod4:output_type -> test.InvalidMethodResponse + 3, // 30: test.InvalidService.InvalidMethod5:output_type -> test.InvalidMethodResponse + 3, // 31: test.InvalidService.InvalidMethod6:output_type -> test.InvalidMethodResponse + 3, // 32: test.InvalidService.InvalidMethod7:output_type -> test.InvalidMethodResponse + 3, // 33: test.InvalidService.InvalidMethod8:output_type -> test.InvalidMethodResponse + 3, // 34: test.InvalidService.InvalidMethod9:output_type -> test.InvalidMethodResponse + 3, // 35: test.InvalidService.InvalidMethod10:output_type -> test.InvalidMethodResponse + 3, // 36: test.InvalidService.InvalidMethod11:output_type -> test.InvalidMethodResponse + 3, // 37: test.InvalidService.InvalidMethod13:output_type -> test.InvalidMethodResponse + 3, // 38: test.InvalidService.InvalidMethod14:output_type -> test.InvalidMethodResponse + 25, // [25:39] is the sub-list for method output_type + 11, // [11:25] is the sub-list for method input_type 11, // [11:11] is the sub-list for extension type_name 11, // [11:11] is the sub-list for extension extendee 0, // [0:11] is the sub-list for field type_name diff --git a/proto/go/internal/linter/testdata/invalid.proto b/proto/go/internal/linter/testdata/invalid.proto index a8c3ce54a..24490401c 100644 --- a/proto/go/internal/linter/testdata/invalid.proto +++ b/proto/go/internal/linter/testdata/invalid.proto @@ -156,10 +156,4 @@ service InvalidService { scope_level: STORAGE }; } - - // Intercepted methods must not have operation type annotations. - rpc InvalidMethod15(RequestWithStorageAndRepo) returns (InvalidMethodResponse) { - option (gitaly.intercepted_method) = true; - option (gitaly.op_type) = {}; - }; } diff --git a/proto/go/internal/linter/testdata/invalid_grpc.pb.go b/proto/go/internal/linter/testdata/invalid_grpc.pb.go index 2f109e568..5955e41a6 100644 --- a/proto/go/internal/linter/testdata/invalid_grpc.pb.go +++ b/proto/go/internal/linter/testdata/invalid_grpc.pb.go @@ -133,8 +133,6 @@ type InvalidServiceClient interface { InvalidMethod13(ctx context.Context, in *InvalidTargetType, opts ...grpc.CallOption) (*InvalidMethodResponse, error) // should fail if multiple storage is specified for storage scoped RPC InvalidMethod14(ctx context.Context, in *RequestWithMultipleNestedStorage, opts ...grpc.CallOption) (*InvalidMethodResponse, error) - // Intercepted methods must not have operation type annotations. - InvalidMethod15(ctx context.Context, in *RequestWithStorageAndRepo, opts ...grpc.CallOption) (*InvalidMethodResponse, error) } type invalidServiceClient struct { @@ -262,15 +260,6 @@ func (c *invalidServiceClient) InvalidMethod14(ctx context.Context, in *RequestW return out, nil } -func (c *invalidServiceClient) InvalidMethod15(ctx context.Context, in *RequestWithStorageAndRepo, opts ...grpc.CallOption) (*InvalidMethodResponse, error) { - out := new(InvalidMethodResponse) - err := c.cc.Invoke(ctx, "/test.InvalidService/InvalidMethod15", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // InvalidServiceServer is the server API for InvalidService service. // All implementations must embed UnimplementedInvalidServiceServer // for forward compatibility @@ -301,8 +290,6 @@ type InvalidServiceServer interface { InvalidMethod13(context.Context, *InvalidTargetType) (*InvalidMethodResponse, error) // should fail if multiple storage is specified for storage scoped RPC InvalidMethod14(context.Context, *RequestWithMultipleNestedStorage) (*InvalidMethodResponse, error) - // Intercepted methods must not have operation type annotations. - InvalidMethod15(context.Context, *RequestWithStorageAndRepo) (*InvalidMethodResponse, error) mustEmbedUnimplementedInvalidServiceServer() } @@ -349,9 +336,6 @@ func (UnimplementedInvalidServiceServer) InvalidMethod13(context.Context, *Inval func (UnimplementedInvalidServiceServer) InvalidMethod14(context.Context, *RequestWithMultipleNestedStorage) (*InvalidMethodResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method InvalidMethod14 not implemented") } -func (UnimplementedInvalidServiceServer) InvalidMethod15(context.Context, *RequestWithStorageAndRepo) (*InvalidMethodResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method InvalidMethod15 not implemented") -} func (UnimplementedInvalidServiceServer) mustEmbedUnimplementedInvalidServiceServer() {} // UnsafeInvalidServiceServer may be embedded to opt out of forward compatibility for this service. @@ -599,24 +583,6 @@ func _InvalidService_InvalidMethod14_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } -func _InvalidService_InvalidMethod15_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestWithStorageAndRepo) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(InvalidServiceServer).InvalidMethod15(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/test.InvalidService/InvalidMethod15", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(InvalidServiceServer).InvalidMethod15(ctx, req.(*RequestWithStorageAndRepo)) - } - return interceptor(ctx, in, info, handler) -} - // InvalidService_ServiceDesc is the grpc.ServiceDesc for InvalidService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -676,10 +642,6 @@ var InvalidService_ServiceDesc = grpc.ServiceDesc{ MethodName: "InvalidMethod14", Handler: _InvalidService_InvalidMethod14_Handler, }, - { - MethodName: "InvalidMethod15", - Handler: _InvalidService_InvalidMethod15_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "go/internal/linter/testdata/invalid.proto", diff --git a/proto/go/internal/linter/testdata/valid.pb.go b/proto/go/internal/linter/testdata/valid.pb.go index b136201be..70cfd8344 100644 --- a/proto/go/internal/linter/testdata/valid.pb.go +++ b/proto/go/internal/linter/testdata/valid.pb.go @@ -581,7 +581,7 @@ var file_go_internal_linter_testdata_valid_proto_rawDesc = []byte{ 0x12, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x04, 0xf0, 0x97, 0x28, 0x01, 0x32, - 0x88, 0x05, 0x0a, 0x0c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0xc2, 0x04, 0x0a, 0x0c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x52, @@ -617,16 +617,12 @@ var file_go_internal_linter_testdata_valid_proto_rawDesc = []byte{ 0x64, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xfa, 0x97, 0x28, 0x04, - 0x08, 0x01, 0x10, 0x02, 0x12, 0x44, 0x0a, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x31, 0x30, 0x12, 0x19, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x80, 0x98, 0x28, 0x01, 0x42, 0x44, 0x5a, 0x42, 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, 0x34, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2f, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x08, 0x01, 0x10, 0x02, 0x42, 0x44, 0x5a, 0x42, 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, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, + 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6c, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -674,19 +670,17 @@ var file_go_internal_linter_testdata_valid_proto_depIdxs = []int32{ 7, // 13: test.ValidService.TestMethod7:input_type -> test.ValidInnerNestedRequest 2, // 14: test.ValidService.TestMethod8:input_type -> test.ValidStorageRequest 5, // 15: test.ValidService.TestMethod9:input_type -> test.ValidStorageNestedRequest - 2, // 16: test.ValidService.TestMethod10:input_type -> test.ValidStorageRequest - 3, // 17: test.InterceptedService.TestMethod:output_type -> test.ValidResponse - 3, // 18: test.ValidService.TestMethod:output_type -> test.ValidResponse - 3, // 19: test.ValidService.TestMethod2:output_type -> test.ValidResponse - 3, // 20: test.ValidService.TestMethod3:output_type -> test.ValidResponse - 3, // 21: test.ValidService.TestMethod5:output_type -> test.ValidResponse - 3, // 22: test.ValidService.TestMethod6:output_type -> test.ValidResponse - 3, // 23: test.ValidService.TestMethod7:output_type -> test.ValidResponse - 3, // 24: test.ValidService.TestMethod8:output_type -> test.ValidResponse - 3, // 25: test.ValidService.TestMethod9:output_type -> test.ValidResponse - 3, // 26: test.ValidService.TestMethod10:output_type -> test.ValidResponse - 17, // [17:27] is the sub-list for method output_type - 7, // [7:17] is the sub-list for method input_type + 3, // 16: test.InterceptedService.TestMethod:output_type -> test.ValidResponse + 3, // 17: test.ValidService.TestMethod:output_type -> test.ValidResponse + 3, // 18: test.ValidService.TestMethod2:output_type -> test.ValidResponse + 3, // 19: test.ValidService.TestMethod3:output_type -> test.ValidResponse + 3, // 20: test.ValidService.TestMethod5:output_type -> test.ValidResponse + 3, // 21: test.ValidService.TestMethod6:output_type -> test.ValidResponse + 3, // 22: test.ValidService.TestMethod7:output_type -> test.ValidResponse + 3, // 23: test.ValidService.TestMethod8:output_type -> test.ValidResponse + 3, // 24: test.ValidService.TestMethod9:output_type -> test.ValidResponse + 16, // [16:25] is the sub-list for method output_type + 7, // [7:16] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name 7, // [7:7] is the sub-list for extension extendee 0, // [0:7] is the sub-list for field type_name diff --git a/proto/go/internal/linter/testdata/valid.proto b/proto/go/internal/linter/testdata/valid.proto index 0e3614792..eb77fdab4 100644 --- a/proto/go/internal/linter/testdata/valid.proto +++ b/proto/go/internal/linter/testdata/valid.proto @@ -107,9 +107,4 @@ service ValidService { scope_level: STORAGE }; } - - // Intercepted methods do not need operation type annotations. - rpc TestMethod10(ValidStorageRequest) returns (ValidResponse) { - option (gitaly.intercepted_method) = true; - } } diff --git a/proto/go/internal/linter/testdata/valid_grpc.pb.go b/proto/go/internal/linter/testdata/valid_grpc.pb.go index d545af891..9814297f4 100644 --- a/proto/go/internal/linter/testdata/valid_grpc.pb.go +++ b/proto/go/internal/linter/testdata/valid_grpc.pb.go @@ -112,8 +112,6 @@ type ValidServiceClient interface { TestMethod7(ctx context.Context, in *ValidInnerNestedRequest, opts ...grpc.CallOption) (*ValidResponse, error) TestMethod8(ctx context.Context, in *ValidStorageRequest, opts ...grpc.CallOption) (*ValidResponse, error) TestMethod9(ctx context.Context, in *ValidStorageNestedRequest, opts ...grpc.CallOption) (*ValidResponse, error) - // Intercepted methods do not need operation type annotations. - TestMethod10(ctx context.Context, in *ValidStorageRequest, opts ...grpc.CallOption) (*ValidResponse, error) } type validServiceClient struct { @@ -196,15 +194,6 @@ func (c *validServiceClient) TestMethod9(ctx context.Context, in *ValidStorageNe return out, nil } -func (c *validServiceClient) TestMethod10(ctx context.Context, in *ValidStorageRequest, opts ...grpc.CallOption) (*ValidResponse, error) { - out := new(ValidResponse) - err := c.cc.Invoke(ctx, "/test.ValidService/TestMethod10", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // ValidServiceServer is the server API for ValidService service. // All implementations must embed UnimplementedValidServiceServer // for forward compatibility @@ -217,8 +206,6 @@ type ValidServiceServer interface { TestMethod7(context.Context, *ValidInnerNestedRequest) (*ValidResponse, error) TestMethod8(context.Context, *ValidStorageRequest) (*ValidResponse, error) TestMethod9(context.Context, *ValidStorageNestedRequest) (*ValidResponse, error) - // Intercepted methods do not need operation type annotations. - TestMethod10(context.Context, *ValidStorageRequest) (*ValidResponse, error) mustEmbedUnimplementedValidServiceServer() } @@ -250,9 +237,6 @@ func (UnimplementedValidServiceServer) TestMethod8(context.Context, *ValidStorag func (UnimplementedValidServiceServer) TestMethod9(context.Context, *ValidStorageNestedRequest) (*ValidResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method TestMethod9 not implemented") } -func (UnimplementedValidServiceServer) TestMethod10(context.Context, *ValidStorageRequest) (*ValidResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TestMethod10 not implemented") -} func (UnimplementedValidServiceServer) mustEmbedUnimplementedValidServiceServer() {} // UnsafeValidServiceServer may be embedded to opt out of forward compatibility for this service. @@ -410,24 +394,6 @@ func _ValidService_TestMethod9_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } -func _ValidService_TestMethod10_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ValidStorageRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ValidServiceServer).TestMethod10(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/test.ValidService/TestMethod10", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ValidServiceServer).TestMethod10(ctx, req.(*ValidStorageRequest)) - } - return interceptor(ctx, in, info, handler) -} - // ValidService_ServiceDesc is the grpc.ServiceDesc for ValidService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -467,10 +433,6 @@ var ValidService_ServiceDesc = grpc.ServiceDesc{ MethodName: "TestMethod9", Handler: _ValidService_TestMethod9_Handler, }, - { - MethodName: "TestMethod10", - Handler: _ValidService_TestMethod10_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "go/internal/linter/testdata/valid.proto", diff --git a/proto/lint.proto b/proto/lint.proto index 572cc6c7f..ff7c21728 100644 --- a/proto/lint.proto +++ b/proto/lint.proto @@ -40,9 +40,6 @@ extend google.protobuf.ServiceOptions { extend google.protobuf.MethodOptions { // Random high number.. OperationMsg op_type = 82303; - // intercepted_method indicates whether the proxy intercepts and handles the method call - // instead of proxying. Intercepted methods do not require operation type annotations. - bool intercepted_method = 82304; } extend google.protobuf.FieldOptions { diff --git a/proto/repository-service.proto b/proto/repository-service.proto index 61416421f..f285cffa1 100644 --- a/proto/repository-service.proto +++ b/proto/repository-service.proto @@ -113,23 +113,13 @@ service RepositoryService { }; } - // CreateBundleFromRefList creates a bundle from a stream of ref patterns. - // When the bundle would be empty the FailedPrecondition error code is returned. + // CreateBundleFromRefList creates a bundle from a stream of ref patterns rpc CreateBundleFromRefList(stream CreateBundleFromRefListRequest) returns (stream CreateBundleFromRefListResponse) { option (op_type) = { op: ACCESSOR }; } - // FetchBundle fetches references from a bundle into the local repository. - // Refs will be mirrored to the target repository with the refspec - // "+refs/*:refs/*" and refs that do not exist in the bundle will be removed. - rpc FetchBundle(stream FetchBundleRequest) returns (FetchBundleResponse) { - option (op_type) = { - op: MUTATOR - }; - } - rpc CreateRepositoryFromBundle(stream CreateRepositoryFromBundleRequest) returns (CreateRepositoryFromBundleResponse) { option (op_type) = { op: MUTATOR @@ -325,16 +315,6 @@ message ApplyGitattributesRequest { message ApplyGitattributesResponse {} -message FetchBundleRequest { - // Repository into which the reference shall be fetched. - Repository repository = 1 [(target_repository)=true]; - - // Data is the bundle file stream. - bytes data = 2; -} - -message FetchBundleResponse {} - message FetchRemoteRequest { Repository repository = 1 [(target_repository)=true]; // force determines if references should be force-updated in case they have diff --git a/proto/smarthttp.proto b/proto/smarthttp.proto index f9e3977d6..26d057685 100644 --- a/proto/smarthttp.proto +++ b/proto/smarthttp.proto @@ -33,13 +33,6 @@ service SmartHTTPService { }; } - // Request and response body for POST /upload-pack using sidechannel protocol - rpc PostUploadPackWithSidechannel(PostUploadPackWithSidechannelRequest) returns (PostUploadPackWithSidechannelResponse) { - option (op_type) = { - op: ACCESSOR - }; - } - // Request and response body for POST /receive-pack rpc PostReceivePack(stream PostReceivePackRequest) returns (stream PostReceivePackResponse) { option (op_type) = { @@ -78,17 +71,6 @@ message PostUploadPackResponse { bytes data = 1; } -message PostUploadPackWithSidechannelRequest { - // repository should only be present in the first message of the stream - Repository repository = 1 [(target_repository)=true]; - // Parameters to use with git -c (key=value pairs) - repeated string git_config_options = 2; - // Git protocol version - string git_protocol = 3; -} - -message PostUploadPackWithSidechannelResponse { } - message PostReceivePackRequest { // repository should only be present in the first message of the stream Repository repository = 1 [(target_repository)=true]; diff --git a/ruby/Gemfile b/ruby/Gemfile index b27c68cad..22200335e 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -3,7 +3,7 @@ source 'https://rubygems.org' gem 'rugged', '~> 1.1' gem 'github-linguist', '~> 7.12', require: 'linguist' gem 'gitlab-markup', '~> 1.7.1' -gem 'activesupport', '~> 6.1.4.1' +gem 'activesupport', '~> 6.1.3.2' gem 'rdoc', '~> 6.0' gem 'gitlab-gollum-lib', '~> 4.2.7.10.gitlab.1', require: false gem 'gitlab-gollum-rugged_adapter', '~> 0.4.4.4.gitlab.1', require: false diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock index e8f2327d4..a44271915 100644 --- a/ruby/Gemfile.lock +++ b/ruby/Gemfile.lock @@ -2,20 +2,20 @@ GEM remote: https://rubygems.org/ specs: abstract_type (0.0.7) - actionpack (6.1.4.1) - actionview (= 6.1.4.1) - activesupport (= 6.1.4.1) + actionpack (6.1.3.2) + actionview (= 6.1.3.2) + activesupport (= 6.1.3.2) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actionview (6.1.4.1) - activesupport (= 6.1.4.1) + actionview (6.1.3.2) + activesupport (= 6.1.3.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activesupport (6.1.4.1) + activesupport (6.1.3.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -94,7 +94,7 @@ GEM reverse_markdown (~> 1.0) rugged (>= 0.24, < 2.0) thor (>= 0.19, < 2.0) - loofah (2.12.0) + loofah (2.10.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) memoizable (0.4.2) @@ -104,12 +104,12 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2020.1104) mini_mime (1.0.2) - mini_portile2 (2.6.1) + mini_portile2 (2.5.1) minitest (5.14.4) msgpack (1.3.3) multipart-post (2.1.1) - nokogiri (1.12.5) - mini_portile2 (~> 2.6.1) + nokogiri (1.11.7) + mini_portile2 (~> 2.5.0) racc (~> 1.4) nokogumbo (1.5.0) nokogiri @@ -139,7 +139,7 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.4.2) + rails-html-sanitizer (1.3.0) loofah (~> 2.3) rainbow (3.0.0) rbtrace (0.4.14) @@ -216,7 +216,7 @@ PLATFORMS ruby DEPENDENCIES - activesupport (~> 6.1.4.1) + activesupport (~> 6.1.3.2) factory_bot faraday (~> 1.0) github-linguist (~> 7.12) diff --git a/ruby/proto/gitaly/repository-service_pb.rb b/ruby/proto/gitaly/repository-service_pb.rb index fe4e2b379..b5fc2aeb8 100644 --- a/ruby/proto/gitaly/repository-service_pb.rb +++ b/ruby/proto/gitaly/repository-service_pb.rb @@ -62,12 +62,6 @@ Google::Protobuf::DescriptorPool.generated_pool.build do end add_message "gitaly.ApplyGitattributesResponse" do end - add_message "gitaly.FetchBundleRequest" do - optional :repository, :message, 1, "gitaly.Repository" - optional :data, :bytes, 2 - end - add_message "gitaly.FetchBundleResponse" do - end add_message "gitaly.FetchRemoteRequest" do optional :repository, :message, 1, "gitaly.Repository" optional :force, :bool, 3 @@ -348,8 +342,6 @@ module Gitaly RepositorySizeResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.RepositorySizeResponse").msgclass ApplyGitattributesRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.ApplyGitattributesRequest").msgclass ApplyGitattributesResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.ApplyGitattributesResponse").msgclass - FetchBundleRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.FetchBundleRequest").msgclass - FetchBundleResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.FetchBundleResponse").msgclass FetchRemoteRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.FetchRemoteRequest").msgclass FetchRemoteResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.FetchRemoteResponse").msgclass CreateRepositoryRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.CreateRepositoryRequest").msgclass diff --git a/ruby/proto/gitaly/repository-service_services_pb.rb b/ruby/proto/gitaly/repository-service_services_pb.rb index 5f030bf8c..c93643efc 100644 --- a/ruby/proto/gitaly/repository-service_services_pb.rb +++ b/ruby/proto/gitaly/repository-service_services_pb.rb @@ -37,29 +37,24 @@ module Gitaly rpc :CreateFork, ::Gitaly::CreateForkRequest, ::Gitaly::CreateForkResponse rpc :CreateRepositoryFromURL, ::Gitaly::CreateRepositoryFromURLRequest, ::Gitaly::CreateRepositoryFromURLResponse # CreateBundle creates a bundle from all refs - rpc :CreateBundle, ::Gitaly::CreateBundleRequest, stream ::Gitaly::CreateBundleResponse) - # CreateBundleFromRefList creates a bundle from a stream of ref patterns. - # When the bundle would be empty the FailedPrecondition error code is returned. - rpc :CreateBundleFromRefList, stream ::Gitaly::CreateBundleFromRefListRequest), stream ::Gitaly::CreateBundleFromRefListResponse) - # FetchBundle fetches references from a bundle into the local repository. - # Refs will be mirrored to the target repository with the refspec - # "+refs/*:refs/*" and refs that do not exist in the bundle will be removed. - rpc :FetchBundle, stream ::Gitaly::FetchBundleRequest), ::Gitaly::FetchBundleResponse - rpc :CreateRepositoryFromBundle, stream ::Gitaly::CreateRepositoryFromBundleRequest), ::Gitaly::CreateRepositoryFromBundleResponse + rpc :CreateBundle, ::Gitaly::CreateBundleRequest, stream(::Gitaly::CreateBundleResponse) + # CreateBundleFromRefList creates a bundle from a stream of ref patterns + rpc :CreateBundleFromRefList, stream(::Gitaly::CreateBundleFromRefListRequest), stream(::Gitaly::CreateBundleFromRefListResponse) + rpc :CreateRepositoryFromBundle, stream(::Gitaly::CreateRepositoryFromBundleRequest), ::Gitaly::CreateRepositoryFromBundleResponse # GetConfig reads the target repository's gitconfig and streams its contents # back. Returns a NotFound error in case no gitconfig was found. - rpc :GetConfig, ::Gitaly::GetConfigRequest, stream ::Gitaly::GetConfigResponse) + rpc :GetConfig, ::Gitaly::GetConfigRequest, stream(Gitaly::GetConfigResponse) rpc :FindLicense, ::Gitaly::FindLicenseRequest, ::Gitaly::FindLicenseResponse - rpc :GetInfoAttributes, ::Gitaly::GetInfoAttributesRequest, stream ::Gitaly::GetInfoAttributesResponse) + rpc :GetInfoAttributes, ::Gitaly::GetInfoAttributesRequest, stream(Gitaly::GetInfoAttributesResponse) rpc :CalculateChecksum, ::Gitaly::CalculateChecksumRequest, ::Gitaly::CalculateChecksumResponse rpc :Cleanup, ::Gitaly::CleanupRequest, ::Gitaly::CleanupResponse - rpc :GetSnapshot, ::Gitaly::GetSnapshotRequest, stream ::Gitaly::GetSnapshotResponse) + rpc :GetSnapshot, ::Gitaly::GetSnapshotRequest, stream(Gitaly::GetSnapshotResponse) rpc :CreateRepositoryFromSnapshot, ::Gitaly::CreateRepositoryFromSnapshotRequest, ::Gitaly::CreateRepositoryFromSnapshotResponse - rpc :GetRawChanges, ::Gitaly::GetRawChangesRequest, stream ::Gitaly::GetRawChangesResponse) - rpc :SearchFilesByContent, ::Gitaly::SearchFilesByContentRequest, stream ::Gitaly::SearchFilesByContentResponse) - rpc :SearchFilesByName, ::Gitaly::SearchFilesByNameRequest, stream ::Gitaly::SearchFilesByNameResponse) - rpc :RestoreCustomHooks, stream ::Gitaly::RestoreCustomHooksRequest), ::Gitaly::RestoreCustomHooksResponse - rpc :BackupCustomHooks, ::Gitaly::BackupCustomHooksRequest, stream ::Gitaly::BackupCustomHooksResponse) + rpc :GetRawChanges, ::Gitaly::GetRawChangesRequest, stream(Gitaly::GetRawChangesResponse) + rpc :SearchFilesByContent, ::Gitaly::SearchFilesByContentRequest, stream(Gitaly::SearchFilesByContentResponse) + rpc :SearchFilesByName, ::Gitaly::SearchFilesByNameRequest, stream(Gitaly::SearchFilesByNameResponse) + rpc :RestoreCustomHooks, stream(Gitaly::RestoreCustomHooksRequest), ::Gitaly::RestoreCustomHooksResponse + rpc :BackupCustomHooks, ::Gitaly::BackupCustomHooksRequest, stream(Gitaly::BackupCustomHooksResponse) rpc :GetObjectDirectorySize, ::Gitaly::GetObjectDirectorySizeRequest, ::Gitaly::GetObjectDirectorySizeResponse rpc :CloneFromPool, ::Gitaly::CloneFromPoolRequest, ::Gitaly::CloneFromPoolResponse rpc :CloneFromPoolInternal, ::Gitaly::CloneFromPoolInternalRequest, ::Gitaly::CloneFromPoolInternalResponse diff --git a/ruby/proto/gitaly/smarthttp_pb.rb b/ruby/proto/gitaly/smarthttp_pb.rb index 3bec5ac26..6d4877f32 100644 --- a/ruby/proto/gitaly/smarthttp_pb.rb +++ b/ruby/proto/gitaly/smarthttp_pb.rb @@ -24,13 +24,6 @@ Google::Protobuf::DescriptorPool.generated_pool.build do add_message "gitaly.PostUploadPackResponse" do optional :data, :bytes, 1 end - add_message "gitaly.PostUploadPackWithSidechannelRequest" do - optional :repository, :message, 1, "gitaly.Repository" - repeated :git_config_options, :string, 2 - optional :git_protocol, :string, 3 - end - add_message "gitaly.PostUploadPackWithSidechannelResponse" do - end add_message "gitaly.PostReceivePackRequest" do optional :repository, :message, 1, "gitaly.Repository" optional :data, :bytes, 2 @@ -51,8 +44,6 @@ module Gitaly InfoRefsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.InfoRefsResponse").msgclass PostUploadPackRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.PostUploadPackRequest").msgclass PostUploadPackResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.PostUploadPackResponse").msgclass - PostUploadPackWithSidechannelRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.PostUploadPackWithSidechannelRequest").msgclass - PostUploadPackWithSidechannelResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.PostUploadPackWithSidechannelResponse").msgclass PostReceivePackRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.PostReceivePackRequest").msgclass PostReceivePackResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("gitaly.PostReceivePackResponse").msgclass end diff --git a/ruby/proto/gitaly/smarthttp_services_pb.rb b/ruby/proto/gitaly/smarthttp_services_pb.rb index 12f5aaf11..b3451bdf2 100644 --- a/ruby/proto/gitaly/smarthttp_services_pb.rb +++ b/ruby/proto/gitaly/smarthttp_services_pb.rb @@ -23,9 +23,7 @@ module Gitaly # references to the user. rpc :InfoRefsReceivePack, ::Gitaly::InfoRefsRequest, stream(::Gitaly::InfoRefsResponse) # Request and response body for POST /upload-pack - rpc :PostUploadPack, stream(::Gitaly::PostUploadPackRequest), stream(Gitaly::PostUploadPackResponse) - # Request and response body for POST /upload-pack using sidechannel protocol - rpc :PostUploadPackWithSidechannel, ::Gitaly::PostUploadPackWithSidechannelRequest, ::Gitaly::PostUploadPackWithSidechannelResponse + rpc :PostUploadPack, stream(::Gitaly::PostUploadPackRequest), stream(::Gitaly::PostUploadPackResponse) # Request and response body for POST /receive-pack rpc :PostReceivePack, stream(::Gitaly::PostReceivePackRequest), stream(::Gitaly::PostReceivePackResponse) end |