diff options
author | Justin Tobler <jtobler@gitlab.com> | 2023-12-06 19:44:15 +0300 |
---|---|---|
committer | Justin Tobler <jtobler@gitlab.com> | 2023-12-06 19:44:15 +0300 |
commit | 761861553cbf9b15d2d642b7e313a576a306950d (patch) | |
tree | a0a983eb74e11b7445cd92634062e35485e4a525 | |
parent | 9b54bcc1d8e0ddcefcfdf9142a16778d02a23957 (diff) | |
parent | ec32915c508b8c98765640867175916cd2b77215 (diff) |
Merge branch 'jt/analysis-service' into 'master'
analysis: Implement `CheckBlobsGenerated` RPC
See merge request https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6560
Merged-by: Justin Tobler <jtobler@gitlab.com>
Approved-by: Patrick Steinhardt <psteinhardt@gitlab.com>
Reviewed-by: Patrick Steinhardt <psteinhardt@gitlab.com>
Reviewed-by: Justin Tobler <jtobler@gitlab.com>
Reviewed-by: karthik nayak <knayak@gitlab.com>
-rw-r--r-- | internal/gitaly/service/analysis/check_generated.go | 177 | ||||
-rw-r--r-- | internal/gitaly/service/analysis/check_generated_test.go | 374 | ||||
-rw-r--r-- | internal/gitaly/service/analysis/server.go | 33 | ||||
-rw-r--r-- | internal/gitaly/service/analysis/testhelper_test.go | 11 | ||||
-rw-r--r-- | internal/gitaly/service/setup/register.go | 2 | ||||
-rw-r--r-- | proto/analysis.proto | 62 | ||||
-rw-r--r-- | proto/go/gitalypb/analysis.pb.go | 403 | ||||
-rw-r--r-- | proto/go/gitalypb/analysis_grpc.pb.go | 155 | ||||
-rw-r--r-- | proto/go/gitalypb/protolist.go | 1 |
9 files changed, 1218 insertions, 0 deletions
diff --git a/internal/gitaly/service/analysis/check_generated.go b/internal/gitaly/service/analysis/check_generated.go new file mode 100644 index 000000000..708efddca --- /dev/null +++ b/internal/gitaly/service/analysis/check_generated.go @@ -0,0 +1,177 @@ +package analysis + +import ( + "errors" + "fmt" + "io" + + "github.com/go-enry/go-enry/v2" + "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/helper/chunk" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" + "golang.org/x/sync/errgroup" + "google.golang.org/protobuf/proto" +) + +func (s *server) CheckBlobsGenerated(stream gitalypb.AnalysisService_CheckBlobsGeneratedServer) (returnedErr error) { + req, err := stream.Recv() + if err != nil { + return fmt.Errorf("receiving first request: %w", err) + } + + repository := req.GetRepository() + if err := s.locator.ValidateRepository(repository); err != nil { + return structerr.NewInvalidArgument("%w", err) + } + + ctx := stream.Context() + repo := s.localrepo(repository) + + reader, readerCancel, err := s.catfileCache.ObjectReader(ctx, repo) + if err != nil { + return fmt.Errorf("retrieving object reader: %w", err) + } + defer readerCancel() + + queue, queueCancel, err := reader.ObjectQueue(ctx) + if err != nil { + return fmt.Errorf("retrieving object queue: %w", err) + } + defer queueCancel() + + group, groupCtx := errgroup.WithContext(ctx) + requestsChan := make(chan *gitalypb.CheckBlobsGeneratedRequest) + + // The output of git-cat-file(1) is processed in a separate goroutine to allow requests to + // continuously queue additional objects for processing. + group.Go(func() error { + chunkSender := chunk.New(&checkBlobsGeneratedSender{stream: stream}) + + for req := range requestsChan { + for _, blob := range req.GetBlobs() { + object, err := queue.ReadObject(ctx) + if err != nil { + return fmt.Errorf("reading object: %w", err) + } + + // The requested Git revisions must always resolve to a blob. Otherwise, there is + // not a file to perform the generation check on. + if !object.IsBlob() { + return structerr.NewInvalidArgument("object is not a blob") + } + + // Read an arbitrary number of bytes that is considered enough to determine whether + // the file is generated. + content, err := io.ReadAll(io.LimitReader(object, 2048)) + if err != nil { + return fmt.Errorf("reading blob content: %w", err) + } + + // Any remaining blob data must be consumed before reading the next object. This is + // quite inefficient, but there is currently no alternative because git-cat-file(1) + // cannot be asked to limit the number of bytes it's outputting. + if _, err := io.Copy(io.Discard, object); err != nil { + return fmt.Errorf("discarding remaining blob content: %w", err) + } + + if err := chunkSender.Send(&gitalypb.CheckBlobsGeneratedResponse_Blob{ + Revision: blob.Revision, + Generated: enry.IsGenerated(string(blob.Path), content), + }); err != nil { + return fmt.Errorf("sending response: %w", err) + } + } + + // The sender is flushed for each received request message so that at least one response + // message is always produced. + if err := chunkSender.Flush(); err != nil { + return fmt.Errorf("flushing response: %w", err) + } + } + + return nil + }) + + // Ensure that the sending goroutine always closes and any lingering requests are first + // processed before the surrounding function returns. + defer func() { + close(requestsChan) + if err := group.Wait(); err != nil && returnedErr == nil { + returnedErr = err + } + }() + + for { + if err := validateCheckBlobsGeneratedRequest(req); err != nil { + return structerr.NewInvalidArgument("validating request: %w", err) + } + + // Queue up all revisions specified in the request for processing through git-cat-file(1). + for _, blob := range req.GetBlobs() { + if err := queue.RequestObject(ctx, git.Revision(blob.Revision)); err != nil { + return fmt.Errorf("requesting object: %w", err) + } + } + + if err := queue.Flush(ctx); err != nil { + return fmt.Errorf("flushing queue: %w", err) + } + + select { + // When performing the file generation check the file path is used to gain additional + // insight. Send the request to the processing goroutine to provide file paths and context + // for how to batch response messages. + case requestsChan <- req: + // The group context is cancelled when the sending goroutine exits with an error. + case <-groupCtx.Done(): + return nil + } + + req, err = stream.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + break + } + + return fmt.Errorf("receiving next request: %w", err) + } + } + + return nil +} + +func validateCheckBlobsGeneratedRequest(req *gitalypb.CheckBlobsGeneratedRequest) error { + if len(req.Blobs) == 0 { + return errors.New("empty blobs") + } + + for _, blob := range req.Blobs { + if err := git.ValidateRevision(blob.Revision, git.AllowPathScopedRevision()); err != nil { + return err + } + + if len(blob.GetPath()) == 0 { + return errors.New("empty path") + } + } + + return nil +} + +type checkBlobsGeneratedSender struct { + stream gitalypb.AnalysisService_CheckBlobsGeneratedServer + response *gitalypb.CheckBlobsGeneratedResponse +} + +func (s *checkBlobsGeneratedSender) Reset() { + s.response = &gitalypb.CheckBlobsGeneratedResponse{} +} + +func (s *checkBlobsGeneratedSender) Append(m proto.Message) { + s.response.Blobs = append(s.response.Blobs, m.(*gitalypb.CheckBlobsGeneratedResponse_Blob)) +} + +func (s *checkBlobsGeneratedSender) Send() error { + return s.stream.Send(s.response) +} diff --git a/internal/gitaly/service/analysis/check_generated_test.go b/internal/gitaly/service/analysis/check_generated_test.go new file mode 100644 index 000000000..a3ca63de9 --- /dev/null +++ b/internal/gitaly/service/analysis/check_generated_test.go @@ -0,0 +1,374 @@ +package analysis + +import ( + "errors" + "io" + "testing" + + "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/repository" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +func TestCheckBlobsGenerated(t *testing.T) { + t.Parallel() + + ctx := testhelper.Context(t) + cfg := testcfg.Build(t) + + addr := testserver.RunGitalyServer(t, cfg, func(srv *grpc.Server, deps *service.Dependencies) { + gitalypb.RegisterAnalysisServiceServer(srv, NewServer(deps)) + gitalypb.RegisterRepositoryServiceServer(srv, repository.NewServer(deps)) + }) + cfg.SocketPath = addr + + conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + t.Cleanup(func() { + testhelper.MustClose(t, conn) + }) + + client := gitalypb.NewAnalysisServiceClient(conn) + + type setupData struct { + requests []*gitalypb.CheckBlobsGeneratedRequest + expectedResponses []*gitalypb.CheckBlobsGeneratedResponse + expectedError error + } + + for _, tc := range []struct { + desc string + setup func(t *testing.T) setupData + }{ + { + desc: "repository not set", + setup: func(t *testing.T) setupData { + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: nil, + }, + }, + expectedError: structerr.NewInvalidArgument("repository not set"), + } + }, + }, + { + desc: "blobs not set", + setup: func(t *testing.T) setupData { + repo, _ := gittest.CreateRepository(t, ctx, cfg) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: nil, + }, + }, + expectedError: structerr.NewInvalidArgument("validating request: empty blobs"), + } + }, + }, + { + desc: "revision not set", + setup: func(t *testing.T) setupData { + repo, _ := gittest.CreateRepository(t, ctx, cfg) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: nil, + Path: []byte("path/to/file"), + }, + }, + }, + }, + expectedError: structerr.NewInvalidArgument("validating request: empty revision"), + } + }, + }, + { + desc: "invalid revision", + setup: func(t *testing.T) setupData { + repo, _ := gittest.CreateRepository(t, ctx, cfg) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte("not a valid revision"), + Path: []byte("path/to/file"), + }, + }, + }, + }, + expectedError: structerr.NewInvalidArgument("validating request: revision can't contain whitespace"), + } + }, + }, + { + desc: "path not set", + setup: func(t *testing.T) setupData { + repo, _ := gittest.CreateRepository(t, ctx, cfg) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte("foo:bar"), + Path: nil, + }, + }, + }, + }, + expectedError: structerr.NewInvalidArgument("validating request: empty path"), + } + }, + }, + { + desc: "object not found", + setup: func(t *testing.T) setupData { + repo, _ := gittest.CreateRepository(t, ctx, cfg) + revision := "foo:bar" + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte(revision), + Path: []byte("bar"), + }, + }, + }, + }, + expectedError: testhelper.WithInterceptedMetadata( + structerr.NewInternal("reading object: object not found"), + "revision", + revision, + ), + } + }, + }, + { + desc: "revision does not resolve to a blob", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + commitID := gittest.WriteCommit(t, cfg, repoPath) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte(commitID), + Path: []byte("bar"), + }, + }, + }, + }, + expectedError: structerr.NewInvalidArgument("object is not a blob"), + } + }, + }, + { + desc: "detect generated blob via file path", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + blobID := gittest.WriteBlob(t, cfg, repoPath, []byte("foobar")) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte(blobID), + Path: []byte("Gopkg.lock"), + }, + }, + }, + }, + expectedResponses: []*gitalypb.CheckBlobsGeneratedResponse{ + { + Blobs: []*gitalypb.CheckBlobsGeneratedResponse_Blob{ + { + Revision: []byte(blobID), + Generated: true, + }, + }, + }, + }, + } + }, + }, + { + desc: "detect generated blob via content", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("foo"), gittest.WithTreeEntries( + gittest.TreeEntry{Mode: "100644", Path: "bar.go", Content: "Code generated by\nfoobar\n"}, + )) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte("foo:bar.go"), + Path: []byte("bar.go"), + }, + }, + }, + }, + expectedResponses: []*gitalypb.CheckBlobsGeneratedResponse{ + { + Blobs: []*gitalypb.CheckBlobsGeneratedResponse_Blob{ + { + Revision: []byte("foo:bar.go"), + Generated: true, + }, + }, + }, + }, + } + }, + }, + { + desc: "detect non-generated blob", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + blobID := gittest.WriteBlob(t, cfg, repoPath, []byte("foobar")) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte(blobID), + Path: []byte("foobar.go"), + }, + }, + }, + }, + expectedResponses: []*gitalypb.CheckBlobsGeneratedResponse{ + { + Blobs: []*gitalypb.CheckBlobsGeneratedResponse_Blob{ + { + Revision: []byte(blobID), + Generated: false, + }, + }, + }, + }, + } + }, + }, + { + desc: "check stream of files", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + generatedBlobID := gittest.WriteBlob(t, cfg, repoPath, []byte("Code generated by\nfoobar\n")) + normalBlobID := gittest.WriteBlob(t, cfg, repoPath, []byte("foobar")) + + return setupData{ + requests: []*gitalypb.CheckBlobsGeneratedRequest{ + { + Repository: repo, + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte(generatedBlobID), + Path: []byte("foo.go"), + }, + { + Revision: []byte(normalBlobID), + Path: []byte("bar.go"), + }, + }, + }, + { + Blobs: []*gitalypb.CheckBlobsGeneratedRequest_Blob{ + { + Revision: []byte(normalBlobID), + Path: []byte("bar.go"), + }, + }, + }, + }, + expectedResponses: []*gitalypb.CheckBlobsGeneratedResponse{ + { + Blobs: []*gitalypb.CheckBlobsGeneratedResponse_Blob{ + { + Revision: []byte(generatedBlobID), + Generated: true, + }, + { + Revision: []byte(normalBlobID), + Generated: false, + }, + }, + }, + { + Blobs: []*gitalypb.CheckBlobsGeneratedResponse_Blob{ + { + Revision: []byte(normalBlobID), + Generated: false, + }, + }, + }, + }, + } + }, + }, + } { + tc := tc + t.Run(tc.desc, func(t *testing.T) { + t.Parallel() + testSetup := tc.setup(t) + + stream, err := client.CheckBlobsGenerated(ctx) + require.NoError(t, err) + + for _, req := range testSetup.requests { + err := stream.Send(req) + require.NoError(t, err) + } + + require.NoError(t, stream.CloseSend()) + + var actualResponses []*gitalypb.CheckBlobsGeneratedResponse + for { + resp, err := stream.Recv() + if err != nil { + if !errors.Is(err, io.EOF) { + testhelper.RequireGrpcError(t, testSetup.expectedError, err) + } + break + } + + actualResponses = append(actualResponses, resp) + } + + testhelper.ProtoEqual(t, testSetup.expectedResponses, actualResponses) + }) + } +} diff --git a/internal/gitaly/service/analysis/server.go b/internal/gitaly/service/analysis/server.go new file mode 100644 index 000000000..965ac72af --- /dev/null +++ b/internal/gitaly/service/analysis/server.go @@ -0,0 +1,33 @@ +package analysis + +import ( + "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/git/catfile" + "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" + "gitlab.com/gitlab-org/gitaly/v16/internal/log" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" +) + +type server struct { + gitalypb.UnimplementedAnalysisServiceServer + logger log.Logger + locator storage.Locator + gitCmdFactory git.CommandFactory + catfileCache catfile.Cache +} + +// NewServer creates a new instance of the gRPC AnalysisService. +func NewServer(deps *service.Dependencies) gitalypb.AnalysisServiceServer { + return &server{ + logger: deps.GetLogger(), + locator: deps.GetLocator(), + gitCmdFactory: deps.GetGitCmdFactory(), + catfileCache: deps.GetCatfileCache(), + } +} + +func (s *server) localrepo(repo storage.Repository) *localrepo.Repo { + return localrepo.New(s.logger, s.locator, s.gitCmdFactory, s.catfileCache, repo) +} diff --git a/internal/gitaly/service/analysis/testhelper_test.go b/internal/gitaly/service/analysis/testhelper_test.go new file mode 100644 index 000000000..4b3cbd7dd --- /dev/null +++ b/internal/gitaly/service/analysis/testhelper_test.go @@ -0,0 +1,11 @@ +package analysis + +import ( + "testing" + + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" +) + +func TestMain(m *testing.M) { + testhelper.Run(m) +} diff --git a/internal/gitaly/service/setup/register.go b/internal/gitaly/service/setup/register.go index 4076abb84..e05c8fa07 100644 --- a/internal/gitaly/service/setup/register.go +++ b/internal/gitaly/service/setup/register.go @@ -5,6 +5,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/analysis" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/blob" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/cleanup" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/commit" @@ -51,6 +52,7 @@ var ( // RegisterAll will register all the known gRPC services on the provided gRPC service instance. func RegisterAll(srv *grpc.Server, deps *service.Dependencies) { + gitalypb.RegisterAnalysisServiceServer(srv, analysis.NewServer(deps)) gitalypb.RegisterBlobServiceServer(srv, blob.NewServer(deps)) gitalypb.RegisterCleanupServiceServer(srv, cleanup.NewServer(deps)) gitalypb.RegisterCommitServiceServer(srv, commit.NewServer(deps)) diff --git a/proto/analysis.proto b/proto/analysis.proto new file mode 100644 index 000000000..ced5b9cb9 --- /dev/null +++ b/proto/analysis.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; + +package gitaly; + +import "lint.proto"; +import "shared.proto"; + +option go_package = "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb"; + +// AnalysisService is a gRPC service providing RPCs that analyze objects in a repository. +service AnalysisService { + + // CheckBlobsGenerated checks a provided set of blobs in a specified repository to determine + // whether the file is considered generated. This RPC supports bidirectional streaming because the + // client may specify any number of files to check across multiple request messages and the server + // responds to each request with a separate set of response messages. + // + // Each provided blob in the request is validated when received. Improperly formatted requests + // result in RPC termination and an error being returned to the client. The RPC also aborts and + // returns an error if requests are made that list Git revisions which do not resolve to a blob + // and/or cannot be found in the repository. + rpc CheckBlobsGenerated(stream CheckBlobsGeneratedRequest) returns (stream CheckBlobsGeneratedResponse) { + option (op_type) = { + op: ACCESSOR + }; + } +} + +// CheckBlobsGeneratedRequest is a request for the CheckBlobsGenerated RPC. The client may send +// multiple requests through the stream to check multiple sets of files. The first request must have +// the repository field set. Every request, including the first, must contain a blob set with at +// least a single entry. +message CheckBlobsGeneratedRequest { + // Blob defines the required information to determine if a blob is generated. + message Blob { + // revision is a Git revision that resolves to a blob. + bytes revision = 1; + // path is the file path of the blob and is used to gain insight as to whether the blob is + // generated. + bytes path = 2; + } + + // repository is the repository that generated files are being checked for. + Repository repository = 1 [(target_repository)=true]; + // blobs is a set of blobs that the generated file check is being performed on. + repeated Blob blobs = 2; +} + +// CheckBlobsGeneratedResponse is a response for the CheckBlobsGenerated RPC. If the client sends +// multiple requests, the server responds with a separate response message for each request. +message CheckBlobsGeneratedResponse { + // Blob defines the status of the generated blob check for a revision. + message Blob { + // revision is the Git revision of the checked blob provided in the request. + bytes revision = 1; + // generated is the result of the file generation check for a particular blob. + bool generated = 2; + } + + // blobs is a set of blobs that the generated file check has been performed on. + repeated Blob blobs = 1; +} diff --git a/proto/go/gitalypb/analysis.pb.go b/proto/go/gitalypb/analysis.pb.go new file mode 100644 index 000000000..d19efdc18 --- /dev/null +++ b/proto/go/gitalypb/analysis.pb.go @@ -0,0 +1,403 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v4.23.1 +// source: analysis.proto + +package gitalypb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// CheckBlobsGeneratedRequest is a request for the CheckBlobsGenerated RPC. The client may send +// multiple requests through the stream to check multiple sets of files. The first request must have +// the repository field set. Every request, including the first, must contain a blob set with at +// least a single entry. +type CheckBlobsGeneratedRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // repository is the repository that generated files are being checked for. + Repository *Repository `protobuf:"bytes,1,opt,name=repository,proto3" json:"repository,omitempty"` + // blobs is a set of blobs that the generated file check is being performed on. + Blobs []*CheckBlobsGeneratedRequest_Blob `protobuf:"bytes,2,rep,name=blobs,proto3" json:"blobs,omitempty"` +} + +func (x *CheckBlobsGeneratedRequest) Reset() { + *x = CheckBlobsGeneratedRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_analysis_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckBlobsGeneratedRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckBlobsGeneratedRequest) ProtoMessage() {} + +func (x *CheckBlobsGeneratedRequest) ProtoReflect() protoreflect.Message { + mi := &file_analysis_proto_msgTypes[0] + 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 CheckBlobsGeneratedRequest.ProtoReflect.Descriptor instead. +func (*CheckBlobsGeneratedRequest) Descriptor() ([]byte, []int) { + return file_analysis_proto_rawDescGZIP(), []int{0} +} + +func (x *CheckBlobsGeneratedRequest) GetRepository() *Repository { + if x != nil { + return x.Repository + } + return nil +} + +func (x *CheckBlobsGeneratedRequest) GetBlobs() []*CheckBlobsGeneratedRequest_Blob { + if x != nil { + return x.Blobs + } + return nil +} + +// CheckBlobsGeneratedResponse is a response for the CheckBlobsGenerated RPC. If the client sends +// multiple requests, the server responds with a separate response message for each request. +type CheckBlobsGeneratedResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // blobs is a set of blobs that the generated file check has been performed on. + Blobs []*CheckBlobsGeneratedResponse_Blob `protobuf:"bytes,1,rep,name=blobs,proto3" json:"blobs,omitempty"` +} + +func (x *CheckBlobsGeneratedResponse) Reset() { + *x = CheckBlobsGeneratedResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_analysis_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckBlobsGeneratedResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckBlobsGeneratedResponse) ProtoMessage() {} + +func (x *CheckBlobsGeneratedResponse) ProtoReflect() protoreflect.Message { + mi := &file_analysis_proto_msgTypes[1] + 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 CheckBlobsGeneratedResponse.ProtoReflect.Descriptor instead. +func (*CheckBlobsGeneratedResponse) Descriptor() ([]byte, []int) { + return file_analysis_proto_rawDescGZIP(), []int{1} +} + +func (x *CheckBlobsGeneratedResponse) GetBlobs() []*CheckBlobsGeneratedResponse_Blob { + if x != nil { + return x.Blobs + } + return nil +} + +// Blob defines the required information to determine if a blob is generated. +type CheckBlobsGeneratedRequest_Blob struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // revision is a Git revision that resolves to a blob. + Revision []byte `protobuf:"bytes,1,opt,name=revision,proto3" json:"revision,omitempty"` + // path is the file path of the blob and is used to gain insight as to whether the blob is + // generated. + Path []byte `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` +} + +func (x *CheckBlobsGeneratedRequest_Blob) Reset() { + *x = CheckBlobsGeneratedRequest_Blob{} + if protoimpl.UnsafeEnabled { + mi := &file_analysis_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckBlobsGeneratedRequest_Blob) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckBlobsGeneratedRequest_Blob) ProtoMessage() {} + +func (x *CheckBlobsGeneratedRequest_Blob) ProtoReflect() protoreflect.Message { + mi := &file_analysis_proto_msgTypes[2] + 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 CheckBlobsGeneratedRequest_Blob.ProtoReflect.Descriptor instead. +func (*CheckBlobsGeneratedRequest_Blob) Descriptor() ([]byte, []int) { + return file_analysis_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *CheckBlobsGeneratedRequest_Blob) GetRevision() []byte { + if x != nil { + return x.Revision + } + return nil +} + +func (x *CheckBlobsGeneratedRequest_Blob) GetPath() []byte { + if x != nil { + return x.Path + } + return nil +} + +// Blob defines the status of the generated blob check for a revision. +type CheckBlobsGeneratedResponse_Blob struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // revision is the Git revision of the checked blob provided in the request. + Revision []byte `protobuf:"bytes,1,opt,name=revision,proto3" json:"revision,omitempty"` + // generated is the result of the file generation check for a particular blob. + Generated bool `protobuf:"varint,2,opt,name=generated,proto3" json:"generated,omitempty"` +} + +func (x *CheckBlobsGeneratedResponse_Blob) Reset() { + *x = CheckBlobsGeneratedResponse_Blob{} + if protoimpl.UnsafeEnabled { + mi := &file_analysis_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckBlobsGeneratedResponse_Blob) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckBlobsGeneratedResponse_Blob) ProtoMessage() {} + +func (x *CheckBlobsGeneratedResponse_Blob) ProtoReflect() protoreflect.Message { + mi := &file_analysis_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 CheckBlobsGeneratedResponse_Blob.ProtoReflect.Descriptor instead. +func (*CheckBlobsGeneratedResponse_Blob) Descriptor() ([]byte, []int) { + return file_analysis_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *CheckBlobsGeneratedResponse_Blob) GetRevision() []byte { + if x != nil { + return x.Revision + } + return nil +} + +func (x *CheckBlobsGeneratedResponse_Blob) GetGenerated() bool { + if x != nil { + return x.Generated + } + return false +} + +var File_analysis_proto protoreflect.FileDescriptor + +var file_analysis_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x06, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x1a, 0x0a, 0x6c, 0x69, 0x6e, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xcd, 0x01, 0x0a, 0x1a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x6c, 0x6f, 0x62, + 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 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, 0x3d, 0x0a, 0x05, 0x62, + 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x47, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6c, 0x6f, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x1a, 0x36, 0x0a, 0x04, 0x42, 0x6c, + 0x6f, 0x62, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x22, 0x9f, 0x01, 0x0a, 0x1b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x6c, 0x6f, 0x62, + 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x6f, + 0x62, 0x73, 0x1a, 0x40, 0x0a, 0x04, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x64, 0x32, 0x7d, 0x0a, 0x0f, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6a, 0x0a, 0x13, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x12, 0x22, + 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x6c, 0x6f, + 0x62, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 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 ( + file_analysis_proto_rawDescOnce sync.Once + file_analysis_proto_rawDescData = file_analysis_proto_rawDesc +) + +func file_analysis_proto_rawDescGZIP() []byte { + file_analysis_proto_rawDescOnce.Do(func() { + file_analysis_proto_rawDescData = protoimpl.X.CompressGZIP(file_analysis_proto_rawDescData) + }) + return file_analysis_proto_rawDescData +} + +var file_analysis_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_analysis_proto_goTypes = []interface{}{ + (*CheckBlobsGeneratedRequest)(nil), // 0: gitaly.CheckBlobsGeneratedRequest + (*CheckBlobsGeneratedResponse)(nil), // 1: gitaly.CheckBlobsGeneratedResponse + (*CheckBlobsGeneratedRequest_Blob)(nil), // 2: gitaly.CheckBlobsGeneratedRequest.Blob + (*CheckBlobsGeneratedResponse_Blob)(nil), // 3: gitaly.CheckBlobsGeneratedResponse.Blob + (*Repository)(nil), // 4: gitaly.Repository +} +var file_analysis_proto_depIdxs = []int32{ + 4, // 0: gitaly.CheckBlobsGeneratedRequest.repository:type_name -> gitaly.Repository + 2, // 1: gitaly.CheckBlobsGeneratedRequest.blobs:type_name -> gitaly.CheckBlobsGeneratedRequest.Blob + 3, // 2: gitaly.CheckBlobsGeneratedResponse.blobs:type_name -> gitaly.CheckBlobsGeneratedResponse.Blob + 0, // 3: gitaly.AnalysisService.CheckBlobsGenerated:input_type -> gitaly.CheckBlobsGeneratedRequest + 1, // 4: gitaly.AnalysisService.CheckBlobsGenerated:output_type -> gitaly.CheckBlobsGeneratedResponse + 4, // [4:5] is the sub-list for method output_type + 3, // [3:4] 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_analysis_proto_init() } +func file_analysis_proto_init() { + if File_analysis_proto != nil { + return + } + file_lint_proto_init() + file_shared_proto_init() + if !protoimpl.UnsafeEnabled { + file_analysis_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckBlobsGeneratedRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_analysis_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckBlobsGeneratedResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_analysis_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckBlobsGeneratedRequest_Blob); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_analysis_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckBlobsGeneratedResponse_Blob); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_analysis_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_analysis_proto_goTypes, + DependencyIndexes: file_analysis_proto_depIdxs, + MessageInfos: file_analysis_proto_msgTypes, + }.Build() + File_analysis_proto = out.File + file_analysis_proto_rawDesc = nil + file_analysis_proto_goTypes = nil + file_analysis_proto_depIdxs = nil +} diff --git a/proto/go/gitalypb/analysis_grpc.pb.go b/proto/go/gitalypb/analysis_grpc.pb.go new file mode 100644 index 000000000..04055e50e --- /dev/null +++ b/proto/go/gitalypb/analysis_grpc.pb.go @@ -0,0 +1,155 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.23.1 +// source: analysis.proto + +package gitalypb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// AnalysisServiceClient is the client API for AnalysisService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AnalysisServiceClient interface { + // CheckBlobsGenerated checks a provided set of blobs in a specified repository to determine + // whether the file is considered generated. This RPC supports bidirectional streaming because the + // client may specify any number of files to check across multiple request messages and the server + // responds to each request with a separate set of response messages. + // + // Each provided blob in the request is validated when received. Improperly formatted requests + // result in RPC termination and an error being returned to the client. The RPC also aborts and + // returns an error if requests are made that list Git revisions which do not resolve to a blob + // and/or cannot be found in the repository. + CheckBlobsGenerated(ctx context.Context, opts ...grpc.CallOption) (AnalysisService_CheckBlobsGeneratedClient, error) +} + +type analysisServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAnalysisServiceClient(cc grpc.ClientConnInterface) AnalysisServiceClient { + return &analysisServiceClient{cc} +} + +func (c *analysisServiceClient) CheckBlobsGenerated(ctx context.Context, opts ...grpc.CallOption) (AnalysisService_CheckBlobsGeneratedClient, error) { + stream, err := c.cc.NewStream(ctx, &AnalysisService_ServiceDesc.Streams[0], "/gitaly.AnalysisService/CheckBlobsGenerated", opts...) + if err != nil { + return nil, err + } + x := &analysisServiceCheckBlobsGeneratedClient{stream} + return x, nil +} + +type AnalysisService_CheckBlobsGeneratedClient interface { + Send(*CheckBlobsGeneratedRequest) error + Recv() (*CheckBlobsGeneratedResponse, error) + grpc.ClientStream +} + +type analysisServiceCheckBlobsGeneratedClient struct { + grpc.ClientStream +} + +func (x *analysisServiceCheckBlobsGeneratedClient) Send(m *CheckBlobsGeneratedRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *analysisServiceCheckBlobsGeneratedClient) Recv() (*CheckBlobsGeneratedResponse, error) { + m := new(CheckBlobsGeneratedResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// AnalysisServiceServer is the server API for AnalysisService service. +// All implementations must embed UnimplementedAnalysisServiceServer +// for forward compatibility +type AnalysisServiceServer interface { + // CheckBlobsGenerated checks a provided set of blobs in a specified repository to determine + // whether the file is considered generated. This RPC supports bidirectional streaming because the + // client may specify any number of files to check across multiple request messages and the server + // responds to each request with a separate set of response messages. + // + // Each provided blob in the request is validated when received. Improperly formatted requests + // result in RPC termination and an error being returned to the client. The RPC also aborts and + // returns an error if requests are made that list Git revisions which do not resolve to a blob + // and/or cannot be found in the repository. + CheckBlobsGenerated(AnalysisService_CheckBlobsGeneratedServer) error + mustEmbedUnimplementedAnalysisServiceServer() +} + +// UnimplementedAnalysisServiceServer must be embedded to have forward compatible implementations. +type UnimplementedAnalysisServiceServer struct { +} + +func (UnimplementedAnalysisServiceServer) CheckBlobsGenerated(AnalysisService_CheckBlobsGeneratedServer) error { + return status.Errorf(codes.Unimplemented, "method CheckBlobsGenerated not implemented") +} +func (UnimplementedAnalysisServiceServer) mustEmbedUnimplementedAnalysisServiceServer() {} + +// UnsafeAnalysisServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AnalysisServiceServer will +// result in compilation errors. +type UnsafeAnalysisServiceServer interface { + mustEmbedUnimplementedAnalysisServiceServer() +} + +func RegisterAnalysisServiceServer(s grpc.ServiceRegistrar, srv AnalysisServiceServer) { + s.RegisterService(&AnalysisService_ServiceDesc, srv) +} + +func _AnalysisService_CheckBlobsGenerated_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(AnalysisServiceServer).CheckBlobsGenerated(&analysisServiceCheckBlobsGeneratedServer{stream}) +} + +type AnalysisService_CheckBlobsGeneratedServer interface { + Send(*CheckBlobsGeneratedResponse) error + Recv() (*CheckBlobsGeneratedRequest, error) + grpc.ServerStream +} + +type analysisServiceCheckBlobsGeneratedServer struct { + grpc.ServerStream +} + +func (x *analysisServiceCheckBlobsGeneratedServer) Send(m *CheckBlobsGeneratedResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *analysisServiceCheckBlobsGeneratedServer) Recv() (*CheckBlobsGeneratedRequest, error) { + m := new(CheckBlobsGeneratedRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// AnalysisService_ServiceDesc is the grpc.ServiceDesc for AnalysisService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AnalysisService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "gitaly.AnalysisService", + HandlerType: (*AnalysisServiceServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "CheckBlobsGenerated", + Handler: _AnalysisService_CheckBlobsGenerated_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "analysis.proto", +} diff --git a/proto/go/gitalypb/protolist.go b/proto/go/gitalypb/protolist.go index 30e8c28a3..b7e92510a 100644 --- a/proto/go/gitalypb/protolist.go +++ b/proto/go/gitalypb/protolist.go @@ -4,6 +4,7 @@ package gitalypb // GitalyProtos is a list of gitaly protobuf files var GitalyProtos = []string{ + "analysis.proto", "blob.proto", "cleanup.proto", "commit.proto", |