Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2022-03-24 19:22:22 +0300
committerNick Thomas <nick@gitlab.com>2022-04-05 16:01:48 +0300
commit2778fb7a767f9da6e2fca4a0ebf2d98b667b8ddf (patch)
tree0414a35088effc5865027b20247c179d6c318177
parentbfe8d574aed051bdbfe900fa5cd667224f213d1c (diff)
Allow Commit.RawBlame to take a Range parameter
Git supports a wide array of range options for this option, but for now we restrict the formats we support to the very simplest, which is of the form "1,100". We can use this to implement limits on how many lines of the blame we retrieve GitLab-side, which should help to reduce the resource usage of this particular RPC. Changelog: added
-rw-r--r--internal/gitaly/service/commit/raw_blame.go16
-rw-r--r--internal/gitaly/service/commit/raw_blame_test.go44
2 files changed, 49 insertions, 11 deletions
diff --git a/internal/gitaly/service/commit/raw_blame.go b/internal/gitaly/service/commit/raw_blame.go
index 860e511b7..8bd76ef10 100644
--- a/internal/gitaly/service/commit/raw_blame.go
+++ b/internal/gitaly/service/commit/raw_blame.go
@@ -3,6 +3,7 @@ package commit
import (
"fmt"
"io"
+ "regexp"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
@@ -12,6 +13,8 @@ import (
"google.golang.org/grpc/status"
)
+var validBlameRange = regexp.MustCompile(`\A\d+,\d+\z`)
+
func (s *server) RawBlame(in *gitalypb.RawBlameRequest, stream gitalypb.CommitService_RawBlameServer) error {
if err := validateRawBlameRequest(in); err != nil {
return status.Errorf(codes.InvalidArgument, "RawBlame: %v", err)
@@ -20,10 +23,16 @@ func (s *server) RawBlame(in *gitalypb.RawBlameRequest, stream gitalypb.CommitSe
ctx := stream.Context()
revision := string(in.GetRevision())
path := string(in.GetPath())
+ blameRange := string(in.GetRange())
+
+ flags := []git.Option{git.Flag{Name: "-p"}}
+ if blameRange != "" {
+ flags = append(flags, git.ValueFlag{Name: "-L", Value: blameRange})
+ }
cmd, err := s.gitCmdFactory.New(ctx, in.Repository, git.SubCmd{
Name: "blame",
- Flags: []git.Option{git.Flag{Name: "-p"}},
+ Flags: flags,
Args: []string{revision},
PostSepArgs: []string{path},
})
@@ -59,5 +68,10 @@ func validateRawBlameRequest(in *gitalypb.RawBlameRequest) error {
return fmt.Errorf("empty Path")
}
+ blameRange := in.GetRange()
+ if len(blameRange) > 0 && !validBlameRange.Match(blameRange) {
+ return fmt.Errorf("invalid Range")
+ }
+
return nil
}
diff --git a/internal/gitaly/service/commit/raw_blame_test.go b/internal/gitaly/service/commit/raw_blame_test.go
index 5de17dd91..5de729b04 100644
--- a/internal/gitaly/service/commit/raw_blame_test.go
+++ b/internal/gitaly/service/commit/raw_blame_test.go
@@ -19,22 +19,31 @@ func TestSuccessfulRawBlameRequest(t *testing.T) {
_, repo, _, client := setupCommitServiceWithRepo(ctx, t, true)
testCases := []struct {
- revision, path, data []byte
+ revision, path, data, blameRange []byte
}{
{
- revision: []byte("e63f41fe459e62e1228fcef60d7189127aeba95a"),
- path: []byte("files/ruby/popen.rb"),
- data: testhelper.MustReadFile(t, "testdata/files-ruby-popen-e63f41f-blame.txt"),
+ revision: []byte("e63f41fe459e62e1228fcef60d7189127aeba95a"),
+ path: []byte("files/ruby/popen.rb"),
+ data: testhelper.MustReadFile(t, "testdata/files-ruby-popen-e63f41f-blame.txt"),
+ blameRange: []byte{},
},
{
- revision: []byte("e63f41fe459e62e1228fcef60d7189127aeba95a"),
- path: []byte("files/ruby/../ruby/popen.rb"),
- data: testhelper.MustReadFile(t, "testdata/files-ruby-popen-e63f41f-blame.txt"),
+ revision: []byte("e63f41fe459e62e1228fcef60d7189127aeba95a"),
+ path: []byte("files/ruby/popen.rb"),
+ data: testhelper.MustReadFile(t, "testdata/files-ruby-popen-e63f41f-blame.txt")[0:956],
+ blameRange: []byte("1,5"),
},
{
- revision: []byte("93dcf076a236c837dd47d61f86d95a6b3d71b586"),
- path: []byte("gitaly/empty-file"),
- data: []byte{},
+ revision: []byte("e63f41fe459e62e1228fcef60d7189127aeba95a"),
+ path: []byte("files/ruby/../ruby/popen.rb"),
+ data: testhelper.MustReadFile(t, "testdata/files-ruby-popen-e63f41f-blame.txt"),
+ blameRange: []byte{},
+ },
+ {
+ revision: []byte("93dcf076a236c837dd47d61f86d95a6b3d71b586"),
+ path: []byte("gitaly/empty-file"),
+ data: []byte{},
+ blameRange: []byte{},
},
}
@@ -44,6 +53,7 @@ func TestSuccessfulRawBlameRequest(t *testing.T) {
Repository: repo,
Revision: testCase.revision,
Path: testCase.path,
+ Range: testCase.blameRange,
}
c, err := client.RawBlame(ctx, request)
require.NoError(t, err)
@@ -73,6 +83,7 @@ func TestFailedRawBlameRequest(t *testing.T) {
description string
repo *gitalypb.Repository
revision, path []byte
+ blameRange []byte
code codes.Code
}{
{
@@ -80,6 +91,7 @@ func TestFailedRawBlameRequest(t *testing.T) {
repo: invalidRepo,
revision: []byte("master"),
path: []byte("a/b/c"),
+ blameRange: []byte{},
code: codes.InvalidArgument,
},
{
@@ -87,6 +99,7 @@ func TestFailedRawBlameRequest(t *testing.T) {
repo: repo,
revision: []byte(""),
path: []byte("a/b/c"),
+ blameRange: []byte{},
code: codes.InvalidArgument,
},
{
@@ -94,6 +107,7 @@ func TestFailedRawBlameRequest(t *testing.T) {
repo: repo,
revision: []byte("abcdef"),
path: []byte(""),
+ blameRange: []byte{},
code: codes.InvalidArgument,
},
{
@@ -101,6 +115,15 @@ func TestFailedRawBlameRequest(t *testing.T) {
repo: repo,
revision: []byte("--output=/meow"),
path: []byte("a/b/c"),
+ blameRange: []byte{},
+ code: codes.InvalidArgument,
+ },
+ {
+ description: "Invalid range",
+ repo: repo,
+ revision: []byte("abcdef"),
+ path: []byte("a/b/c"),
+ blameRange: []byte("foo"),
code: codes.InvalidArgument,
},
}
@@ -111,6 +134,7 @@ func TestFailedRawBlameRequest(t *testing.T) {
Repository: testCase.repo,
Revision: testCase.revision,
Path: testCase.path,
+ Range: testCase.blameRange,
}
c, err := client.RawBlame(ctx, &request)
require.NoError(t, err)