forked from
tangled.org/core
Monorepo for Tangled — https://tangled.org
1package git
2
3import (
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
13func (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, types.TextFragment{
69 Header: tf.Header(),
70 Lines: tf.Lines,
71 })
72 for _, l := range tf.Lines {
73 switch l.Op {
74 case gitdiff.OpAdd:
75 nd.Stat.Insertions += 1
76 case gitdiff.OpDelete:
77 nd.Stat.Deletions += 1
78 }
79 }
80 }
81
82 nd.Diff = append(nd.Diff, ndiff)
83 }
84
85 nd.Stat.FilesChanged = len(diffs)
86
87 return &nd, nil
88}