@@ -3,13 +3,68 @@ package function
3
3
import (
4
4
"fmt"
5
5
"github.com/src-d/gitbase"
6
- "gopkg.in/src-d/go-git.v4"
7
6
"github.com/src-d/go-mysql-server/sql"
7
+ "gopkg.in/src-d/go-git.v4"
8
8
9
9
"gopkg.in/src-d/go-git.v4/plumbing"
10
10
"gopkg.in/src-d/go-git.v4/plumbing/object"
11
11
)
12
12
13
+ type BlameGenerator struct {
14
+ commit * object.Commit
15
+ fIter * object.FileIter
16
+ curLine int
17
+ curFile * object.File
18
+ lines []* git.Line
19
+ }
20
+
21
+ func NewBlameGenerator (c * object.Commit , f * object.FileIter ) (* BlameGenerator , error ) {
22
+ return & BlameGenerator {commit : c , fIter : f , curLine : - 1 }, nil
23
+ }
24
+
25
+ func (g * BlameGenerator ) loadNewFile () error {
26
+ var err error
27
+ g .curFile , err = g .fIter .Next ()
28
+ if err != nil {
29
+ return err
30
+ }
31
+
32
+ result , err := git .Blame (g .commit , g .curFile .Name )
33
+ if err != nil {
34
+ return err
35
+ }
36
+ g .lines = result .Lines
37
+ g .curLine = 0
38
+ return nil
39
+ }
40
+
41
+ func (g * BlameGenerator ) Next () (interface {}, error ) {
42
+ if g .curLine == - 1 || g .curLine >= len (g .lines ) {
43
+ err := g .loadNewFile ()
44
+ if err != nil {
45
+ return nil , err
46
+ }
47
+ }
48
+
49
+ l := g .lines [g .curLine ]
50
+ b := BlameLine {
51
+ Commit : g .commit .Hash .String (),
52
+ File : g .curFile .Name ,
53
+ LineNum : g .curLine ,
54
+ Author : l .Author ,
55
+ Text : l .Text ,
56
+ }
57
+ g .curLine ++
58
+ return b , nil
59
+ }
60
+
61
+ func (g * BlameGenerator ) Close () error {
62
+ g .fIter .Close ()
63
+ return nil
64
+ }
65
+
66
+ var _ sql.Generator = (* BlameGenerator )(nil )
67
+
13
68
type (
14
69
// Blame implements git-blame function as UDF
15
70
Blame struct {
@@ -83,27 +138,13 @@ func (b *Blame) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
83
138
if err != nil {
84
139
return nil , err
85
140
}
86
- defer fIter .Close ()
87
141
88
- var lines []BlameLine
89
- for f , err := fIter .Next (); err == nil ; f , err = fIter .Next () {
90
- result , err := git .Blame (commit , f .Name )
91
- if err != nil {
92
- return nil , err
93
- }
94
-
95
- for i , l := range result .Lines {
96
- lines = append (lines , BlameLine {
97
- Commit : commit .Hash .String (),
98
- File : f .Name ,
99
- LineNum : i ,
100
- Author : l .Author ,
101
- Text : l .Text ,
102
- })
103
- }
142
+ bg , err := NewBlameGenerator (commit , fIter )
143
+ if err != nil {
144
+ return nil , err
104
145
}
105
146
106
- return lines , nil
147
+ return bg , nil
107
148
}
108
149
109
150
func (b * Blame ) resolveCommit (ctx * sql.Context , repo * gitbase.Repository , row sql.Row ) (* object.Commit , error ) {
0 commit comments