mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-12 11:15:00 +02:00
156 lines
3.1 KiB
Go
156 lines
3.1 KiB
Go
package mergeconflicts
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/golang-collections/collections/stack"
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
)
|
|
|
|
type State struct {
|
|
sync.Mutex
|
|
|
|
conflicts []*mergeConflict
|
|
// this is the index of the above `conflicts` field which is currently selected
|
|
conflictIndex int
|
|
|
|
// this is the index of the selected conflict's available selections slice e.g. [TOP, MIDDLE, BOTTOM]
|
|
// We use this to know which hunk of the conflict is selected.
|
|
selectionIndex int
|
|
|
|
// this allows us to undo actions
|
|
EditHistory *stack.Stack
|
|
}
|
|
|
|
func NewState() *State {
|
|
return &State{
|
|
Mutex: sync.Mutex{},
|
|
conflictIndex: 0,
|
|
selectionIndex: 0,
|
|
conflicts: []*mergeConflict{},
|
|
EditHistory: stack.New(),
|
|
}
|
|
}
|
|
|
|
func (s *State) setConflictIndex(index int) {
|
|
if len(s.conflicts) == 0 {
|
|
s.conflictIndex = 0
|
|
} else {
|
|
s.conflictIndex = clamp(index, 0, len(s.conflicts)-1)
|
|
}
|
|
s.setSelectionIndex(s.selectionIndex)
|
|
}
|
|
|
|
func (s *State) setSelectionIndex(index int) {
|
|
if selections := s.availableSelections(); len(selections) != 0 {
|
|
s.selectionIndex = clamp(index, 0, len(selections)-1)
|
|
}
|
|
}
|
|
|
|
func (s *State) SelectNextConflictHunk() {
|
|
s.setSelectionIndex(s.selectionIndex + 1)
|
|
}
|
|
|
|
func (s *State) SelectPrevConflictHunk() {
|
|
s.setSelectionIndex(s.selectionIndex - 1)
|
|
}
|
|
|
|
func (s *State) SelectNextConflict() {
|
|
s.setConflictIndex(s.conflictIndex + 1)
|
|
}
|
|
|
|
func (s *State) SelectPrevConflict() {
|
|
s.setConflictIndex(s.conflictIndex - 1)
|
|
}
|
|
|
|
func (s *State) PushFileSnapshot(content string) {
|
|
s.EditHistory.Push(content)
|
|
}
|
|
|
|
func (s *State) PopFileSnapshot() (string, bool) {
|
|
if s.EditHistory.Len() == 0 {
|
|
return "", false
|
|
}
|
|
|
|
return s.EditHistory.Pop().(string), true
|
|
}
|
|
|
|
func (s *State) currentConflict() *mergeConflict {
|
|
if len(s.conflicts) == 0 {
|
|
return nil
|
|
}
|
|
|
|
return s.conflicts[s.conflictIndex]
|
|
}
|
|
|
|
func (s *State) SetConflictsFromCat(cat string) {
|
|
s.setConflicts(findConflicts(cat))
|
|
}
|
|
|
|
func (s *State) setConflicts(conflicts []*mergeConflict) {
|
|
s.conflicts = conflicts
|
|
s.setConflictIndex(s.conflictIndex)
|
|
}
|
|
|
|
func (s *State) NoConflicts() bool {
|
|
return len(s.conflicts) == 0
|
|
}
|
|
|
|
func (s *State) Selection() Selection {
|
|
if selections := s.availableSelections(); len(selections) > 0 {
|
|
return selections[s.selectionIndex]
|
|
}
|
|
return TOP
|
|
}
|
|
|
|
func (s *State) availableSelections() []Selection {
|
|
if conflict := s.currentConflict(); conflict != nil {
|
|
return availableSelections(conflict)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *State) IsFinalConflict() bool {
|
|
return len(s.conflicts) == 1
|
|
}
|
|
|
|
func (s *State) Reset() {
|
|
s.EditHistory = stack.New()
|
|
}
|
|
|
|
func (s *State) GetConflictMiddle() int {
|
|
return s.currentConflict().target
|
|
}
|
|
|
|
func (s *State) ContentAfterConflictResolve(
|
|
path string,
|
|
selection Selection,
|
|
) (bool, string, error) {
|
|
conflict := s.currentConflict()
|
|
if conflict == nil {
|
|
return false, "", nil
|
|
}
|
|
|
|
content := ""
|
|
err := utils.ForEachLineInFile(path, func(line string, i int) {
|
|
if selection.isIndexToKeep(conflict, i) {
|
|
content += line
|
|
}
|
|
})
|
|
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
|
|
return true, content, nil
|
|
}
|
|
|
|
func clamp(x int, min int, max int) int {
|
|
if x < min {
|
|
return min
|
|
} else if x > max {
|
|
return max
|
|
}
|
|
return x
|
|
}
|