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