diff options
Diffstat (limited to 'cmd/gitaly-git2go-v15/cherry_pick_test.go')
-rw-r--r-- | cmd/gitaly-git2go-v15/cherry_pick_test.go | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/cmd/gitaly-git2go-v15/cherry_pick_test.go b/cmd/gitaly-git2go-v15/cherry_pick_test.go new file mode 100644 index 000000000..5902d1fdf --- /dev/null +++ b/cmd/gitaly-git2go-v15/cherry_pick_test.go @@ -0,0 +1,220 @@ +//go:build static && system_libgit2 +// +build static,system_libgit2 + +package main + +import ( + "errors" + "testing" + "time" + + git "github.com/libgit2/git2go/v33" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil" + cmdtesthelper "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/testhelper" + "gitlab.com/gitlab-org/gitaly/v15/internal/git2go" + "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" + "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg" +) + +func TestCherryPick_validation(t *testing.T) { + cfg, repo, repoPath := testcfg.BuildWithRepo(t) + testcfg.BuildGitalyGit2Go(t, cfg) + executor := buildExecutor(t, cfg) + + testcases := []struct { + desc string + request git2go.CherryPickCommand + expectedErr string + }{ + { + desc: "no arguments", + expectedErr: "cherry-pick: missing repository", + }, + { + desc: "missing repository", + request: git2go.CherryPickCommand{CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, + expectedErr: "cherry-pick: missing repository", + }, + { + desc: "missing committer name", + request: git2go.CherryPickCommand{Repository: repoPath, CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, + expectedErr: "cherry-pick: missing committer name", + }, + { + desc: "missing committer mail", + request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, + expectedErr: "cherry-pick: missing committer mail", + }, + { + desc: "missing committer date", + request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, + expectedErr: "cherry-pick: missing committer date", + }, + { + desc: "missing message", + request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Ours: "HEAD", Commit: "HEAD"}, + expectedErr: "cherry-pick: missing message", + }, + { + desc: "missing ours", + request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Commit: "HEAD"}, + expectedErr: "cherry-pick: missing ours", + }, + { + desc: "missing commit", + request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD"}, + expectedErr: "cherry-pick: missing commit", + }, + } + for _, tc := range testcases { + t.Run(tc.desc, func(t *testing.T) { + ctx := testhelper.Context(t) + + _, err := executor.CherryPick(ctx, repo, tc.request) + require.EqualError(t, err, tc.expectedErr) + }) + } +} + +func TestCherryPick(t *testing.T) { + testcases := []struct { + desc string + base map[string]string + ours map[string]string + commit map[string]string + expected map[string]string + expectedCommitID string + expectedErr error + expectedErrMsg string + }{ + { + desc: "trivial cherry-pick succeeds", + base: map[string]string{ + "file": "foo", + }, + ours: map[string]string{ + "file": "foo", + }, + commit: map[string]string{ + "file": "foobar", + }, + expected: map[string]string{ + "file": "foobar", + }, + expectedCommitID: "aa3c9f5ad67ad86e313129a851f6d64614be7f6e", + }, + { + desc: "conflicting cherry-pick fails", + base: map[string]string{ + "file": "foo", + }, + ours: map[string]string{ + "file": "fooqux", + }, + commit: map[string]string{ + "file": "foobar", + }, + expectedErr: git2go.HasConflictsError{}, + expectedErrMsg: "cherry-pick: could not apply due to conflicts", + }, + { + desc: "empty cherry-pick fails", + base: map[string]string{ + "file": "foo", + }, + ours: map[string]string{ + "file": "fooqux", + }, + commit: map[string]string{ + "file": "fooqux", + }, + expectedErr: git2go.EmptyError{}, + expectedErrMsg: "cherry-pick: could not apply because the result was empty", + }, + { + desc: "fails on nonexistent ours commit", + expectedErrMsg: "cherry-pick: ours commit lookup: lookup commit \"nonexistent\": revspec 'nonexistent' not found", + }, + { + desc: "fails on nonexistent cherry-pick commit", + ours: map[string]string{ + "file": "fooqux", + }, + expectedErrMsg: "cherry-pick: commit lookup: lookup commit \"nonexistent\": revspec 'nonexistent' not found", + }, + } + for _, tc := range testcases { + cfg, repo, repoPath := testcfg.BuildWithRepo(t) + testcfg.BuildGitalyGit2Go(t, cfg) + executor := buildExecutor(t, cfg) + + base := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{nil}, tc.base) + + ours, commit := "nonexistent", "nonexistent" + if len(tc.ours) > 0 { + ours = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.ours).String() + } + if len(tc.commit) > 0 { + commit = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.commit).String() + } + + t.Run(tc.desc, func(t *testing.T) { + ctx := testhelper.Context(t) + + committer := git.Signature{ + Name: "Baz", + Email: "baz@example.com", + When: time.Date(2021, 1, 17, 14, 45, 51, 0, time.FixedZone("", +2*60*60)), + } + + response, err := executor.CherryPick(ctx, repo, git2go.CherryPickCommand{ + Repository: repoPath, + CommitterName: committer.Name, + CommitterMail: committer.Email, + CommitterDate: committer.When, + Message: "Foo", + Ours: ours, + Commit: commit, + }) + + if tc.expectedErrMsg != "" { + require.EqualError(t, err, tc.expectedErrMsg) + + if tc.expectedErr != nil { + require.True(t, errors.Is(err, tc.expectedErr)) + } + return + } + + require.NoError(t, err) + assert.Equal(t, tc.expectedCommitID, response.String()) + + repo, err := git2goutil.OpenRepository(repoPath) + require.NoError(t, err) + defer repo.Free() + + commitOid, err := git.NewOid(response.String()) + require.NoError(t, err) + + commit, err := repo.LookupCommit(commitOid) + require.NoError(t, err) + require.Equal(t, &cmdtesthelper.DefaultAuthor, commit.Author()) + require.Equal(t, &committer, commit.Committer()) + + tree, err := commit.Tree() + require.NoError(t, err) + require.Len(t, tc.expected, int(tree.EntryCount())) + + for name, contents := range tc.expected { + entry := tree.EntryByName(name) + require.NotNil(t, entry) + + blob, err := repo.LookupBlob(entry.Id) + require.NoError(t, err) + require.Equal(t, []byte(contents), blob.Contents()) + } + }) + } +} |