1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
package git2go
import (
"bytes"
"context"
"encoding/gob"
"errors"
"fmt"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/repository"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// ConflictsCommand contains parameters to perform a merge and return its conflicts.
type ConflictsCommand struct {
// Repository is the path to execute merge in.
Repository string
// Ours is the commit that is to be merged into theirs.
Ours string
// Theirs is the commit into which ours is to be merged.
Theirs string
}
// ConflictEntry represents a conflict entry which is one of the sides of a conflict.
type ConflictEntry struct {
// Path is the path of the conflicting file.
Path string
// Mode is the mode of the conflicting file.
Mode int32
}
// Conflict represents a merge conflict for a single file.
type Conflict struct {
// Ancestor is the conflict entry of the merge-base.
Ancestor ConflictEntry
// Our is the conflict entry of ours.
Our ConflictEntry
// Their is the conflict entry of theirs.
Their ConflictEntry
// Content contains the conflicting merge results.
Content []byte
}
// ConflictError is an error which happened during conflict resolution.
type ConflictError struct {
// Code is the GRPC error code
Code codes.Code
// Message is the error message
Message string
}
func (e ConflictError) Error() string {
return status.Error(e.Code, e.Message).Error()
}
// ConflictsResult contains all conflicts resulting from a merge.
type ConflictsResult struct {
// Conflicts
Conflicts []Conflict
// Err is set if an error occurred. Err must exist on all gob serialized
// results so that any error can be returned.
//
// Will be a ConflictError when an error occurred with the conflicts
// subcommand.
Err error
}
// Conflicts performs a merge via gitaly-git2go and returns all resulting conflicts.
func (b *Executor) Conflicts(ctx context.Context, repo repository.GitRepo, c ConflictsCommand) (ConflictsResult, error) {
if err := c.verify(); err != nil {
return ConflictsResult{}, fmt.Errorf("conflicts: %w: %s", ErrInvalidArgument, err.Error())
}
input := &bytes.Buffer{}
const cmd = "conflicts"
if err := gob.NewEncoder(input).Encode(c); err != nil {
return ConflictsResult{}, fmt.Errorf("%s: %w", cmd, err)
}
output, err := b.run(ctx, repo, input, cmd)
if err != nil {
return ConflictsResult{}, fmt.Errorf("%s: %w", cmd, err)
}
var result ConflictsResult
if err := gob.NewDecoder(output).Decode(&result); err != nil {
return ConflictsResult{}, fmt.Errorf("%s: %w", cmd, err)
}
var conflictErr ConflictError
switch {
case errors.As(result.Err, &conflictErr):
return ConflictsResult{}, status.Error(conflictErr.Code, conflictErr.Message)
case result.Err != nil:
return ConflictsResult{}, result.Err
}
return result, nil
}
func (c ConflictsCommand) verify() error {
if c.Repository == "" {
return errors.New("missing repository")
}
if c.Ours == "" {
return errors.New("missing ours")
}
if c.Theirs == "" {
return errors.New("missing theirs")
}
return nil
}
|