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:
Diffstat (limited to 'internal/git2go/apply_test.go')
-rw-r--r--internal/git2go/apply_test.go217
1 files changed, 217 insertions, 0 deletions
diff --git a/internal/git2go/apply_test.go b/internal/git2go/apply_test.go
new file mode 100644
index 000000000..1744432b6
--- /dev/null
+++ b/internal/git2go/apply_test.go
@@ -0,0 +1,217 @@
+package git2go
+
+import (
+ "errors"
+ "path/filepath"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/internal/command"
+ "gitlab.com/gitlab-org/gitaly/internal/git"
+ "gitlab.com/gitlab-org/gitaly/internal/gitaly/config"
+ "gitlab.com/gitlab-org/gitaly/internal/testhelper"
+)
+
+func TestExecutor_Apply(t *testing.T) {
+ pbRepo, repoPath, clean := testhelper.InitBareRepo(t)
+ defer clean()
+
+ repo := git.NewRepository(pbRepo)
+ executor := New(filepath.Join(config.Config.BinDir, "gitaly-git2go"), command.GitPath())
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ oidBase, err := repo.WriteBlob(ctx, "file", strings.NewReader("base"))
+ require.NoError(t, err)
+
+ oidA, err := repo.WriteBlob(ctx, "file", strings.NewReader("a"))
+ require.NoError(t, err)
+
+ oidB, err := repo.WriteBlob(ctx, "file", strings.NewReader("b"))
+ require.NoError(t, err)
+
+ author := NewSignature("Test Author", "test.author@example.com", time.Now())
+ committer := NewSignature("Test Committer", "test.committer@example.com", time.Now())
+
+ parentCommitSHA, err := executor.Commit(ctx, CommitParams{
+ Repository: repoPath,
+ Author: author,
+ Committer: committer,
+ Message: "base commit",
+ Actions: []Action{CreateFile{Path: "file", OID: oidBase}},
+ })
+ require.NoError(t, err)
+
+ noCommonAncestor, err := executor.Commit(ctx, CommitParams{
+ Repository: repoPath,
+ Author: author,
+ Committer: committer,
+ Message: "commit with ab",
+ Actions: []Action{CreateFile{Path: "file", OID: oidA}},
+ })
+ require.NoError(t, err)
+
+ updateToA, err := executor.Commit(ctx, CommitParams{
+ Repository: repoPath,
+ Author: author,
+ Committer: committer,
+ Message: "commit with a",
+ Parent: parentCommitSHA,
+ Actions: []Action{UpdateFile{Path: "file", OID: oidA}},
+ })
+ require.NoError(t, err)
+
+ updateToB, err := executor.Commit(ctx, CommitParams{
+ Repository: repoPath,
+ Author: author,
+ Committer: committer,
+ Message: "commit to b",
+ Parent: parentCommitSHA,
+ Actions: []Action{UpdateFile{Path: "file", OID: oidB}},
+ })
+ require.NoError(t, err)
+
+ updateFromAToB, err := executor.Commit(ctx, CommitParams{
+ Repository: repoPath,
+ Author: author,
+ Committer: committer,
+ Message: "commit a -> b",
+ Parent: updateToA,
+ Actions: []Action{UpdateFile{Path: "file", OID: oidB}},
+ })
+ require.NoError(t, err)
+
+ otherFile, err := executor.Commit(ctx, CommitParams{
+ Repository: repoPath,
+ Author: author,
+ Committer: committer,
+ Message: "commit with other-file",
+ Actions: []Action{CreateFile{Path: "other-file", OID: oidA}},
+ })
+ require.NoError(t, err)
+
+ diffBetween := func(t testing.TB, fromCommit, toCommit string) []byte {
+ t.Helper()
+ return testhelper.MustRunCommand(t, nil,
+ "git", "-C", repoPath, "format-patch", "--stdout", fromCommit+".."+toCommit)
+ }
+
+ for _, tc := range []struct {
+ desc string
+ patches []Patch
+ parentCommit string
+ tree []testhelper.TreeEntry
+ error error
+ }{
+ {
+ desc: "patch applies cleanly",
+ patches: []Patch{
+ {
+ Author: author,
+ Message: "test commit message",
+ Diff: diffBetween(t, parentCommitSHA, updateToA),
+ },
+ },
+ parentCommit: parentCommitSHA,
+ tree: []testhelper.TreeEntry{
+ {Path: "file", Mode: "100644", Content: "a"},
+ },
+ },
+ {
+ desc: "multiple patches apply cleanly",
+ patches: []Patch{
+ {
+ Author: author,
+ Message: "commit with a",
+ Diff: diffBetween(t, parentCommitSHA, updateToA),
+ },
+ {
+ Author: author,
+ Message: "commit with a -> b",
+ Diff: diffBetween(t, updateToA, updateFromAToB),
+ },
+ },
+ parentCommit: updateToA,
+ tree: []testhelper.TreeEntry{
+ {Path: "file", Mode: "100644", Content: "b"},
+ },
+ },
+ {
+ desc: "three way merged",
+ patches: []Patch{
+ {
+ Author: author,
+ Message: "three-way merged files",
+ Diff: diffBetween(t, parentCommitSHA, otherFile),
+ },
+ },
+ parentCommit: parentCommitSHA,
+ tree: []testhelper.TreeEntry{
+ {Path: "file", Mode: "100644", Content: "base"},
+ {Path: "other-file", Mode: "100644", Content: "a"},
+ },
+ },
+ {
+ // This test asserts incorrect behavior due to a bug in libgit2's
+ // git_apply_to_tree function. The correct behavior would be to
+ // return an error about merge conflict but we currently concatenate
+ // the blobs of the two trees together. This test will fail once the
+ // issue is fixed.
+ //
+ // See: https://gitlab.com/gitlab-org/gitaly/-/issues/3325
+ desc: "no common ancestor",
+ patches: []Patch{
+ {
+ Author: author,
+ Message: "three-way merged file",
+ Diff: diffBetween(t, parentCommitSHA, noCommonAncestor),
+ },
+ },
+ parentCommit: parentCommitSHA,
+ // error: ErrMergeConflict, <- correct output
+ tree: []testhelper.TreeEntry{
+ {Path: "file", Mode: "100644", Content: "abase"},
+ },
+ },
+ {
+ desc: "merge conflict",
+ patches: []Patch{
+ {
+ Author: author,
+ Message: "applies cleanly",
+ Diff: diffBetween(t, parentCommitSHA, updateToA),
+ },
+ {
+ Author: author,
+ Message: "conflicts",
+ Diff: diffBetween(t, parentCommitSHA, updateToB),
+ },
+ },
+ error: ErrMergeConflict,
+ },
+ } {
+ t.Run(tc.desc, func(t *testing.T) {
+ commitID, err := executor.Apply(ctx, ApplyParams{
+ Repository: repoPath,
+ Committer: committer,
+ ParentCommit: parentCommitSHA,
+ Patches: NewSlicePatchIterator(tc.patches),
+ })
+ if tc.error != nil {
+ require.True(t, errors.Is(err, tc.error), err)
+ return
+ }
+
+ require.Equal(t, commit{
+ Parent: tc.parentCommit,
+ Author: author,
+ Committer: committer,
+ Message: tc.patches[len(tc.patches)-1].Message,
+ }, getCommit(t, ctx, repo, commitID))
+ testhelper.RequireTree(t, repoPath, commitID, tc.tree)
+ })
+ }
+}