1package repository
2
3import (
4	"testing"
5
6	"github.com/stretchr/testify/require"
7	"gitlab.com/gitlab-org/gitaly/v14/internal/git"
8	"gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest"
9	"gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo"
10	"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
11	"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
12	"google.golang.org/grpc/codes"
13)
14
15func TestFetchSourceBranchSourceRepositorySuccess(t *testing.T) {
16	cfg, sourceRepo, sourcePath, client := setupRepositoryService(t)
17
18	ctx, cancel := testhelper.Context()
19	defer cancel()
20
21	md := testhelper.GitalyServersMetadataFromCfg(t, cfg)
22	ctx = testhelper.MergeOutgoingMetadata(ctx, md)
23
24	targetRepoProto, _, cleanup := gittest.CloneRepoAtStorage(t, cfg, cfg.Storages[0], "fetch-source-target.git")
25	defer cleanup()
26	targetRepo := localrepo.NewTestRepo(t, cfg, targetRepoProto)
27
28	sourceBranch := "fetch-source-branch-test-branch"
29	newCommitID := gittest.WriteCommit(t, cfg, sourcePath, gittest.WithBranch(sourceBranch))
30
31	targetRef := "refs/tmp/fetch-source-branch-test"
32	req := &gitalypb.FetchSourceBranchRequest{
33		Repository:       targetRepoProto,
34		SourceRepository: sourceRepo,
35		SourceBranch:     []byte(sourceBranch),
36		TargetRef:        []byte(targetRef),
37	}
38
39	resp, err := client.FetchSourceBranch(ctx, req)
40	require.NoError(t, err)
41	require.True(t, resp.Result, "response.Result should be true")
42
43	fetchedCommit, err := targetRepo.ReadCommit(ctx, git.Revision(targetRef))
44	require.NoError(t, err)
45	require.Equal(t, newCommitID.String(), fetchedCommit.GetId())
46}
47
48func TestFetchSourceBranchSameRepositorySuccess(t *testing.T) {
49	cfg, repoProto, repoPath, client := setupRepositoryService(t)
50
51	ctx, cancel := testhelper.Context()
52	defer cancel()
53
54	md := testhelper.GitalyServersMetadataFromCfg(t, cfg)
55	ctx = testhelper.MergeOutgoingMetadata(ctx, md)
56
57	repo := localrepo.NewTestRepo(t, cfg, repoProto)
58
59	sourceBranch := "fetch-source-branch-test-branch"
60	newCommitID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch(sourceBranch))
61
62	targetRef := "refs/tmp/fetch-source-branch-test"
63	req := &gitalypb.FetchSourceBranchRequest{
64		Repository:       repoProto,
65		SourceRepository: repoProto,
66		SourceBranch:     []byte(sourceBranch),
67		TargetRef:        []byte(targetRef),
68	}
69
70	resp, err := client.FetchSourceBranch(ctx, req)
71	require.NoError(t, err)
72	require.True(t, resp.Result, "response.Result should be true")
73
74	fetchedCommit, err := repo.ReadCommit(ctx, git.Revision(targetRef))
75	require.NoError(t, err)
76	require.Equal(t, newCommitID.String(), fetchedCommit.GetId())
77}
78
79func TestFetchSourceBranchBranchNotFound(t *testing.T) {
80	cfg, targetRepo, _, client := setupRepositoryService(t)
81
82	ctx, cancel := testhelper.Context()
83	defer cancel()
84
85	md := testhelper.GitalyServersMetadataFromCfg(t, cfg)
86	ctx = testhelper.MergeOutgoingMetadata(ctx, md)
87
88	sourceRepo, _, cleanup := gittest.CloneRepoAtStorage(t, cfg, cfg.Storages[0], "fetch-source-source.git")
89	t.Cleanup(cleanup)
90
91	sourceBranch := "does-not-exist"
92	targetRef := "refs/tmp/fetch-source-branch-test"
93
94	testCases := []struct {
95		req  *gitalypb.FetchSourceBranchRequest
96		desc string
97	}{
98		{
99			desc: "target different from source",
100			req: &gitalypb.FetchSourceBranchRequest{
101				Repository:       targetRepo,
102				SourceRepository: sourceRepo,
103				SourceBranch:     []byte(sourceBranch),
104				TargetRef:        []byte(targetRef),
105			},
106		},
107		{
108			desc: "target same as source",
109			req: &gitalypb.FetchSourceBranchRequest{
110				Repository:       sourceRepo,
111				SourceRepository: sourceRepo,
112				SourceBranch:     []byte(sourceBranch),
113				TargetRef:        []byte(targetRef),
114			},
115		},
116	}
117
118	for _, tc := range testCases {
119		t.Run(tc.desc, func(t *testing.T) {
120			resp, err := client.FetchSourceBranch(ctx, tc.req)
121			require.NoError(t, err)
122			require.False(t, resp.Result, "response.Result should be false")
123		})
124	}
125}
126
127func TestFetchSourceBranchWrongRef(t *testing.T) {
128	cfg, targetRepo, _, client := setupRepositoryService(t)
129
130	ctx, cancel := testhelper.Context()
131	defer cancel()
132
133	md := testhelper.GitalyServersMetadataFromCfg(t, cfg)
134	ctx = testhelper.MergeOutgoingMetadata(ctx, md)
135
136	sourceRepo, sourceRepoPath, cleanup := gittest.CloneRepoAtStorage(t, cfg, cfg.Storages[0], "fetch-source-source.git")
137	defer cleanup()
138
139	sourceBranch := "fetch-source-branch-testmas-branch"
140	gittest.WriteCommit(t, cfg, sourceRepoPath, gittest.WithBranch(sourceBranch))
141
142	targetRef := "refs/tmp/fetch-source-branch-test"
143
144	testCases := []struct {
145		req  *gitalypb.FetchSourceBranchRequest
146		desc string
147	}{
148		{
149			desc: "source branch empty",
150			req: &gitalypb.FetchSourceBranchRequest{
151				Repository:       targetRepo,
152				SourceRepository: sourceRepo,
153				SourceBranch:     []byte(""),
154				TargetRef:        []byte(targetRef),
155			},
156		},
157		{
158			desc: "source branch blank",
159			req: &gitalypb.FetchSourceBranchRequest{
160				Repository:       targetRepo,
161				SourceRepository: sourceRepo,
162				SourceBranch:     []byte("   "),
163				TargetRef:        []byte(targetRef),
164			},
165		},
166		{
167			desc: "source branch starts with -",
168			req: &gitalypb.FetchSourceBranchRequest{
169				Repository:       targetRepo,
170				SourceRepository: sourceRepo,
171				SourceBranch:     []byte("-ref"),
172				TargetRef:        []byte(targetRef),
173			},
174		},
175		{
176			desc: "source branch with :",
177			req: &gitalypb.FetchSourceBranchRequest{
178				Repository:       targetRepo,
179				SourceRepository: sourceRepo,
180				SourceBranch:     []byte("some:ref"),
181				TargetRef:        []byte(targetRef),
182			},
183		},
184		{
185			desc: "source branch with NULL",
186			req: &gitalypb.FetchSourceBranchRequest{
187				Repository:       targetRepo,
188				SourceRepository: sourceRepo,
189				SourceBranch:     []byte("some\x00ref"),
190				TargetRef:        []byte(targetRef),
191			},
192		},
193		{
194			desc: "target branch empty",
195			req: &gitalypb.FetchSourceBranchRequest{
196				Repository:       targetRepo,
197				SourceRepository: sourceRepo,
198				SourceBranch:     []byte(sourceBranch),
199				TargetRef:        []byte(""),
200			},
201		},
202		{
203			desc: "target branch blank",
204			req: &gitalypb.FetchSourceBranchRequest{
205				Repository:       targetRepo,
206				SourceRepository: sourceRepo,
207				SourceBranch:     []byte(sourceBranch),
208				TargetRef:        []byte("   "),
209			},
210		},
211		{
212			desc: "target branch starts with -",
213			req: &gitalypb.FetchSourceBranchRequest{
214				Repository:       targetRepo,
215				SourceRepository: sourceRepo,
216				SourceBranch:     []byte(sourceBranch),
217				TargetRef:        []byte("-ref"),
218			},
219		},
220		{
221			desc: "target branch with :",
222			req: &gitalypb.FetchSourceBranchRequest{
223				Repository:       targetRepo,
224				SourceRepository: sourceRepo,
225				SourceBranch:     []byte(sourceBranch),
226				TargetRef:        []byte("some:ref"),
227			},
228		},
229		{
230			desc: "target branch with NULL",
231			req: &gitalypb.FetchSourceBranchRequest{
232				Repository:       targetRepo,
233				SourceRepository: sourceRepo,
234				SourceBranch:     []byte(sourceBranch),
235				TargetRef:        []byte("some\x00ref"),
236			},
237		},
238	}
239
240	for _, tc := range testCases {
241		t.Run(tc.desc, func(t *testing.T) {
242			_, err := client.FetchSourceBranch(ctx, tc.req)
243			testhelper.RequireGrpcError(t, err, codes.InvalidArgument)
244		})
245	}
246}
247