1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-12 11:15:00 +02:00
lazygit/pkg/gui/mergeconflicts/find_conflicts.go

116 lines
2.6 KiB
Go
Raw Normal View History

2021-05-30 07:22:04 +02:00
package mergeconflicts
import (
2022-01-25 16:20:19 +02:00
"bufio"
"bytes"
"io"
"os"
2021-05-30 07:22:04 +02:00
"strings"
"github.com/jesseduffield/lazygit/pkg/utils"
)
// LineType tells us whether a given line is a start/middle/end marker of a conflict,
// or if it's not a marker at all
type LineType int
const (
START LineType = iota
ANCESTOR
TARGET
2021-05-30 07:22:04 +02:00
END
NOT_A_MARKER
)
func findConflicts(content string) []*mergeConflict {
conflicts := make([]*mergeConflict, 0)
if content == "" {
return conflicts
}
var newConflict *mergeConflict
for i, line := range utils.SplitLines(content) {
switch determineLineType(line) {
case START:
newConflict = &mergeConflict{start: i, ancestor: -1}
case ANCESTOR:
2021-08-21 11:34:30 +02:00
if newConflict != nil {
newConflict.ancestor = i
}
case TARGET:
if newConflict != nil {
newConflict.target = i
2021-08-21 11:34:30 +02:00
}
2021-05-30 07:22:04 +02:00
case END:
2021-08-21 11:34:30 +02:00
if newConflict != nil {
newConflict.end = i
conflicts = append(conflicts, newConflict)
}
2021-06-02 19:53:01 +02:00
// reset value to avoid any possible silent mutations in further iterations
newConflict = nil
2021-05-30 07:22:04 +02:00
default:
// line isn't a merge conflict marker so we just continue
}
}
return conflicts
}
2022-01-25 16:20:19 +02:00
var CONFLICT_START = "<<<<<<< "
var CONFLICT_END = ">>>>>>> "
var CONFLICT_START_BYTES = []byte(CONFLICT_START)
var CONFLICT_END_BYTES = []byte(CONFLICT_END)
2021-05-30 07:22:04 +02:00
func determineLineType(line string) LineType {
2022-01-25 16:20:19 +02:00
// TODO: find out whether we ever actually get this prefix
2021-05-30 07:22:04 +02:00
trimmedLine := strings.TrimPrefix(line, "++")
2021-06-05 05:30:55 +02:00
switch {
2022-01-25 16:20:19 +02:00
case strings.HasPrefix(trimmedLine, CONFLICT_START):
2021-06-05 05:30:55 +02:00
return START
case strings.HasPrefix(trimmedLine, "||||||| "):
return ANCESTOR
2021-06-05 05:30:55 +02:00
case trimmedLine == "=======":
return TARGET
2022-01-25 16:20:19 +02:00
case strings.HasPrefix(trimmedLine, CONFLICT_END):
2021-06-05 05:30:55 +02:00
return END
default:
return NOT_A_MARKER
2021-05-30 07:22:04 +02:00
}
}
2022-01-25 16:20:19 +02:00
// tells us whether a file actually has inline merge conflicts. We need to run this
// because git will continue showing a status of 'UU' even after the conflicts have
// been resolved in the user's editor
func FileHasConflictMarkers(path string) (bool, error) {
file, err := os.Open(path)
if err != nil {
return false, err
}
defer file.Close()
return fileHasConflictMarkersAux(file), nil
}
// Efficiently scans through a file looking for merge conflict markers. Returns true if it does
func fileHasConflictMarkersAux(file io.Reader) bool {
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
line := scanner.Bytes()
// only searching for start/end markers because the others are more ambiguous
if bytes.HasPrefix(line, CONFLICT_START_BYTES) {
return true
}
if bytes.HasPrefix(line, CONFLICT_END_BYTES) {
return true
}
}
return false
}