diff options
author | Quang-Minh Nguyen <qmnguyen@gitlab.com> | 2023-06-04 18:00:15 +0300 |
---|---|---|
committer | Quang-Minh Nguyen <qmnguyen@gitlab.com> | 2023-06-06 11:27:09 +0300 |
commit | 8f136efa86e0ebd489bc245fc370d6f9784083c8 (patch) | |
tree | 05915e07ecdf6fdb4fc068247b4598f58c94039f | |
parent | 2c3b53012ccc44bcef44d5cbda21b29d573e8d52 (diff) |
WIP: Expose another port for pack rpcsqmnguyen0711/expose-another-port-for-pack-rpcs
-rw-r--r-- | client/dial.go | 1 | ||||
-rw-r--r-- | internal/cli/gitaly/serve.go | 68 | ||||
-rw-r--r-- | internal/gitaly/config/config.go | 1 | ||||
-rw-r--r-- | internal/gitaly/server/server_factory.go | 41 | ||||
-rw-r--r-- | internal/gitaly/service/setup/register.go | 16 | ||||
-rw-r--r-- | internal/gitaly/service/smarthttp/upload_pack.go | 89 | ||||
-rw-r--r-- | internal/gitaly/service/smarthttp/upload_pack_test.go | 246 | ||||
-rw-r--r-- | internal/grpc/encoding/raw.go | 36 | ||||
-rw-r--r-- | internal/testhelper/testserver/gitaly.go | 38 | ||||
-rw-r--r-- | proto/go/gitalypb/smarthttp.pb.go | 345 | ||||
-rw-r--r-- | proto/go/gitalypb/smarthttp_grpc.pb.go | 70 | ||||
-rw-r--r-- | proto/smarthttp.proto | 22 |
12 files changed, 825 insertions, 148 deletions
diff --git a/client/dial.go b/client/dial.go index 4776109f7..f32523df8 100644 --- a/client/dial.go +++ b/client/dial.go @@ -9,6 +9,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/backoff" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/client" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/dnsresolver" + _ "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/encoding" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/sidechannel" "google.golang.org/grpc" healthpb "google.golang.org/grpc/health/grpc_health_v1" diff --git a/internal/cli/gitaly/serve.go b/internal/cli/gitaly/serve.go index aec987c81..9f0c96c92 100644 --- a/internal/cli/gitaly/serve.go +++ b/internal/cli/gitaly/serve.go @@ -3,6 +3,7 @@ package gitaly import ( "context" "fmt" + "net/http" "os" "runtime/debug" "time" @@ -307,6 +308,25 @@ func run(cfg config.Cfg) error { concurrencyTracker := hook.NewConcurrencyTracker() prometheus.MustRegister(concurrencyTracker) + createServiceDependencies := func() *service.Dependencies { + return &service.Dependencies{ + Cfg: cfg, + GitalyHookManager: hookManager, + TransactionManager: transactionManager, + StorageLocator: locator, + ClientPool: conns, + GitCmdFactory: gitCmdFactory, + CatfileCache: catfileCache, + DiskCache: diskCache, + PackObjectsCache: streamCache, + PackObjectsConcurrencyTracker: concurrencyTracker, + PackObjectsLimiter: packObjectsLimiter, + Git2goExecutor: git2goExecutor, + UpdaterWithHooks: updaterWithHooks, + HousekeepingManager: housekeepingManager, + } + } + for _, c := range []starter.Config{ {Name: starter.Unix, Addr: cfg.SocketPath, HandoverOnUpgrade: true}, {Name: starter.Unix, Addr: cfg.InternalSocketPath(), HandoverOnUpgrade: false}, @@ -330,25 +350,39 @@ func run(cfg config.Cfg) error { } } - setup.RegisterAll(srv, &service.Dependencies{ - Cfg: cfg, - GitalyHookManager: hookManager, - TransactionManager: transactionManager, - StorageLocator: locator, - ClientPool: conns, - GitCmdFactory: gitCmdFactory, - CatfileCache: catfileCache, - DiskCache: diskCache, - PackObjectsCache: streamCache, - PackObjectsConcurrencyTracker: concurrencyTracker, - PackObjectsLimiter: packObjectsLimiter, - Git2goExecutor: git2goExecutor, - UpdaterWithHooks: updaterWithHooks, - HousekeepingManager: housekeepingManager, - }) + setup.RegisterAll(srv, createServiceDependencies()) b.RegisterStarter(starter.New(c, srv)) } + if addr := cfg.PackServerListenAddr; addr != "" { + for _, c := range []starter.Config{ + // TODO: Handle TLS later + {Name: starter.TCP, Addr: cfg.PackServerListenAddr, HandoverOnUpgrade: true}, + // TODO: Add internal socket here + } { + if c.Addr == "" { + continue + } + + var srv *grpc.Server + var httpSrv *http.Server + if c.HandoverOnUpgrade { + srv, httpSrv, err = gitalyServerFactory.CreateHTTP2External(c.IsSecure()) + if err != nil { + return fmt.Errorf("create external gRPC server: %w", err) + } + } else { + srv, httpSrv, err = gitalyServerFactory.CreateHTTP2Internal() + if err != nil { + return fmt.Errorf("create internal gRPC server: %w", err) + } + } + + setup.RegisterPackDependencies(srv, createServiceDependencies()) + b.RegisterStarter(starter.New(c, httpSrv)) + } + } + if addr := cfg.PrometheusListenAddr; addr != "" { b.RegisterStarter(func(listen bootstrap.ListenFunc, _ chan<- error, _ *prometheus.CounterVec) error { l, err := listen("tcp", addr) @@ -406,5 +440,5 @@ func run(cfg config.Cfg) error { gracefulStopTicker := helper.NewTimerTicker(cfg.GracefulRestartTimeout.Duration()) defer gracefulStopTicker.Stop() - return b.Wait(gracefulStopTicker, gitalyServerFactory.GracefulStop) + return b.Wait(gracefulStopTicker, func() { gitalyServerFactory.GracefulStop() }) } diff --git a/internal/gitaly/config/config.go b/internal/gitaly/config/config.go index fdc1fcf0a..ee70bb64c 100644 --- a/internal/gitaly/config/config.go +++ b/internal/gitaly/config/config.go @@ -93,6 +93,7 @@ type Cfg struct { SocketPath string `toml:"socket_path,omitempty" json:"socket_path" split_words:"true"` ListenAddr string `toml:"listen_addr,omitempty" json:"listen_addr" split_words:"true"` TLSListenAddr string `toml:"tls_listen_addr,omitempty" json:"tls_listen_addr" split_words:"true"` + PackServerListenAddr string `toml:"pack_server_listen_addr,omitempty" json:"pack_server_listen_addr" split_words:"true"` PrometheusListenAddr string `toml:"prometheus_listen_addr,omitempty" json:"prometheus_listen_addr" split_words:"true"` BinDir string `toml:"bin_dir,omitempty" json:"bin_dir"` RuntimeDir string `toml:"runtime_dir,omitempty" json:"runtime_dir"` diff --git a/internal/gitaly/server/server_factory.go b/internal/gitaly/server/server_factory.go index 10afb3ce3..7e8b92e33 100644 --- a/internal/gitaly/server/server_factory.go +++ b/internal/gitaly/server/server_factory.go @@ -1,12 +1,17 @@ package server import ( + "net/http" "sync" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/gitaly/v16/internal/cache" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/backchannel" + _ "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/encoding" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/middleware/limithandler" "google.golang.org/grpc" ) @@ -97,3 +102,39 @@ func (s *GitalyServerFactory) CreateInternal(opts ...Option) (*grpc.Server, erro s.internalServers = append(s.internalServers, server) return server, nil } + +// CreateHTTP2Internal creates a new internal gRPC server using native Go's HTTP2 stack +func (s *GitalyServerFactory) CreateHTTP2Internal(opts ...Option) (*grpc.Server, *http.Server, error) { + server, err := s.New(false, opts...) + if err != nil { + return nil, nil, err + } + s.internalServers = append(s.internalServers, server) + return s.createInsecureHTTP2Server(server, err) +} + +// CreateHTTP2External creates a new external gRPC server using native Go's HTTP2 stack +func (s *GitalyServerFactory) CreateHTTP2External(secure bool, opts ...Option) (*grpc.Server, *http.Server, error) { + server, err := s.New(secure, opts...) + if err != nil { + return nil, nil, err + } + s.externalServers = append(s.externalServers, server) + // TODO: Handle secure HTTP2 server + return s.createInsecureHTTP2Server(server, err) +} + +func (s *GitalyServerFactory) createInsecureHTTP2Server(server *grpc.Server, err error) (*grpc.Server, *http.Server, error) { + httpSrv := &http.Server{} + http2Srv := &http2.Server{ + MaxReadFrameSize: 128 * 1024, + MaxUploadBufferPerStream: 16 * 1024 * 1024, + } + if err := http2.ConfigureServer(httpSrv, http2Srv); err != nil { + return nil, nil, err + } + httpSrv.Handler = h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server.ServeHTTP(w, r) + }), http2Srv) + return server, httpSrv, err +} diff --git a/internal/gitaly/service/setup/register.go b/internal/gitaly/service/setup/register.go index 0a0177cfe..8031ec81b 100644 --- a/internal/gitaly/service/setup/register.go +++ b/internal/gitaly/service/setup/register.go @@ -156,3 +156,19 @@ func RegisterAll(srv *grpc.Server, deps *service.Dependencies) { reflection.Register(srv) grpcprometheus.Register(srv) } + +func RegisterPackDependencies(srv *grpc.Server, deps *service.Dependencies) { + gitalypb.RegisterSmartHTTPServiceServer(srv, smarthttp.NewServer( + deps.GetLocator(), + deps.GetGitCmdFactory(), + deps.GetTxManager(), + deps.GetDiskCache(), + smarthttp.WithPackfileNegotiationMetrics(smarthttpPackfileNegotiationMetrics), + )) + gitalypb.RegisterSSHServiceServer(srv, ssh.NewServer( + deps.GetLocator(), + deps.GetGitCmdFactory(), + deps.GetTxManager(), + ssh.WithPackfileNegotiationMetrics(sshPackfileNegotiationMetrics), + )) +} diff --git a/internal/gitaly/service/smarthttp/upload_pack.go b/internal/gitaly/service/smarthttp/upload_pack.go index b28f35591..cd966ae34 100644 --- a/internal/gitaly/service/smarthttp/upload_pack.go +++ b/internal/gitaly/service/smarthttp/upload_pack.go @@ -6,6 +6,9 @@ import ( "fmt" "io" + "gitlab.com/gitlab-org/gitaly/v16/streamio" + "google.golang.org/protobuf/proto" + "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" "gitlab.com/gitlab-org/gitaly/v16/internal/command" "gitlab.com/gitlab-org/gitaly/v16/internal/git" @@ -16,6 +19,12 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" ) +type postUploadPackRequest interface { + GetRepository() *gitalypb.Repository + GetGitConfigOptions() []string + GetGitProtocol() string +} + func (s *server) PostUploadPackWithSidechannel(ctx context.Context, req *gitalypb.PostUploadPackWithSidechannelRequest) (*gitalypb.PostUploadPackWithSidechannelResponse, error) { repoPath, gitConfig, err := s.validateUploadPackRequest(ctx, req) if err != nil { @@ -28,10 +37,12 @@ func (s *server) PostUploadPackWithSidechannel(ctx context.Context, req *gitalyp } defer conn.Close() - if err := s.runUploadPack(ctx, req, repoPath, gitConfig, conn, conn); err != nil { + proxy := func(cmd *command.Command) (int64, error) { + return io.CopyBuffer(conn, cmd, make([]byte, 64*1024)) + } + if err := s.runUploadPack(ctx, req, repoPath, gitConfig, conn, proxy); err != nil { return nil, structerr.NewInternal("running upload-pack: %w", err) } - if err := conn.Close(); err != nil { return nil, structerr.NewInternal("close sidechannel connection: %w", err) } @@ -39,6 +50,73 @@ func (s *server) PostUploadPackWithSidechannel(ctx context.Context, req *gitalyp return &gitalypb.PostUploadPackWithSidechannelResponse{}, nil } +func (s *server) PostUploadPackV3(stream gitalypb.SmartHTTPService_PostUploadPackV3Server) error { + ctx := stream.Context() + + var req gitalypb.PostUploadPackV3Request + var firstRequest []byte + // First request contains Repository only + if err := stream.RecvMsg(&firstRequest); err != nil { + return err + } + if err := proto.Unmarshal(firstRequest, &req); err != nil { + return err + } + + repoPath, gitConfig, err := s.validateUploadPackRequest(ctx, &req) + if err != nil { + return structerr.NewInvalidArgument("%w", err) + } + + stdin := streamio.NewReader(func() ([]byte, error) { + var stdinBuffer []byte + err := stream.RecvMsg(&stdinBuffer) + if err != nil { + return nil, err + } + return stdinBuffer, err + }) + + var totalBytes int64 + var recentBytes int + const maxBufferSize = 1024 * 1024 + bufferSize := 64 * 1024 + copyBuffer := make([]byte, bufferSize) + proxy := func(cmd *command.Command) (int64, error) { + for { + read, err := cmd.Read(copyBuffer[recentBytes:]) + if err != nil { + if err == io.EOF { + if recentBytes > 0 { + return totalBytes, stream.SendMsg(copyBuffer[:recentBytes]) + } + return totalBytes, nil + } + return totalBytes, err + } + totalBytes += int64(read) + recentBytes += read + if recentBytes == bufferSize { + if err := stream.SendMsg(copyBuffer); err != nil { + return totalBytes, err + } + bufferSize *= 2 + if bufferSize > maxBufferSize { + bufferSize = maxBufferSize + } + copyBuffer = make([]byte, bufferSize) + recentBytes = 0 + } + } + } + + if err := s.runUploadPack(ctx, &req, repoPath, gitConfig, stdin, proxy); err != nil { + return structerr.NewInternal("running upload-pack: %w", err) + } + + return nil +} + type statsCollector struct { c io.Closer statsCh chan stats.PackfileNegotiation @@ -72,7 +150,7 @@ 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 *gitalypb.PostUploadPackWithSidechannelRequest) (string, []git.ConfigPair, error) { +func (s *server) validateUploadPackRequest(ctx context.Context, req postUploadPackRequest) (string, []git.ConfigPair, error) { repository := req.GetRepository() if err := service.ValidateRepository(repository); err != nil { return "", nil, err @@ -92,7 +170,7 @@ func (s *server) validateUploadPackRequest(ctx context.Context, req *gitalypb.Po return repoPath, config, nil } -func (s *server) runUploadPack(ctx context.Context, req *gitalypb.PostUploadPackWithSidechannelRequest, repoPath string, gitConfig []git.ConfigPair, stdin io.Reader, stdout io.Writer) error { +func (s *server) runUploadPack(ctx context.Context, req postUploadPackRequest, repoPath string, gitConfig []git.ConfigPair, stdin io.Reader, proxy func(*command.Command) (int64, error)) error { h := sha1.New() stdin = io.TeeReader(stdin, h) @@ -115,8 +193,7 @@ func (s *server) runUploadPack(ctx context.Context, req *gitalypb.PostUploadPack return structerr.NewUnavailable("spawning upload-pack: %w", err) } - // Use a custom buffer size to minimize the number of system calls. - respBytes, err := io.CopyBuffer(stdout, cmd, make([]byte, 64*1024)) + respBytes, err := proxy(cmd) if err != nil { return structerr.NewUnavailable("copying stdout from upload-pack: %w", err) } diff --git a/internal/gitaly/service/smarthttp/upload_pack_test.go b/internal/gitaly/service/smarthttp/upload_pack_test.go index c75df1496..2534bd786 100644 --- a/internal/gitaly/service/smarthttp/upload_pack_test.go +++ b/internal/gitaly/service/smarthttp/upload_pack_test.go @@ -11,6 +11,9 @@ import ( "sync" "testing" + "gitlab.com/gitlab-org/gitaly/v16/streamio" + "google.golang.org/protobuf/proto" + "github.com/prometheus/client_golang/prometheus" promtest "github.com/prometheus/client_golang/prometheus/testutil" "github.com/stretchr/testify/require" @@ -33,22 +36,23 @@ const ( ) type ( - requestMaker func(t *testing.T, ctx context.Context, serverSocketPath, token string, in *gitalypb.PostUploadPackWithSidechannelRequest, body io.Reader) (*bytes.Buffer, error) + requestMaker func(t *testing.T, ctx context.Context, serverSocketPath, token string, in postUploadPackRequest, body io.Reader) (*bytes.Buffer, error) ) func runTestWithAndWithoutConfigOptions( t *testing.T, - tf func(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option), + tf func(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt), makeRequest requestMaker, - opts ...testcfg.Option, + opts []testcfg.Option, + serverOpts []testserver.GitalyServerOpt, ) { ctx := testhelper.Context(t) - t.Run("no config options", func(t *testing.T) { tf(t, ctx, makeRequest) }) + t.Run("no config options", func(t *testing.T) { tf(t, ctx, makeRequest, []testcfg.Option{}, serverOpts) }) if len(opts) > 0 { t.Run("with config options", func(t *testing.T) { - tf(t, ctx, makeRequest, opts...) + tf(t, ctx, makeRequest, opts, serverOpts) }) } } @@ -56,15 +60,29 @@ func runTestWithAndWithoutConfigOptions( func TestServer_PostUploadWithChannel(t *testing.T) { t.Parallel() - runTestWithAndWithoutConfigOptions(t, testServerPostUpload, makePostUploadPackWithSidechannelRequest, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions( + t, testServerPostUpload, makePostUploadPackWithSidechannelRequest, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{}, + ) } -func testServerPostUpload(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func TestServer_PostUploadV3(t *testing.T) { + t.Parallel() + + runTestWithAndWithoutConfigOptions( + t, testServerPostUpload, makePostUploadPackV3, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{testserver.WithHTTP2()}, + ) +} + +func testServerPostUpload(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { cfg := testcfg.Build(t, opts...) testcfg.BuildGitalyHooks(t, cfg) negotiationMetrics := prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"feature"}) - cfg.SocketPath = runSmartHTTPServer(t, cfg, WithPackfileNegotiationMetrics(negotiationMetrics)) + cfg.SocketPath = startSmartHTTPServerWithOptions(t, cfg, []ServerOpt{WithPackfileNegotiationMetrics(negotiationMetrics)}, serverOpts).Address() repo, repoPath := gittest.CreateRepository(t, ctx, cfg) _, localRepoPath := gittest.CreateRepository(t, ctx, cfg) @@ -101,10 +119,24 @@ func testServerPostUpload(t *testing.T, ctx context.Context, makeRequest request func TestServer_PostUploadPackSidechannel_gitConfigOptions(t *testing.T) { t.Parallel() - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitConfigOptions, makePostUploadPackWithSidechannelRequest, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackGitConfigOptions, makePostUploadPackWithSidechannelRequest, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{}, + ) } -func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func TestServer_PostUploadPackV3_gitConfigOptions(t *testing.T) { + t.Parallel() + + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackGitConfigOptions, makePostUploadPackV3, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{testserver.WithHTTP2()}, + ) +} + +func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { testhelper.SkipQuarantinedTest( t, "https://gitlab.com/gitlab-org/gitaly/-/issues/5027", @@ -114,7 +146,7 @@ func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, cfg := testcfg.Build(t, opts...) testcfg.BuildGitalyHooks(t, cfg) - cfg.SocketPath = runSmartHTTPServer(t, cfg) + cfg.SocketPath = startSmartHTTPServerWithOptions(t, cfg, []ServerOpt{}, serverOpts).Address() repo, repoPath := gittest.CreateRepository(t, ctx, cfg) @@ -170,15 +202,29 @@ func testServerPostUploadPackGitConfigOptions(t *testing.T, ctx context.Context, func TestServer_PostUploadPackWithSidechannel_gitProtocol(t *testing.T) { t.Parallel() - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackGitProtocol, makePostUploadPackWithSidechannelRequest, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackGitProtocol, makePostUploadPackWithSidechannelRequest, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{}, + ) +} + +func TestServer_PostUploadPackV3_gitProtocol(t *testing.T) { + t.Parallel() + + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackGitProtocol, makePostUploadPackV3, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{testserver.WithHTTP2()}, + ) } -func testServerPostUploadPackGitProtocol(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func testServerPostUploadPackGitProtocol(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { cfg := testcfg.Build(t, opts...) protocolDetectingFactory := gittest.NewProtocolDetectingCommandFactory(t, ctx, cfg) - server := startSmartHTTPServerWithOptions(t, cfg, nil, []testserver.GitalyServerOpt{ + server := startSmartHTTPServerWithOptions(t, cfg, nil, append(serverOpts, testserver.WithGitCommandFactory(protocolDetectingFactory), - }) + )) cfg.SocketPath = server.Address() repo, _ := gittest.CreateRepository(t, ctx, cfg) @@ -207,12 +253,26 @@ func testServerPostUploadPackGitProtocol(t *testing.T, ctx context.Context, make func TestServer_PostUploadPackWithSidechannel_suppressDeepenExitError(t *testing.T) { t.Parallel() - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackSuppressDeepenExitError, makePostUploadPackWithSidechannelRequest, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackSuppressDeepenExitError, makePostUploadPackWithSidechannelRequest, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{}, + ) +} + +func TestServer_PostUploadPackV3_suppressDeepenExitError(t *testing.T) { + t.Parallel() + + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackSuppressDeepenExitError, makePostUploadPackV3, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{testserver.WithHTTP2()}, + ) } -func testServerPostUploadPackSuppressDeepenExitError(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func testServerPostUploadPackSuppressDeepenExitError(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { cfg := testcfg.Build(t, opts...) - cfg.SocketPath = runSmartHTTPServer(t, cfg) + cfg.SocketPath = startSmartHTTPServerWithOptions(t, cfg, nil, serverOpts).Address() repo, repoPath := gittest.CreateRepository(t, ctx, cfg) commitID := gittest.WriteCommit(t, cfg, repoPath) @@ -232,10 +292,17 @@ func TestServer_PostUploadPackWithSidechannel_usesPackObjectsHook(t *testing.T) t.Parallel() ctx := testhelper.Context(t) - testServerPostUploadPackUsesPackObjectsHook(t, ctx, makePostUploadPackWithSidechannelRequest) + testServerPostUploadPackUsesPackObjectsHook(t, ctx, makePostUploadPackWithSidechannelRequest, nil, nil) +} + +func TestServer_PostUploadPackV3_usesPackObjectsHook(t *testing.T) { + t.Parallel() + ctx := testhelper.Context(t) + + testServerPostUploadPackUsesPackObjectsHook(t, ctx, makePostUploadPackV3, nil, []testserver.GitalyServerOpt{testserver.WithHTTP2()}) } -func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { cfg := testcfg.Build(t, append(opts, testcfg.WithPackObjectsCacheEnabled())...) cfg.BinDir = testhelper.TempDir(t) @@ -252,7 +319,7 @@ func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Conte // transferred back. testhelper.WriteExecutable(t, cfg.BinaryPath("gitaly-hooks"), []byte(hookScript)) - cfg.SocketPath = runSmartHTTPServer(t, cfg) + cfg.SocketPath = startSmartHTTPServerWithOptions(t, cfg, nil, serverOpts).Address() repo, repoPath := gittest.CreateRepository(t, ctx, cfg) oldHead := gittest.WriteCommit(t, cfg, repoPath) @@ -276,14 +343,28 @@ func testServerPostUploadPackUsesPackObjectsHook(t *testing.T, ctx context.Conte func TestServer_PostUploadPack_validation(t *testing.T) { t.Parallel() - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackValidation, makePostUploadPackWithSidechannelRequest, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackValidation, makePostUploadPackWithSidechannelRequest, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{}, + ) +} + +func TestServer_PostUploadPackV3_validation(t *testing.T) { + t.Parallel() + + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackValidation, makePostUploadPackV3, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{testserver.WithHTTP2()}, + ) } -func testServerPostUploadPackValidation(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func testServerPostUploadPackValidation(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { t.Parallel() cfg := testcfg.Build(t, opts...) - serverSocketPath := runSmartHTTPServer(t, cfg) + serverSocketPath := startSmartHTTPServerWithOptions(t, cfg, nil, serverOpts).Address() cfg.SocketPath = serverSocketPath for _, tc := range []struct { @@ -320,12 +401,26 @@ func testServerPostUploadPackValidation(t *testing.T, ctx context.Context, makeR func TestServer_PostUploadPackSidechannel_validation(t *testing.T) { t.Parallel() - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackWithSideChannelValidation, makePostUploadPackWithSidechannelRequest, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackWithSideChannelValidation, makePostUploadPackWithSidechannelRequest, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{}, + ) +} + +func TestServer_PostUploadPackV3(t *testing.T) { + t.Parallel() + + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackWithSideChannelValidation, makePostUploadPackV3, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{testserver.WithHTTP2()}, + ) } -func testServerPostUploadPackWithSideChannelValidation(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func testServerPostUploadPackWithSideChannelValidation(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { cfg := testcfg.Build(t, opts...) - serverSocketPath := runSmartHTTPServer(t, cfg) + serverSocketPath := startSmartHTTPServerWithOptions(t, cfg, nil, serverOpts).Address() for _, tc := range []struct { desc string @@ -398,15 +493,29 @@ func extractPackDataFromResponse(t *testing.T, buf *bytes.Buffer) ([]byte, int, func TestServer_PostUploadPackWithSidechannel_partialClone(t *testing.T) { t.Parallel() - runTestWithAndWithoutConfigOptions(t, testServerPostUploadPackPartialClone, makePostUploadPackWithSidechannelRequest, testcfg.WithPackObjectsCacheEnabled()) + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackPartialClone, makePostUploadPackWithSidechannelRequest, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{}, + ) } -func testServerPostUploadPackPartialClone(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func TestServer_PostUploadPackV3_partialClone(t *testing.T) { + t.Parallel() + + runTestWithAndWithoutConfigOptions( + t, testServerPostUploadPackPartialClone, makePostUploadPackV3, + []testcfg.Option{testcfg.WithPackObjectsCacheEnabled()}, + []testserver.GitalyServerOpt{testserver.WithHTTP2()}, + ) +} + +func testServerPostUploadPackPartialClone(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { cfg := testcfg.Build(t, opts...) testcfg.BuildGitalyHooks(t, cfg) negotiationMetrics := prometheus.NewCounterVec(prometheus.CounterOpts{}, []string{"feature"}) - cfg.SocketPath = runSmartHTTPServer(t, cfg, WithPackfileNegotiationMetrics(negotiationMetrics)) + cfg.SocketPath = startSmartHTTPServerWithOptions(t, cfg, []ServerOpt{WithPackfileNegotiationMetrics(negotiationMetrics)}, serverOpts).Address() repo, repoPath := gittest.CreateRepository(t, ctx, cfg) _, localRepoPath := gittest.CreateRepository(t, ctx, cfg) @@ -451,12 +560,19 @@ func TestServer_PostUploadPackWithSidechannel_allowAnySHA1InWant(t *testing.T) { t.Parallel() ctx := testhelper.Context(t) - testServerPostUploadPackAllowAnySHA1InWant(t, ctx, makePostUploadPackWithSidechannelRequest) + testServerPostUploadPackAllowAnySHA1InWant(t, ctx, makePostUploadPackWithSidechannelRequest, nil, nil) } -func testServerPostUploadPackAllowAnySHA1InWant(t *testing.T, ctx context.Context, makeRequest requestMaker, opts ...testcfg.Option) { +func TestServer_PostUploadPackV3_allowAnySHA1InWant(t *testing.T) { + t.Parallel() + ctx := testhelper.Context(t) + + testServerPostUploadPackAllowAnySHA1InWant(t, ctx, makePostUploadPackV3, nil, []testserver.GitalyServerOpt{testserver.WithHTTP2()}) +} + +func testServerPostUploadPackAllowAnySHA1InWant(t *testing.T, ctx context.Context, makeRequest requestMaker, opts []testcfg.Option, serverOpts []testserver.GitalyServerOpt) { cfg := testcfg.Build(t, opts...) - cfg.SocketPath = runSmartHTTPServer(t, cfg) + cfg.SocketPath = startSmartHTTPServerWithOptions(t, cfg, nil, serverOpts).Address() repo, repoPath := gittest.CreateRepository(t, ctx, cfg) _, localRepoPath := gittest.CreateRepository(t, ctx, cfg) @@ -499,7 +615,7 @@ func dialSmartHTTPServerWithSidechannel(t *testing.T, serverSocketPath, token st return conn } -func makePostUploadPackWithSidechannelRequest(t *testing.T, ctx context.Context, serverSocketPath, token string, in *gitalypb.PostUploadPackWithSidechannelRequest, body io.Reader) (*bytes.Buffer, error) { +func makePostUploadPackWithSidechannelRequest(t *testing.T, ctx context.Context, serverSocketPath, token string, in postUploadPackRequest, body io.Reader) (*bytes.Buffer, error) { t.Helper() registry := sidechannel.NewRegistry() @@ -549,3 +665,65 @@ func makePostUploadPackWithSidechannelRequest(t *testing.T, ctx context.Context, return responseBuffer, err } + +func makePostUploadPackV3(t *testing.T, ctx context.Context, serverSocketPath, token string, in postUploadPackRequest, body io.Reader) (*bytes.Buffer, error) { + t.Helper() + + conn, err := grpc.Dial( + serverSocketPath, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultCallOptions(grpc.CallContentSubtype("raw")), + ) + require.NoError(t, err) + + client := gitalypb.NewSmartHTTPServiceClient(conn) + defer testhelper.MustClose(t, conn) + + stream, err := client.PostUploadPackV3(ctx) + if err != nil { + return nil, err + } + + var firstRequest []byte + if firstRequest, err = proto.Marshal(&gitalypb.PostUploadPackV3Request{ + Repository: in.GetRepository(), + GitConfigOptions: in.GetGitConfigOptions(), + GitProtocol: in.GetGitProtocol(), + }); err != nil { + return nil, err + } + if err = stream.SendMsg(firstRequest); err != nil { + return nil, err + } + + responseBuffer := &bytes.Buffer{} + stdin := streamio.NewReader(func() ([]byte, error) { + var stdinBuffer []byte + err := stream.RecvMsg(&stdinBuffer) + if err != nil { + return nil, err + } + return stdinBuffer, err + }) + stdout := streamio.NewWriter(func(p []byte) error { + return stream.SendMsg(p) + }) + + errC := make(chan error, 1) + go func() { + _, err := io.CopyBuffer(responseBuffer, stdin, make([]byte, 64*1024)) + errC <- err + }() + + if body != nil { + if _, err = io.CopyBuffer(stdout, body, make([]byte, 64*1024)); err != nil { + return nil, err + } + } + + if err := stream.CloseSend(); err != nil { + return nil, err + } + + return responseBuffer, <-errC +} diff --git a/internal/grpc/encoding/raw.go b/internal/grpc/encoding/raw.go new file mode 100644 index 000000000..5aed6b87d --- /dev/null +++ b/internal/grpc/encoding/raw.go @@ -0,0 +1,36 @@ +package encoding + +import ( + "google.golang.org/grpc/encoding" +) + +const Name = "raw" + +func init() { + // TODO: This should be called explicitly + encoding.RegisterCodec(codec{}) +} + +// codec is a Codec implementation with raw encoding. Clients and Servers +// exchange raw bytes without serializing/deserializing. It means they can +// send/receive any message without being restricted to Protobuf. Both sides +// are responsible for performing serialization and deserialization in the +// handler. +// The usage of this encoder is restricted: +// - The call must be bi-directional streaming +// - Both sides must use SendMsg and RecvMsg. Code-generated Send and Recv are +// not usable. +type codec struct{} + +func (codec) Marshal(v interface{}) ([]byte, error) { + return v.([]byte), nil +} + +func (codec) Unmarshal(data []byte, v interface{}) error { + *v.(*[]byte) = data + return nil +} + +func (codec) Name() string { + return Name +} diff --git a/internal/testhelper/testserver/gitaly.go b/internal/testhelper/testserver/gitaly.go index d46061101..b28007458 100644 --- a/internal/testhelper/testserver/gitaly.go +++ b/internal/testhelper/testserver/gitaly.go @@ -3,6 +3,7 @@ package testserver import ( "context" "net" + "net/http" "os" "testing" @@ -204,9 +205,22 @@ func runGitaly(tb testing.TB, cfg config.Cfg, registrar func(srv *grpc.Server, d secure := cfg.TLS.CertPath != "" && cfg.TLS.KeyPath != "" - externalServer, err := serverFactory.CreateExternal(secure, serverOpts...) - require.NoError(tb, err) - tb.Cleanup(externalServer.Stop) + var externalServer *grpc.Server + var httpServer *http.Server + var err error + + if gsd.useHTTP2 { + externalServer, httpServer, err = serverFactory.CreateHTTP2External(secure, serverOpts...) + require.NoError(tb, err) + tb.Cleanup(func() { + externalServer.GracefulStop() + httpServer.Shutdown(testhelper.Context(tb)) + }) + } else { + externalServer, err = serverFactory.CreateExternal(secure, serverOpts...) + require.NoError(tb, err) + tb.Cleanup(externalServer.Stop) + } registrar(externalServer, deps) registerHealthServerIfNotRegistered(externalServer) @@ -232,7 +246,14 @@ func runGitaly(tb testing.TB, cfg config.Cfg, registrar func(srv *grpc.Server, d } go func() { - assert.NoError(tb, externalServer.Serve(listener), "failure to serve external gRPC") + if gsd.useHTTP2 { + err := httpServer.Serve(listener) + if err != http.ErrServerClosed { + assert.NoError(tb, err, "failure to serve external gRPC") + } + } else { + assert.NoError(tb, externalServer.Serve(listener), "failure to serve external gRPC") + } }() ctx := testhelper.Context(tb) @@ -268,6 +289,7 @@ type gitalyServerDeps struct { git2goExecutor *git2go.Executor updaterWithHooks *updateref.UpdaterWithHooks housekeepingManager housekeeping.Manager + useHTTP2 bool } func (gsd *gitalyServerDeps) createDependencies(tb testing.TB, cfg config.Cfg) *service.Dependencies { @@ -487,3 +509,11 @@ func WithHousekeepingManager(manager housekeeping.Manager) GitalyServerOpt { return deps } } + +// WithHTTP2 starts Gitaly server using HTTP2 server +func WithHTTP2() GitalyServerOpt { + return func(deps gitalyServerDeps) gitalyServerDeps { + deps.useHTTP2 = true + return deps + } +} diff --git a/proto/go/gitalypb/smarthttp.pb.go b/proto/go/gitalypb/smarthttp.pb.go index 1829cd764..8d31bb4ee 100644 --- a/proto/go/gitalypb/smarthttp.pb.go +++ b/proto/go/gitalypb/smarthttp.pb.go @@ -204,6 +204,81 @@ func (x *PostUploadPackWithSidechannelRequest) GetGitProtocol() string { } // This comment is left unintentionally blank. +type PostUploadPackV3Request 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"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *PostUploadPackV3Request) Reset() { + *x = PostUploadPackV3Request{} + if protoimpl.UnsafeEnabled { + mi := &file_smarthttp_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PostUploadPackV3Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PostUploadPackV3Request) ProtoMessage() {} + +func (x *PostUploadPackV3Request) ProtoReflect() protoreflect.Message { + mi := &file_smarthttp_proto_msgTypes[3] + 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 PostUploadPackV3Request.ProtoReflect.Descriptor instead. +func (*PostUploadPackV3Request) Descriptor() ([]byte, []int) { + return file_smarthttp_proto_rawDescGZIP(), []int{3} +} + +func (x *PostUploadPackV3Request) GetRepository() *Repository { + if x != nil { + return x.Repository + } + return nil +} + +func (x *PostUploadPackV3Request) GetGitConfigOptions() []string { + if x != nil { + return x.GitConfigOptions + } + return nil +} + +func (x *PostUploadPackV3Request) GetGitProtocol() string { + if x != nil { + return x.GitProtocol + } + return "" +} + +func (x *PostUploadPackV3Request) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +// This comment is left unintentionally blank. type PostUploadPackWithSidechannelResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -213,7 +288,7 @@ type PostUploadPackWithSidechannelResponse struct { func (x *PostUploadPackWithSidechannelResponse) Reset() { *x = PostUploadPackWithSidechannelResponse{} if protoimpl.UnsafeEnabled { - mi := &file_smarthttp_proto_msgTypes[3] + mi := &file_smarthttp_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -226,7 +301,7 @@ func (x *PostUploadPackWithSidechannelResponse) String() string { func (*PostUploadPackWithSidechannelResponse) ProtoMessage() {} func (x *PostUploadPackWithSidechannelResponse) ProtoReflect() protoreflect.Message { - mi := &file_smarthttp_proto_msgTypes[3] + mi := &file_smarthttp_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -239,7 +314,55 @@ func (x *PostUploadPackWithSidechannelResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use PostUploadPackWithSidechannelResponse.ProtoReflect.Descriptor instead. func (*PostUploadPackWithSidechannelResponse) Descriptor() ([]byte, []int) { - return file_smarthttp_proto_rawDescGZIP(), []int{3} + return file_smarthttp_proto_rawDescGZIP(), []int{4} +} + +// This comment is left unintentionally blank. +type PostUploadPackV3Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *PostUploadPackV3Response) Reset() { + *x = PostUploadPackV3Response{} + if protoimpl.UnsafeEnabled { + mi := &file_smarthttp_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PostUploadPackV3Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PostUploadPackV3Response) ProtoMessage() {} + +func (x *PostUploadPackV3Response) 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 PostUploadPackV3Response.ProtoReflect.Descriptor instead. +func (*PostUploadPackV3Response) Descriptor() ([]byte, []int) { + return file_smarthttp_proto_rawDescGZIP(), []int{5} +} + +func (x *PostUploadPackV3Response) GetData() []byte { + if x != nil { + return x.Data + } + return nil } // This comment is left unintentionally blank. @@ -268,7 +391,7 @@ type PostReceivePackRequest struct { func (x *PostReceivePackRequest) Reset() { *x = PostReceivePackRequest{} if protoimpl.UnsafeEnabled { - mi := &file_smarthttp_proto_msgTypes[4] + mi := &file_smarthttp_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -281,7 +404,7 @@ func (x *PostReceivePackRequest) String() string { func (*PostReceivePackRequest) ProtoMessage() {} func (x *PostReceivePackRequest) ProtoReflect() protoreflect.Message { - mi := &file_smarthttp_proto_msgTypes[4] + mi := &file_smarthttp_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -294,7 +417,7 @@ func (x *PostReceivePackRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PostReceivePackRequest.ProtoReflect.Descriptor instead. func (*PostReceivePackRequest) Descriptor() ([]byte, []int) { - return file_smarthttp_proto_rawDescGZIP(), []int{4} + return file_smarthttp_proto_rawDescGZIP(), []int{6} } func (x *PostReceivePackRequest) GetRepository() *Repository { @@ -359,7 +482,7 @@ type PostReceivePackResponse struct { func (x *PostReceivePackResponse) Reset() { *x = PostReceivePackResponse{} if protoimpl.UnsafeEnabled { - mi := &file_smarthttp_proto_msgTypes[5] + mi := &file_smarthttp_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -372,7 +495,7 @@ func (x *PostReceivePackResponse) String() string { func (*PostReceivePackResponse) ProtoMessage() {} func (x *PostReceivePackResponse) ProtoReflect() protoreflect.Message { - mi := &file_smarthttp_proto_msgTypes[5] + mi := &file_smarthttp_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -385,7 +508,7 @@ func (x *PostReceivePackResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PostReceivePackResponse.ProtoReflect.Descriptor instead. func (*PostReceivePackResponse) Descriptor() ([]byte, []int) { - return file_smarthttp_proto_rawDescGZIP(), []int{5} + return file_smarthttp_proto_rawDescGZIP(), []int{7} } func (x *PostReceivePackResponse) GetData() []byte { @@ -424,60 +547,81 @@ var file_smarthttp_proto_rawDesc = []byte{ 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, 0xa0, 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, 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, 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, + 0x09, 0x52, 0x0b, 0x67, 0x69, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0xb8, + 0x01, 0x0a, 0x17, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, + 0x6b, 0x56, 0x33, 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, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 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, 0x2e, 0x0a, 0x18, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x56, 0x33, 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, 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, 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, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, - 0x6c, 0x79, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0x82, 0x04, 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, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, + 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, 0x60, 0x0a, 0x10, 0x50, 0x6f, 0x73, + 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x56, 0x33, 0x12, 0x1f, 0x2e, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x50, 0x61, 0x63, 0x6b, 0x56, 0x33, 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, 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, 0x36, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -492,33 +636,38 @@ func file_smarthttp_proto_rawDescGZIP() []byte { return file_smarthttp_proto_rawDescData } -var file_smarthttp_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_smarthttp_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_smarthttp_proto_goTypes = []interface{}{ (*InfoRefsRequest)(nil), // 0: gitaly.InfoRefsRequest (*InfoRefsResponse)(nil), // 1: gitaly.InfoRefsResponse (*PostUploadPackWithSidechannelRequest)(nil), // 2: gitaly.PostUploadPackWithSidechannelRequest - (*PostUploadPackWithSidechannelResponse)(nil), // 3: gitaly.PostUploadPackWithSidechannelResponse - (*PostReceivePackRequest)(nil), // 4: gitaly.PostReceivePackRequest - (*PostReceivePackResponse)(nil), // 5: gitaly.PostReceivePackResponse - (*Repository)(nil), // 6: gitaly.Repository + (*PostUploadPackV3Request)(nil), // 3: gitaly.PostUploadPackV3Request + (*PostUploadPackWithSidechannelResponse)(nil), // 4: gitaly.PostUploadPackWithSidechannelResponse + (*PostUploadPackV3Response)(nil), // 5: gitaly.PostUploadPackV3Response + (*PostReceivePackRequest)(nil), // 6: gitaly.PostReceivePackRequest + (*PostReceivePackResponse)(nil), // 7: gitaly.PostReceivePackResponse + (*Repository)(nil), // 8: gitaly.Repository } var file_smarthttp_proto_depIdxs = []int32{ - 6, // 0: gitaly.InfoRefsRequest.repository:type_name -> gitaly.Repository - 6, // 1: gitaly.PostUploadPackWithSidechannelRequest.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.PostUploadPackWithSidechannel:input_type -> gitaly.PostUploadPackWithSidechannelRequest - 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.PostUploadPackWithSidechannel:output_type -> gitaly.PostUploadPackWithSidechannelResponse - 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 + 8, // 0: gitaly.InfoRefsRequest.repository:type_name -> gitaly.Repository + 8, // 1: gitaly.PostUploadPackWithSidechannelRequest.repository:type_name -> gitaly.Repository + 8, // 2: gitaly.PostUploadPackV3Request.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.PostUploadPackWithSidechannel:input_type -> gitaly.PostUploadPackWithSidechannelRequest + 3, // 7: gitaly.SmartHTTPService.PostUploadPackV3:input_type -> gitaly.PostUploadPackV3Request + 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 + 4, // 11: gitaly.SmartHTTPService.PostUploadPackWithSidechannel:output_type -> gitaly.PostUploadPackWithSidechannelResponse + 7, // 12: gitaly.SmartHTTPService.PostUploadPackV3:output_type -> gitaly.PostReceivePackResponse + 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 } func init() { file_smarthttp_proto_init() } @@ -566,7 +715,7 @@ func file_smarthttp_proto_init() { } } file_smarthttp_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostUploadPackWithSidechannelResponse); i { + switch v := v.(*PostUploadPackV3Request); i { case 0: return &v.state case 1: @@ -578,7 +727,7 @@ func file_smarthttp_proto_init() { } } file_smarthttp_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PostReceivePackRequest); i { + switch v := v.(*PostUploadPackWithSidechannelResponse); i { case 0: return &v.state case 1: @@ -590,6 +739,30 @@ func file_smarthttp_proto_init() { } } file_smarthttp_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PostUploadPackV3Response); 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 + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_smarthttp_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PostReceivePackResponse); i { case 0: return &v.state @@ -608,7 +781,7 @@ func file_smarthttp_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_smarthttp_proto_rawDesc, NumEnums: 0, - NumMessages: 6, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/go/gitalypb/smarthttp_grpc.pb.go b/proto/go/gitalypb/smarthttp_grpc.pb.go index a6836121f..665aadd09 100644 --- a/proto/go/gitalypb/smarthttp_grpc.pb.go +++ b/proto/go/gitalypb/smarthttp_grpc.pb.go @@ -32,6 +32,7 @@ type SmartHTTPServiceClient interface { InfoRefsReceivePack(ctx context.Context, in *InfoRefsRequest, opts ...grpc.CallOption) (SmartHTTPService_InfoRefsReceivePackClient, error) // Request and response body for POST /upload-pack using sidechannel protocol PostUploadPackWithSidechannel(ctx context.Context, in *PostUploadPackWithSidechannelRequest, opts ...grpc.CallOption) (*PostUploadPackWithSidechannelResponse, error) + PostUploadPackV3(ctx context.Context, opts ...grpc.CallOption) (SmartHTTPService_PostUploadPackV3Client, error) // Request and response body for POST /receive-pack PostReceivePack(ctx context.Context, opts ...grpc.CallOption) (SmartHTTPService_PostReceivePackClient, error) } @@ -117,8 +118,39 @@ func (c *smartHTTPServiceClient) PostUploadPackWithSidechannel(ctx context.Conte return out, nil } +func (c *smartHTTPServiceClient) PostUploadPackV3(ctx context.Context, opts ...grpc.CallOption) (SmartHTTPService_PostUploadPackV3Client, error) { + stream, err := c.cc.NewStream(ctx, &SmartHTTPService_ServiceDesc.Streams[2], "/gitaly.SmartHTTPService/PostUploadPackV3", opts...) + if err != nil { + return nil, err + } + x := &smartHTTPServicePostUploadPackV3Client{stream} + return x, nil +} + +type SmartHTTPService_PostUploadPackV3Client interface { + Send(*PostUploadPackV3Request) error + Recv() (*PostReceivePackResponse, error) + grpc.ClientStream +} + +type smartHTTPServicePostUploadPackV3Client struct { + grpc.ClientStream +} + +func (x *smartHTTPServicePostUploadPackV3Client) Send(m *PostUploadPackV3Request) error { + return x.ClientStream.SendMsg(m) +} + +func (x *smartHTTPServicePostUploadPackV3Client) Recv() (*PostReceivePackResponse, error) { + m := new(PostReceivePackResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *smartHTTPServiceClient) PostReceivePack(ctx context.Context, opts ...grpc.CallOption) (SmartHTTPService_PostReceivePackClient, error) { - stream, err := c.cc.NewStream(ctx, &SmartHTTPService_ServiceDesc.Streams[2], "/gitaly.SmartHTTPService/PostReceivePack", opts...) + stream, err := c.cc.NewStream(ctx, &SmartHTTPService_ServiceDesc.Streams[3], "/gitaly.SmartHTTPService/PostReceivePack", opts...) if err != nil { return nil, err } @@ -162,6 +194,7 @@ type SmartHTTPServiceServer interface { InfoRefsReceivePack(*InfoRefsRequest, SmartHTTPService_InfoRefsReceivePackServer) error // Request and response body for POST /upload-pack using sidechannel protocol PostUploadPackWithSidechannel(context.Context, *PostUploadPackWithSidechannelRequest) (*PostUploadPackWithSidechannelResponse, error) + PostUploadPackV3(SmartHTTPService_PostUploadPackV3Server) error // Request and response body for POST /receive-pack PostReceivePack(SmartHTTPService_PostReceivePackServer) error mustEmbedUnimplementedSmartHTTPServiceServer() @@ -180,6 +213,9 @@ func (UnimplementedSmartHTTPServiceServer) InfoRefsReceivePack(*InfoRefsRequest, func (UnimplementedSmartHTTPServiceServer) PostUploadPackWithSidechannel(context.Context, *PostUploadPackWithSidechannelRequest) (*PostUploadPackWithSidechannelResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PostUploadPackWithSidechannel not implemented") } +func (UnimplementedSmartHTTPServiceServer) PostUploadPackV3(SmartHTTPService_PostUploadPackV3Server) error { + return status.Errorf(codes.Unimplemented, "method PostUploadPackV3 not implemented") +} func (UnimplementedSmartHTTPServiceServer) PostReceivePack(SmartHTTPService_PostReceivePackServer) error { return status.Errorf(codes.Unimplemented, "method PostReceivePack not implemented") } @@ -256,6 +292,32 @@ func _SmartHTTPService_PostUploadPackWithSidechannel_Handler(srv interface{}, ct return interceptor(ctx, in, info, handler) } +func _SmartHTTPService_PostUploadPackV3_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SmartHTTPServiceServer).PostUploadPackV3(&smartHTTPServicePostUploadPackV3Server{stream}) +} + +type SmartHTTPService_PostUploadPackV3Server interface { + Send(*PostReceivePackResponse) error + Recv() (*PostUploadPackV3Request, error) + grpc.ServerStream +} + +type smartHTTPServicePostUploadPackV3Server struct { + grpc.ServerStream +} + +func (x *smartHTTPServicePostUploadPackV3Server) Send(m *PostReceivePackResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *smartHTTPServicePostUploadPackV3Server) Recv() (*PostUploadPackV3Request, error) { + m := new(PostUploadPackV3Request) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func _SmartHTTPService_PostReceivePack_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(SmartHTTPServiceServer).PostReceivePack(&smartHTTPServicePostReceivePackServer{stream}) } @@ -306,6 +368,12 @@ var SmartHTTPService_ServiceDesc = grpc.ServiceDesc{ ServerStreams: true, }, { + StreamName: "PostUploadPackV3", + Handler: _SmartHTTPService_PostUploadPackV3_Handler, + ServerStreams: true, + ClientStreams: true, + }, + { StreamName: "PostReceivePack", Handler: _SmartHTTPService_PostReceivePack_Handler, ServerStreams: true, diff --git a/proto/smarthttp.proto b/proto/smarthttp.proto index d54d123e5..51c8f0682 100644 --- a/proto/smarthttp.proto +++ b/proto/smarthttp.proto @@ -35,6 +35,12 @@ service SmartHTTPService { }; } + rpc PostUploadPackV3(stream PostUploadPackV3Request) returns (stream PostReceivePackResponse) { + option (op_type) = { + op: ACCESSOR + }; + } + // Request and response body for POST /receive-pack rpc PostReceivePack(stream PostReceivePackRequest) returns (stream PostReceivePackResponse) { option (op_type) = { @@ -71,10 +77,26 @@ message PostUploadPackWithSidechannelRequest { } // This comment is left unintentionally blank. +message PostUploadPackV3Request { + // 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; + bytes data = 4; +} + +// This comment is left unintentionally blank. message PostUploadPackWithSidechannelResponse { } // This comment is left unintentionally blank. +message PostUploadPackV3Response { + bytes data = 1; +} + +// This comment is left unintentionally blank. message PostReceivePackRequest { // repository should only be present in the first message of the stream Repository repository = 1 [(target_repository)=true]; |