git/diff.go (view raw)
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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
package git import ( "fmt" "log" "strings" "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/go-git/go-git/v5/plumbing/object" ) type TextFragment struct { Header string Lines []gitdiff.Line } type Diff struct { Name struct { Old string New string } TextFragments []TextFragment IsBinary bool IsNew bool IsDelete bool } // A nicer git diff representation. type NiceDiff struct { Commit struct { Message string Author object.Signature This string Parent string } Stat struct { FilesChanged int Insertions int Deletions int } Diff []Diff } func (g *GitRepo) Diff() (*NiceDiff, error) { c, err := g.r.CommitObject(g.h) if err != nil { return nil, fmt.Errorf("commit object: %w", err) } patch := &object.Patch{} commitTree, err := c.Tree() parent := &object.Commit{} if err == nil { parentTree := &object.Tree{} if c.NumParents() != 0 { parent, err = c.Parents().Next() if err == nil { parentTree, err = parent.Tree() if err == nil { patch, err = parentTree.Patch(commitTree) if err != nil { return nil, fmt.Errorf("patch: %w", err) } } } } else { patch, err = parentTree.Patch(commitTree) if err != nil { return nil, fmt.Errorf("patch: %w", err) } } } diffs, _, err := gitdiff.Parse(strings.NewReader(patch.String())) if err != nil { log.Println(err) } nd := NiceDiff{} nd.Commit.This = c.Hash.String() if parent.Hash.IsZero() { nd.Commit.Parent = "" } else { nd.Commit.Parent = parent.Hash.String() } nd.Commit.Author = c.Author nd.Commit.Message = c.Message for _, d := range diffs { ndiff := Diff{} ndiff.Name.New = d.NewName ndiff.Name.Old = d.OldName ndiff.IsBinary = d.IsBinary ndiff.IsNew = d.IsNew ndiff.IsDelete = d.IsDelete for _, tf := range d.TextFragments { ndiff.TextFragments = append(ndiff.TextFragments, TextFragment{ Header: tf.Header(), Lines: tf.Lines, }) for _, l := range tf.Lines { switch l.Op { case gitdiff.OpAdd: nd.Stat.Insertions += 1 case gitdiff.OpDelete: nd.Stat.Deletions += 1 } } } nd.Diff = append(nd.Diff, ndiff) } nd.Stat.FilesChanged = len(diffs) return &nd, nil } |