85 lines
1.8 kB
1
package git
2
3
import (
4
"fmt"
5
"log"
6
"strings"
7
8
"github.com/bluekeyes/go-gitdiff/gitdiff"
9
"github.com/go-git/go-git/v5/plumbing/object"
10
"github.com/sotangled/tangled/types"
11
)
12
13
func (g *GitRepo) Diff() (*types.NiceDiff, error) {
14
c, err := g.r.CommitObject(g.h)
15
if err != nil {
16
return nil, fmt.Errorf("commit object: %w", err)
17
}
18
19
patch := &object.Patch{}
20
commitTree, err := c.Tree()
21
parent := &object.Commit{}
22
if err == nil {
23
parentTree := &object.Tree{}
24
if c.NumParents() != 0 {
25
parent, err = c.Parents().Next()
26
if err == nil {
27
parentTree, err = parent.Tree()
28
if err == nil {
29
patch, err = parentTree.Patch(commitTree)
30
if err != nil {
31
return nil, fmt.Errorf("patch: %w", err)
32
}
33
}
34
}
35
} else {
36
patch, err = parentTree.Patch(commitTree)
37
if err != nil {
38
return nil, fmt.Errorf("patch: %w", err)
39
}
40
}
41
}
42
43
diffs, _, err := gitdiff.Parse(strings.NewReader(patch.String()))
44
if err != nil {
45
log.Println(err)
46
}
47
48
nd := types.NiceDiff{}
49
nd.Commit.This = c.Hash.String()
50
51
if parent.Hash.IsZero() {
52
nd.Commit.Parent = ""
53
} else {
54
nd.Commit.Parent = parent.Hash.String()
55
}
56
nd.Commit.Author = c.Author
57
nd.Commit.Message = c.Message
58
59
for _, d := range diffs {
60
ndiff := types.Diff{}
61
ndiff.Name.New = d.NewName
62
ndiff.Name.Old = d.OldName
63
ndiff.IsBinary = d.IsBinary
64
ndiff.IsNew = d.IsNew
65
ndiff.IsDelete = d.IsDelete
66
67
for _, tf := range d.TextFragments {
68
ndiff.TextFragments = append(ndiff.TextFragments, *tf)
69
for _, l := range tf.Lines {
70
switch l.Op {
71
case gitdiff.OpAdd:
72
nd.Stat.Insertions += 1
73
case gitdiff.OpDelete:
74
nd.Stat.Deletions += 1
75
}
76
}
77
}
78
79
nd.Diff = append(nd.Diff, ndiff)
80
}
81
82
nd.Stat.FilesChanged = len(diffs)
83
84
return &nd, nil
85
}
86