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:
authorFabio Pitino <fpitino@gitlab.com>2019-07-11 17:38:53 +0300
committerFabio Pitino <fpitino@gitlab.com>2019-07-11 18:05:24 +0300
commit1ea6abc8a7b7f6888018e0a7eba48f7fe681ea6e (patch)
tree1f514967b1071556364a7755b8dad53c828d6205
parente1ac24c71b21dc6c4e7509e66e08a5719b2e47c1 (diff)
Add ListCommitsByRefName RPC
-rw-r--r--changelogs/unreleased/add-list-commits-by-ref-name-rpc.yml5
-rw-r--r--internal/service/commit/list_commits_by_ref_name.go47
-rw-r--r--internal/service/commit/list_commits_by_ref_name_test.go210
3 files changed, 262 insertions, 0 deletions
diff --git a/changelogs/unreleased/add-list-commits-by-ref-name-rpc.yml b/changelogs/unreleased/add-list-commits-by-ref-name-rpc.yml
new file mode 100644
index 000000000..8473459be
--- /dev/null
+++ b/changelogs/unreleased/add-list-commits-by-ref-name-rpc.yml
@@ -0,0 +1,5 @@
+---
+title: Add ListCommitsByRefName RPC
+merge_request: 1365
+author:
+type: added
diff --git a/internal/service/commit/list_commits_by_ref_name.go b/internal/service/commit/list_commits_by_ref_name.go
new file mode 100644
index 000000000..1e006f7bf
--- /dev/null
+++ b/internal/service/commit/list_commits_by_ref_name.go
@@ -0,0 +1,47 @@
+package commit
+
+import (
+ "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/internal/git/catfile"
+ gitlog "gitlab.com/gitlab-org/gitaly/internal/git/log"
+ "gitlab.com/gitlab-org/gitaly/internal/helper/chunk"
+)
+
+func (s *server) ListCommitsByRefName(in *gitalypb.ListCommitsByRefNameRequest, stream gitalypb.CommitService_ListCommitsByRefNameServer) error {
+ ctx := stream.Context()
+
+ c, err := catfile.New(ctx, in.Repository)
+ if err != nil {
+ return err
+ }
+
+ sender := chunk.New(&commitsByRefNameSender{stream: stream})
+
+ for _, refName := range in.RefNames {
+ commit, err := gitlog.GetCommitCatfile(c, string(refName))
+ if catfile.IsNotFound(err) {
+ continue
+ }
+ if err != nil {
+ return err
+ }
+
+ if err := sender.Send(commit); err != nil {
+ return err
+ }
+ }
+
+ return sender.Flush()
+}
+
+type commitsByRefNameSender struct {
+ response *gitalypb.ListCommitsByRefNameResponse
+ stream gitalypb.CommitService_ListCommitsByRefNameServer
+}
+
+func (c *commitsByRefNameSender) Append(it chunk.Item) {
+ c.response.Commits = append(c.response.Commits, it.(*gitalypb.GitCommit))
+}
+
+func (c *commitsByRefNameSender) Send() error { return c.stream.Send(c.response) }
+func (c *commitsByRefNameSender) Reset() { c.response = &gitalypb.ListCommitsByRefNameResponse{} }
diff --git a/internal/service/commit/list_commits_by_ref_name_test.go b/internal/service/commit/list_commits_by_ref_name_test.go
new file mode 100644
index 000000000..fcd540e5b
--- /dev/null
+++ b/internal/service/commit/list_commits_by_ref_name_test.go
@@ -0,0 +1,210 @@
+package commit
+
+import (
+ "context"
+ "io"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/internal/testhelper"
+)
+
+func TestSuccessfulListCommitsByRefNameRequest(t *testing.T) {
+ server, serverSocketPath := startTestServices(t)
+ defer server.Stop()
+
+ client, conn := newCommitServiceClient(t, serverSocketPath)
+ defer conn.Close()
+
+ testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
+ defer cleanupFn()
+
+ testCases := []struct {
+ desc string
+ request *gitalypb.ListCommitsByRefNameRequest
+ expectedIds []string
+ }{
+ {
+ desc: "find one commit",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{[]byte("refs/heads/master")},
+ },
+ expectedIds: []string{"1e292f8fedd741b75372e19097c76d327140c312"},
+ },
+ {
+ desc: "find one commit with UTF8 characters",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{[]byte("refs/heads/ʕ•ᴥ•ʔ")},
+ },
+ expectedIds: []string{"e63f41fe459e62e1228fcef60d7189127aeba95a"},
+ },
+ {
+ desc: "find one commit with non UTF8 characters",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{[]byte("refs/heads/Ääh-test-utf-8")},
+ },
+ expectedIds: []string{"7975be0116940bf2ad4321f79d02a55c5f7779aa"},
+ },
+ {
+ desc: "find multiple commits",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{
+ []byte("refs/heads/master"),
+ []byte("refs/heads/add-pdf-file"),
+ },
+ },
+ expectedIds: []string{
+ "1e292f8fedd741b75372e19097c76d327140c312",
+ "e774ebd33ca5de8e6ef1e633fd887bb52b9d0a7a",
+ },
+ },
+ {
+ desc: "unknown ref names",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{
+ []byte("refs/heads/does-not-exist-1"),
+ []byte("refs/heads/does-not-exist-2"),
+ },
+ },
+ expectedIds: []string{},
+ },
+ {
+ desc: "find partial commits",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{
+ []byte("refs/heads/master"),
+ []byte("refs/heads/does-not-exist-1"),
+ []byte("refs/heads/add-pdf-file"),
+ },
+ },
+ expectedIds: []string{
+ "1e292f8fedd741b75372e19097c76d327140c312",
+ "e774ebd33ca5de8e6ef1e633fd887bb52b9d0a7a",
+ },
+ },
+ {
+ desc: "no query",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{},
+ },
+ expectedIds: []string{},
+ },
+ {
+ desc: "empty query",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{[]byte("")},
+ },
+ expectedIds: []string{},
+ },
+ {
+ desc: "find empty commit",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{[]byte("refs/heads/1942eed5cc108b19c7405106e81fa96125d0be22")},
+ },
+ expectedIds: []string{"1942eed5cc108b19c7405106e81fa96125d0be22"},
+ },
+ {
+ desc: "invalid ref names",
+ request: &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: [][]byte{
+ []byte("refs/does-not-exist-1"),
+ []byte("does-not-exist-2"),
+ },
+ },
+ expectedIds: []string{},
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.desc, func(t *testing.T) {
+ request := testCase.request
+ request.Repository = testRepo
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ c, err := client.ListCommitsByRefName(ctx, request)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ receivedCommits := consumeGetByRefNameResponse(t, c)
+ require.Len(t, receivedCommits, len(testCase.expectedIds))
+
+ for i, receivedCommit := range receivedCommits {
+ require.Equal(t, testCase.expectedIds[i], receivedCommit.Id, "mismatched commit")
+ }
+ })
+ }
+}
+
+func consumeGetByRefNameResponse(t *testing.T, c gitalypb.CommitService_ListCommitsByRefNameClient) []*gitalypb.GitCommit {
+ receivedCommits := []*gitalypb.GitCommit{}
+ for {
+ resp, err := c.Recv()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ t.Fatal(err)
+ }
+
+ receivedCommits = append(receivedCommits, resp.GetCommits()...)
+ }
+
+ return receivedCommits
+}
+
+var repositoryRefNames = map[string]string{
+ "bb5206fee213d983da88c47f9cf4cc6caf9c66dc": "refs/heads/feature_conflict",
+ "0031876facac3f2b2702a0e53a26e89939a42209": "refs/heads/few-commits",
+ "06041ab2037429d243a38abb55957818dd9f948d": "refs/heads/file-mode-change",
+ "48f0be4bd10c1decee6fae52f9ae6d10f77b60f4": "refs/heads/fix",
+ "ce369011c189f62c815f5971d096b26759bab0d1": "refs/heads/flat-path",
+ "d25b6d94034242f3930dfcfeb6d8d9aac3583992": "refs/heads/flat-path-2",
+ "e56497bb5f03a90a51293fc6d516788730953899": "refs/heads/flatten-dirs",
+ "ab2c9622c02288a2bbaaf35d96088cfdff31d9d9": "refs/heads/gitaly-diff-stuff",
+ "0999bb770f8dc92ab5581cc0b474b3e31a96bf5c": "refs/heads/gitaly-non-utf8-commit",
+ "94bb47ca1297b7b3731ff2a36923640991e9236f": "refs/heads/gitaly-rename-test",
+ "cb19058ecc02d01f8e4290b7e79cafd16a8839b6": "refs/heads/gitaly-stuff",
+ "e63f41fe459e62e1228fcef60d7189127aeba95a": "refs/heads/gitaly-test-ref",
+ "c809470461118b7bcab850f6e9a7ca97ac42f8ea": "refs/heads/gitaly-windows-1251",
+ "5937ac0a7beb003549fc5fd26fc247adbce4a52e": "refs/heads/improve/awesome",
+ "7df99c9ad5b8c9bfc5ae4fb7a91cc87adcce02ef": "refs/heads/jv-conflict-1",
+ "bd493d44ae3c4dd84ce89cb75be78c4708cbd548": "refs/heads/jv-conflict-2",
+ "d23bddc916b96c98ff192e198b1adee0f6871085": "refs/heads/many_files",
+ "0ed8c6c6752e8c6ea63e7b92a517bf5ac1209c80": "refs/heads/markdown",
+ "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9": "refs/tags/v1.0.0",
+ "8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b": "refs/tags/v1.1.0",
+}
+
+func TestSuccessfulListCommitsByRefNameLargeRequest(t *testing.T) {
+ server, serverSocketPath := startTestServices(t)
+ defer server.Stop()
+
+ client, conn := newCommitServiceClient(t, serverSocketPath)
+ defer conn.Close()
+
+ testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
+ defer cleanupFn()
+
+ refNames := [][]byte{}
+ for _, refName := range repositoryRefNames {
+ refNames = append(refNames, []byte(refName))
+ }
+ req := &gitalypb.ListCommitsByRefNameRequest{
+ RefNames: refNames,
+ Repository: testRepo,
+ }
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ c, err := client.ListCommitsByRefName(ctx, req)
+ require.NoError(t, err)
+
+ actualCommits := consumeGetByRefNameResponse(t, c)
+
+ for _, actual := range actualCommits {
+ _, ok := repositoryRefNames[actual.Id]
+ require.True(t, ok, "commit ID must be present in the input list: %s", actual.Id)
+ }
+}