summaryrefslogtreecommitdiff
path: root/internal/git/compare.go
blob: 4b8f120796af316d612a17e311fa03b0d3b44703 (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
package git

import (
	"fmt"
	"strconv"
	"strings"
	"time"
)

func CompareDiff(base, head, repoDir string) (string, error) {
	out, err := gitCmd(repoDir, "diff", base+"..."+head)
	if err != nil {
		return "", err
	}
	return string(out), nil
}

func CompareCommits(base, head Ref, repoDir string) ([]Commit, error) {
	format := []string{"%H", "%h", "%s", "%b", "%an", "%ae", "%ad", "%cn", "%ce", "%cd", "%P", "%D"}
	out, err := gitCmd(repoDir,
		"log",
		"--date=unix",
		"--pretty=format:"+strings.Join(format, "\x1F"),
		"-z",
		base.String()+".."+head.String(),
	)
	if err != nil {
		return nil, err
	}

	lines := strings.Split(string(out), "\x00")
	commits := make([]Commit, 0, len(lines))
	for _, line := range lines {
		if line == "" {
			continue
		}
		parts := strings.Split(line, "\x1F")
		if len(parts) != len(format) {
			return nil, fmt.Errorf("unexpected commit format: %s", line)
		}
		full, short, subject, body, author, email, date :=
			parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6]
		committerName, committerEmail, committerDate, parents, refs :=
			parts[7], parts[8], parts[9], parts[10], parts[11]

		timestampInt, err := strconv.Atoi(date)
		if err != nil {
			return nil, fmt.Errorf("failed to parse commit date: %w", err)
		}
		committerTimestampInt, err := strconv.Atoi(committerDate)
		if err != nil {
			return nil, fmt.Errorf("failed to parse committer date: %w", err)
		}
		commits = append(commits, Commit{
			Hash:           full,
			ShortHash:      short,
			Subject:        subject,
			Body:           body,
			Author:         author,
			Email:          email,
			Date:           time.Unix(int64(timestampInt), 0),
			CommitterName:  committerName,
			CommitterEmail: committerEmail,
			CommitterDate:  time.Unix(int64(committerTimestampInt), 0),
			Parents:        strings.Fields(parents),
			RefNames:       parseRefNames(refs),
		})
	}
	return commits, nil
}