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:
authorKarthik Nayak <knayak@gitlab.com>2023-05-03 10:30:25 +0300
committerKarthik Nayak <knayak@gitlab.com>2023-05-03 10:30:25 +0300
commit6b6e6257b546748c771768f631cde0b75ae03e72 (patch)
tree05a252fdcc19960b2b8860dfcf4954e1032a3f98
parentd96505953555659c8475fe48d1386331f3b37f73 (diff)
-rw-r--r--internal/git/localrepo/merge.go39
-rw-r--r--internal/git/localrepo/merge_test.go24
2 files changed, 47 insertions, 16 deletions
diff --git a/internal/git/localrepo/merge.go b/internal/git/localrepo/merge.go
index f34aa52a6..d0b67cc7b 100644
--- a/internal/git/localrepo/merge.go
+++ b/internal/git/localrepo/merge.go
@@ -101,9 +101,7 @@ func (repo *Repo) MergeTree(
if exitCode > 1 {
if text.ChompBytes(stderr.Bytes()) == "fatal: refusing to merge unrelated histories" {
- return "", &MergeTreeError{
- InfoMessage: "unrelated histories",
- }
+ return "", &MergeTreeError{}
}
return "", fmt.Errorf("merge-tree: %w", err)
}
@@ -141,8 +139,6 @@ func parseMergeTreeError(objectHash git.ObjectHash, cfg mergeTreeConfig, output
return "", fmt.Errorf("hex to oid: %w", err)
}
- mergeTreeError.InfoMessage = strings.TrimSuffix(infoMsg, "\x00")
-
mergeTreeError.ConflictingFileInfo = make([]ConflictingFileInfo, len(oidAndConflicts[1:]))
// From git-merge-tree(1), the information is of the format `<mode> <object> <stage> <filename>`
@@ -181,6 +177,31 @@ func parseMergeTreeError(objectHash git.ObjectHash, cfg mergeTreeConfig, output
}
}
+ fields := strings.Split(infoMsg, "\x00")
+ // The git output contains a null characted at the end, which creates a stray empty field.
+ fields = fields[:len(fields)-1]
+
+ for i := 0; i < len(fields); {
+ c := ConflictInfoMessage{}
+
+ numOfPaths, err := strconv.Atoi(fields[i])
+ if err != nil {
+ return "", fmt.Errorf("converting stage to int: %w", err)
+ }
+
+ if i+numOfPaths+2 > len(fields) {
+ return "", fmt.Errorf("incorrect number of fields: %s", infoMsg)
+ }
+
+ c.Paths = fields[i+1 : i+numOfPaths+1]
+ c.Type = fields[i+numOfPaths+1]
+ c.Message = fields[i+numOfPaths+2]
+
+ mergeTreeError.ConflictInfoMessage = append(mergeTreeError.ConflictInfoMessage, c)
+
+ i = i + numOfPaths + 3
+ }
+
return oid, &mergeTreeError
}
@@ -191,11 +212,17 @@ type ConflictingFileInfo struct {
Stage MergeStage
}
+type ConflictInfoMessage struct {
+ Paths []string
+ Type string
+ Message string
+}
+
// MergeTreeError encapsulates any conflicting file info and messages that occur
// when a merge-tree(1) command fails.
type MergeTreeError struct {
ConflictingFileInfo []ConflictingFileInfo
- InfoMessage string
+ ConflictInfoMessage []ConflictInfoMessage
}
// Error returns the error string for a conflict error.
diff --git a/internal/git/localrepo/merge_test.go b/internal/git/localrepo/merge_test.go
index ede6456b8..3a8e78c42 100644
--- a/internal/git/localrepo/merge_test.go
+++ b/internal/git/localrepo/merge_test.go
@@ -95,10 +95,8 @@ func TestMergeTree(t *testing.T) {
},
},
{
- desc: "no shared ancestors",
- expectedErr: &MergeTreeError{
- InfoMessage: "unrelated histories",
- },
+ desc: "no shared ancestors",
+ expectedErr: &MergeTreeError{},
setupFunc: func(t *testing.T, ctx context.Context, repoPath string) (git.ObjectID, git.ObjectID, []gittest.TreeEntry) {
tree1 := gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{
{
@@ -138,7 +136,6 @@ func TestMergeTree(t *testing.T) {
Stage: 0,
},
},
- InfoMessage: "1\x00file2\x00Auto-merging\x00Auto-merging file2\n\x001\x00file2\x00CONFLICT (contents)\x00CONFLICT (add/add): Merge conflict in file2\n",
},
setupFunc: func(t *testing.T, ctx context.Context, repoPath string) (git.ObjectID, git.ObjectID, []gittest.TreeEntry) {
tree1 := gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{
@@ -321,7 +318,18 @@ func TestParseResult(t *testing.T) {
Stage: MergeStageTheirs,
},
},
- InfoMessage: "1\x00a\x00Auto-merging\x00Auto-merging a\n\x001\x00a\x00CONFLICT (contents)\x00CONFLICT (content): Merge conflict in a\n",
+ ConflictInfoMessage: []ConflictInfoMessage{
+ {
+ Paths: []string{"a"},
+ Type: "Auto-merging",
+ Message: "Auto-merging a\n",
+ },
+ {
+ Paths: []string{"a"},
+ Type: "CONFLICT (contents)",
+ Message: "CONFLICT (content): Merge conflict in a\n",
+ },
+ },
},
},
{
@@ -361,7 +369,6 @@ func TestParseResult(t *testing.T) {
Stage: MergeStageTheirs,
},
},
- InfoMessage: "1\x00a\x00Auto-merging\x00Auto-merging a\n\x001\x00a\x00CONFLICT (contents)\x00CONFLICT (content): Merge conflict in a\n",
},
},
{
@@ -399,7 +406,6 @@ func TestParseResult(t *testing.T) {
Stage: MergeStageTheirs,
},
},
- InfoMessage: "3\x00a\x00c\x00d\x00CONFLICT (rename/rename)\x00CONFLICT (rename/rename): a renamed to c in @ and to d in master.\n",
},
},
{
@@ -459,7 +465,6 @@ func TestParseResult(t *testing.T) {
Stage: MergeStageTheirs,
},
},
- InfoMessage: "1\x00a\x00Auto-merging\x00Auto-merging a\n\x001\x00a\x00CONFLICT (contents)\x00CONFLICT (content): Merge conflict in a\n\x001\x00b\x00Auto-merging\x00Auto-merging b\n\x001\x00b\x00CONFLICT (contents)\x00CONFLICT (content): Merge conflict in b\n",
},
},
{
@@ -509,7 +514,6 @@ func TestParseResult(t *testing.T) {
Stage: MergeStageTheirs,
},
},
- InfoMessage: "1\x00a\x00CONFLICT (modify/delete)\x00CONFLICT (modify/delete): a deleted in @ and modified in master. Version master of a left in tree.\n\x001\x00b\x00Auto-merging\x00Auto-merging b\n\x001\x00b\x00CONFLICT (contents)\x00CONFLICT (content): Merge conflict in b\n",
},
},
{