summaryrefslogtreecommitdiffstats
path: root/pkg/commands/patch/parse.go
blob: fee7d291814920545fb64cfb7ad7926d52451f6a (plain)
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
package patch

import (
	"regexp"
	"strings"

	"github.com/jesseduffield/lazygit/pkg/utils"
)

var hunkHeaderRegexp = regexp.MustCompile(`(?m)^@@ -(\d+)[^\+]+\+(\d+)[^@]+@@(.*)$`)

func Parse(patchStr string) *Patch {
	// ignore trailing newline.
	lines := strings.Split(strings.TrimSuffix(patchStr, "\n"), "\n")

	hunks := []*Hunk{}
	patchHeader := []string{}

	var currentHunk *Hunk
	for _, line := range lines {
		if strings.HasPrefix(line, "@@") {
			oldStart, newStart, headerContext := headerInfo(line)

			currentHunk = &Hunk{
				oldStart:      oldStart,
				newStart:      newStart,
				headerContext: headerContext,
				bodyLines:     []*PatchLine{},
			}
			hunks = append(hunks, currentHunk)
		} else if currentHunk != nil {
			currentHunk.bodyLines = append(currentHunk.bodyLines, newHunkLine(line))
		} else {
			patchHeader = append(patchHeader, line)
		}
	}

	return &Patch{
		hunks:  hunks,
		header: patchHeader,
	}
}

func headerInfo(header string) (int, int, string) {
	match := hunkHeaderRegexp.FindStringSubmatch(header)

	oldStart := utils.MustConvertToInt(match[1])
	newStart := utils.MustConvertToInt(match[2])
	headerContext := match[3]

	return oldStart, newStart, headerContext
}

func newHunkLine(line string) *PatchLine {
	if line == "" {
		return &PatchLine{
			Kind:    CONTEXT,
			Content: "",
		}
	}

	firstChar := line[:1]

	kind := parseFirstChar(firstChar)

	return &PatchLine{
		Kind:    kind,
		Content: line,
	}
}

func parseFirstChar(firstChar string) PatchLineKind {
	switch firstChar {
	case " ":
		return CONTEXT
	case "+":
		return ADDITION
	case "-":
		return DELETION
	case "\\":
		return NEWLINE_MESSAGE
	}

	return CONTEXT
}