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:
-rw-r--r--cmd/gitaly-git2go/merge.go74
-rw-r--r--internal/git2go/merge.go3
2 files changed, 76 insertions, 1 deletions
diff --git a/cmd/gitaly-git2go/merge.go b/cmd/gitaly-git2go/merge.go
index 907e717c0..dc9efd808 100644
--- a/cmd/gitaly-git2go/merge.go
+++ b/cmd/gitaly-git2go/merge.go
@@ -12,6 +12,7 @@ import (
"time"
git "github.com/libgit2/git2go/v30"
+ "gitlab.com/gitlab-org/gitaly/cmd/gitaly-git2go/conflicts"
"gitlab.com/gitlab-org/gitaly/internal/git2go"
)
@@ -64,7 +65,13 @@ func (cmd *mergeSubcommand) Run(context.Context, io.Reader, io.Writer) error {
defer index.Free()
if index.HasConflicts() {
- return errors.New("could not auto-merge due to conflicts")
+ if !request.AllowConflicts {
+ return errors.New("could not auto-merge due to conflicts")
+ }
+
+ if err := resolveConflicts(repo, index); err != nil {
+ return fmt.Errorf("could not resolve conflicts: %w", err)
+ }
}
tree, err := index.WriteTreeTo(repo)
@@ -88,3 +95,68 @@ func (cmd *mergeSubcommand) Run(context.Context, io.Reader, io.Writer) error {
return nil
}
+
+func resolveConflicts(repo *git.Repository, index *git.Index) error {
+ // We need to get all conflicts up front as resolving conflicts as we
+ // iterate breaks the iterator.
+ indexConflicts, err := getConflicts(index)
+ if err != nil {
+ return err
+ }
+
+ for _, conflict := range indexConflicts {
+ merge, err := conflicts.Merge(repo, conflict)
+ if err != nil {
+ return err
+ }
+
+ mergedBlob, err := repo.CreateBlobFromBuffer(merge.Contents)
+ if err != nil {
+ return err
+ }
+
+ mergedIndexEntry := git.IndexEntry{
+ Path: merge.Path,
+ Mode: git.Filemode(merge.Mode),
+ Id: mergedBlob,
+ }
+
+ if err := index.Add(&mergedIndexEntry); err != nil {
+ return err
+ }
+
+ if err := index.RemoveConflict(merge.Path); err != nil {
+ return err
+ }
+ }
+
+ if index.HasConflicts() {
+ return errors.New("index still has conflicts")
+ }
+
+ return nil
+}
+
+func getConflicts(index *git.Index) ([]git.IndexConflict, error) {
+ var conflicts []git.IndexConflict
+
+ iterator, err := index.ConflictIterator()
+ if err != nil {
+ return nil, err
+ }
+ defer iterator.Free()
+
+ for {
+ conflict, err := iterator.Next()
+ if err != nil {
+ if git.IsErrorCode(err, git.ErrIterOver) {
+ break
+ }
+ return nil, err
+ }
+
+ conflicts = append(conflicts, conflict)
+ }
+
+ return conflicts, nil
+}
diff --git a/internal/git2go/merge.go b/internal/git2go/merge.go
index 7659930a1..e92856810 100644
--- a/internal/git2go/merge.go
+++ b/internal/git2go/merge.go
@@ -37,6 +37,9 @@ type MergeCommand struct {
Ours string `json:"ours"`
// Theirs is the commit into which ours is to be merged.
Theirs string `json:"theirs"`
+ // AllowConflicts controls whether conflicts are allowed. If they are,
+ // then conflicts will be committed as part of the result.
+ AllowConflicts bool `json:"allow_conflicts"`
}
// MergeResult contains results from a merge.