-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
merge_conflict.go
78 lines (66 loc) · 1.6 KB
/
merge_conflict.go
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
package mergeconflicts
// mergeConflict : A git conflict with a start, ancestor (if exists), target, and end corresponding to line
// numbers in the file where the conflict markers appear.
// If no ancestor is present (i.e. we're not using the diff3 algorithm), then
// the `ancestor` field's value will be -1
type mergeConflict struct {
start int
ancestor int
target int
end int
}
func (c *mergeConflict) hasAncestor() bool {
return c.ancestor >= 0
}
func (c *mergeConflict) isMarkerLine(i int) bool {
return i == c.start ||
i == c.ancestor ||
i == c.target ||
i == c.end
}
type Selection int
const (
TOP Selection = iota
MIDDLE
BOTTOM
ALL
)
func (s Selection) isIndexToKeep(conflict *mergeConflict, i int) bool {
// we're only handling one conflict at a time so any lines outside this
// conflict we'll keep
if i < conflict.start || conflict.end < i {
return true
}
if conflict.isMarkerLine(i) {
return false
}
return s.selected(conflict, i)
}
func (s Selection) bounds(c *mergeConflict) (int, int) {
switch s {
case TOP:
if c.hasAncestor() {
return c.start, c.ancestor
} else {
return c.start, c.target
}
case MIDDLE:
return c.ancestor, c.target
case BOTTOM:
return c.target, c.end
case ALL:
return c.start, c.end
}
panic("unexpected selection for merge conflict")
}
func (s Selection) selected(c *mergeConflict, idx int) bool {
start, end := s.bounds(c)
return start < idx && idx < end
}
func availableSelections(c *mergeConflict) []Selection {
if c.hasAncestor() {
return []Selection{TOP, MIDDLE, BOTTOM}
} else {
return []Selection{TOP, BOTTOM}
}
}