main
1package git
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7 "time"
8)
9
10func CompareDiff(base, head, repoDir string) (string, error) {
11 out, err := gitCmd(repoDir, "diff", base+"..."+head)
12 if err != nil {
13 return "", err
14 }
15 return string(out), nil
16}
17
18func CompareCommits(base, head Ref, repoDir string) ([]Commit, error) {
19 format := []string{"%H", "%h", "%s", "%b", "%an", "%ae", "%ad", "%cn", "%ce", "%cd", "%P", "%D"}
20 out, err := gitCmd(repoDir,
21 "log",
22 "--date=unix",
23 "--pretty=format:"+strings.Join(format, "\x1F"),
24 "-z",
25 base.String()+".."+head.String(),
26 )
27 if err != nil {
28 return nil, err
29 }
30
31 lines := strings.Split(string(out), "\x00")
32 commits := make([]Commit, 0, len(lines))
33 for _, line := range lines {
34 if line == "" {
35 continue
36 }
37 parts := strings.Split(line, "\x1F")
38 if len(parts) != len(format) {
39 return nil, fmt.Errorf("unexpected commit format: %s", line)
40 }
41 full, short, subject, body, author, email, date :=
42 parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6]
43 committerName, committerEmail, committerDate, parents, refs :=
44 parts[7], parts[8], parts[9], parts[10], parts[11]
45
46 timestampInt, err := strconv.Atoi(date)
47 if err != nil {
48 return nil, fmt.Errorf("failed to parse commit date: %w", err)
49 }
50 committerTimestampInt, err := strconv.Atoi(committerDate)
51 if err != nil {
52 return nil, fmt.Errorf("failed to parse committer date: %w", err)
53 }
54 commits = append(commits, Commit{
55 Hash: full,
56 ShortHash: short,
57 Subject: subject,
58 Body: body,
59 Author: author,
60 Email: email,
61 Date: time.Unix(int64(timestampInt), 0),
62 CommitterName: committerName,
63 CommitterEmail: committerEmail,
64 CommitterDate: time.Unix(int64(committerTimestampInt), 0),
65 Parents: strings.Fields(parents),
66 RefNames: parseRefNames(refs),
67 })
68 }
69 return commits, nil
70}