summaryrefslogtreecommitdiff
path: root/internal/api/changestats.go
blob: 0b7010566c7caa854c6b61d4b033dea0a987b33e (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
package api

import (
	"bufio"
	"os"
	"regexp"
	"strconv"
	"strings"

	"github.com/thepeterstone/claudomator/internal/task"
)

// gitDiffStatRe matches git diff --stat summary lines, e.g.:
//
//	"3 files changed, 50 insertions(+), 10 deletions(-)"
//	"1 file changed, 5 insertions(+)"
//	"1 file changed, 3 deletions(-)"
var gitDiffStatRe = regexp.MustCompile(`(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?`)

// parseChangestatFromOutput scans text for git diff --stat summary lines and
// returns the first match as a Changestats value. Returns nil if no match found.
func parseChangestatFromOutput(output string) *task.Changestats {
	scanner := bufio.NewScanner(strings.NewReader(output))
	for scanner.Scan() {
		line := scanner.Text()
		if m := gitDiffStatRe.FindStringSubmatch(line); m != nil {
			cs := &task.Changestats{}
			cs.FilesChanged, _ = strconv.Atoi(m[1])
			if m[2] != "" {
				cs.LinesAdded, _ = strconv.Atoi(m[2])
			}
			if m[3] != "" {
				cs.LinesRemoved, _ = strconv.Atoi(m[3])
			}
			return cs
		}
	}
	return nil
}

// parseChangestatFromFile reads a log file and extracts the first git diff stat
// summary it finds. Returns nil if the file cannot be read or contains no match.
func parseChangestatFromFile(path string) *task.Changestats {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil
	}
	return parseChangestatFromOutput(string(data))
}