Skip to content

Commit 2ea8622

Browse files
author
Juanjo Alvarez
committed
Change blame to use file arg
Signed-off-by: Juanjo Alvarez <[email protected]>
1 parent d3a5cfc commit 2ea8622

File tree

6 files changed

+52
-71
lines changed

6 files changed

+52
-71
lines changed

Diff for: docs/using-gitbase/examples.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,15 @@ The output will be similar to this:
203203
## Get miscelaneous information about lines with a "// TODO" comment in HEAD
204204

205205
```sql
206-
SELECT repository_id,
207-
JSON_UNQUOTE(JSON_EXTRACT(bl, "$.file")),
206+
SELECT repository_id, file_path,
208207
JSON_UNQUOTE(JSON_EXTRACT(bl, "$.linenum")),
209208
JSON_UNQUOTE(JSON_EXTRACT(bl, "$.author")),
210209
JSON_UNQUOTE(JSON_EXTRACT(bl, "$.text"))
211-
FROM (SELECT repository_id,
212-
EXPLODE(BLAME(repository_id, commit_hash)) AS bl
210+
FROM (SELECT repository_id, file_path,
211+
EXPLODE(BLAME(repository_id, commit_hash, file_path)) AS bl
213212
FROM ref_commits
214213
NATURAL JOIN blobs
214+
NATURAL JOIN commit_files
215215
WHERE ref_name = 'HEAD'
216216
AND NOT IS_BINARY(blob_content)
217217
) as p
@@ -225,9 +225,10 @@ SELECT
225225
JSON_UNQUOTE(JSON_EXTRACT(bl, "$.author")),
226226
COUNT(JSON_UNQUOTE(JSON_EXTRACT(bl, "$.author")))
227227

228-
FROM (SELECT EXPLODE(BLAME(repository_id, commit_hash)) AS bl
228+
FROM (SELECT EXPLODE(BLAME(repository_id, commit_hash, file_path)) AS bl
229229
FROM ref_commits
230230
NATURAL JOIN blobs
231+
NATURAL JOIN commit_files
231232
WHERE ref_name = 'HEAD'
232233
AND NOT IS_BINARY(blob_content)
233234
) AS p

Diff for: docs/using-gitbase/functions.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ To make some common tasks easier for the user, there are some functions to inter
66

77
| Name | Description |
88
|:-------------|:-------------------------------------------------------------------------------------------------------------------------------|
9-
|`blame(repository, commit)`|Returns an array of lines changes and authorship. |
9+
|`blame(repository, commit, file)`|Returns an array of lines changes and authorship for the specific file and commit.
1010
|`commit_file_stats(repository_id, [from_commit_hash], to_commit_hash) json array`|returns an array with the stats of each file in `to_commit_hash` since the given `from_commit_hash`. If `from_commit_hash` is not given, the parent commit will be used. Vendored files stats are not included in the result of this function. This function is more thoroughly explained later in this document.|
1111
|`commit_stats(repository_id, [from_commit_hash], to_commit_hash) json`|returns the stats between two commits for a repository. If `from_commit_hash` is empty, it will compare the given `to_commit_hash` with its parent commit. Vendored files stats are not included in the result of this function. This function is more thoroughly explained later in this document.|
1212
|`is_remote(reference_name)bool`| checks if the given reference name is from a remote one. |

Diff for: integration_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -514,12 +514,12 @@ func TestIntegration(t *testing.T) {
514514
SELECT repository_id, JSON_EXTRACT(bl, "$.author"),
515515
COUNT(bl)
516516
FROM (
517-
SELECT repository_id, EXPLODE(BLAME(repository_id, commit_hash)) as bl
517+
SELECT repository_id, EXPLODE(BLAME(repository_id, commit_hash, '.gitignore')) as bl
518518
FROM commits
519519
WHERE commit_hash = '918c48b83bd081e863dbe1b80f8998f058cd8294'
520520
) as p
521521
`,
522-
[]sql.Row{{"worktree", "[email protected]", int64(7235)}},
522+
[]sql.Row{{"worktree", "[email protected]", int64(12)}},
523523
},
524524
}
525525

Diff for: internal/function/blame.go

+21-52
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"fmt"
55
"io"
66

7-
"github.com/sirupsen/logrus"
8-
97
"github.com/src-d/gitbase"
108
"github.com/src-d/go-mysql-server/sql"
119
"gopkg.in/src-d/go-git.v4"
@@ -15,57 +13,27 @@ import (
1513
)
1614

1715
type BlameGenerator struct {
18-
ctx *sql.Context
1916
commit *object.Commit
20-
fIter *object.FileIter
17+
file string
2118
curLine int
22-
curFile *object.File
2319
lines []*git.Line
2420
}
2521

26-
func NewBlameGenerator(ctx *sql.Context, c *object.Commit, f *object.FileIter) (*BlameGenerator, error) {
27-
return &BlameGenerator{ctx: ctx, commit: c, fIter: f, curLine: -1}, nil
28-
}
29-
30-
func (g *BlameGenerator) loadNewFile() error {
31-
var err error
32-
g.curFile, err = g.fIter.Next()
22+
func NewBlameGenerator(c *object.Commit, f string) (*BlameGenerator, error) {
23+
result, err := git.Blame(c, f)
3324
if err != nil {
34-
return err
35-
}
36-
37-
result, err := git.Blame(g.commit, g.curFile.Name)
38-
if err != nil {
39-
msg := fmt.Sprintf(
40-
"Error in BLAME for file %s: %s",
41-
g.curFile.Name,
42-
err.Error(),
43-
)
44-
logrus.Warn(msg)
45-
g.ctx.Warn(0, msg)
46-
return io.EOF
47-
}
48-
49-
if len(result.Lines) == 0 {
50-
return g.loadNewFile()
25+
return nil, err
5126
}
52-
53-
g.lines = result.Lines
54-
g.curLine = 0
55-
return nil
27+
return &BlameGenerator{commit: c, file: f, curLine: 0, lines: result.Lines}, nil
5628
}
5729

5830
func (g *BlameGenerator) Next() (interface{}, error) {
59-
if g.curLine == -1 || g.curLine >= len(g.lines) {
60-
err := g.loadNewFile()
61-
if err != nil {
62-
return nil, err
63-
}
31+
if len(g.lines) == 0 || g.curLine >= len(g.lines) {
32+
return nil, io.EOF
6433
}
6534

6635
l := g.lines[g.curLine]
6736
b := BlameLine{
68-
File: g.curFile.Name,
6937
LineNum: g.curLine,
7038
Author: l.Author,
7139
Text: l.Text,
@@ -75,7 +43,6 @@ func (g *BlameGenerator) Next() (interface{}, error) {
7543
}
7644

7745
func (g *BlameGenerator) Close() error {
78-
g.fIter.Close()
7946
return nil
8047
}
8148

@@ -86,20 +53,20 @@ type (
8653
Blame struct {
8754
repo sql.Expression
8855
commit sql.Expression
56+
file sql.Expression
8957
}
9058

9159
// BlameLine represents each line of git blame's output
9260
BlameLine struct {
93-
File string `json:"file"`
9461
LineNum int `json:"linenum"`
9562
Author string `json:"author"`
9663
Text string `json:"text"`
9764
}
9865
)
9966

10067
// NewBlame constructor
101-
func NewBlame(repo, commit sql.Expression) sql.Expression {
102-
return &Blame{repo, commit}
68+
func NewBlame(repo, commit, file sql.Expression) sql.Expression {
69+
return &Blame{repo, commit, file}
10370
}
10471

10572
func (b *Blame) String() string {
@@ -112,26 +79,26 @@ func (*Blame) Type() sql.Type {
11279
}
11380

11481
func (b *Blame) WithChildren(children ...sql.Expression) (sql.Expression, error) {
115-
if len(children) != 2 {
82+
if len(children) != 3 {
11683
return nil, sql.ErrInvalidChildrenNumber.New(b, len(children), 2)
11784
}
11885

119-
return NewBlame(children[0], children[1]), nil
86+
return NewBlame(children[0], children[1], children[2]), nil
12087
}
12188

12289
// Children implements the Expression interface.
12390
func (b *Blame) Children() []sql.Expression {
124-
return []sql.Expression{b.repo, b.commit}
91+
return []sql.Expression{b.repo, b.commit, b.file}
12592
}
12693

12794
// IsNullable implements the Expression interface.
12895
func (b *Blame) IsNullable() bool {
129-
return b.repo.IsNullable() || (b.commit.IsNullable())
96+
return b.repo.IsNullable() || (b.commit.IsNullable()) || (b.file.IsNullable())
13097
}
13198

13299
// Resolved implements the Expression interface.
133100
func (b *Blame) Resolved() bool {
134-
return b.repo.Resolved() && b.commit.Resolved()
101+
return b.repo.Resolved() && b.commit.Resolved() && b.file.Resolved()
135102
}
136103

137104
// Eval implements the sql.Expression interface.
@@ -151,14 +118,16 @@ func (b *Blame) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
151118
return nil, nil
152119
}
153120

154-
fIter, err := commit.Files()
121+
file, err := exprToString(ctx, b.file, row)
155122
if err != nil {
156-
return nil, err
123+
ctx.Warn(0, err.Error())
124+
return nil, nil
157125
}
158126

159-
bg, err := NewBlameGenerator(ctx, commit, fIter)
127+
bg, err := NewBlameGenerator(commit, file)
160128
if err != nil {
161-
return nil, err
129+
ctx.Warn(0, err.Error())
130+
return nil, nil
162131
}
163132

164133
return bg, nil

Diff for: internal/function/blame_test.go

+21-10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func TestBlameEval(t *testing.T) {
2828
name string
2929
repo sql.Expression
3030
commit sql.Expression
31+
file sql.Expression
3132
row sql.Row
3233
expected BlameLine
3334
expectedNil bool
@@ -38,11 +39,11 @@ func TestBlameEval(t *testing.T) {
3839
name: "init commit",
3940
repo: expression.NewGetField(0, sql.Text, "repository_id", false),
4041
commit: expression.NewGetField(1, sql.Text, "commit_hash", false),
41-
row: sql.NewRow("worktree", "b029517f6300c2da0f4b651b8642506cd6aaf45d"),
42+
file: expression.NewGetField(2, sql.Text, "file", false),
43+
row: sql.NewRow("worktree", "b029517f6300c2da0f4b651b8642506cd6aaf45d", ".gitignore"),
4244
testedLine: 0,
4345
lineCount: 12,
4446
expected: BlameLine{
45-
".gitignore",
4647
0,
4748
4849
"*.class",
@@ -53,11 +54,11 @@ func TestBlameEval(t *testing.T) {
5354
name: "changelog",
5455
repo: expression.NewGetField(0, sql.Text, "repository_id", false),
5556
commit: expression.NewGetField(1, sql.Text, "commit_hash", false),
56-
row: sql.NewRow("worktree", "b8e471f58bcbca63b07bda20e428190409c2db47"),
57+
file: expression.NewGetField(2, sql.Text, "file", false),
58+
row: sql.NewRow("worktree", "b8e471f58bcbca63b07bda20e428190409c2db47", "CHANGELOG"),
5759
testedLine: 0,
5860
lineCount: 1,
5961
expected: BlameLine{
60-
"CHANGELOG",
6162
0,
6263
6364
"Initial changelog",
@@ -68,7 +69,8 @@ func TestBlameEval(t *testing.T) {
6869
name: "no repo",
6970
repo: expression.NewGetField(0, sql.Text, "repository_id", false),
7071
commit: expression.NewGetField(1, sql.Text, "commit_hash", false),
71-
row: sql.NewRow("foo", "bar"),
72+
file: expression.NewGetField(2, sql.Text, "file", false),
73+
row: sql.NewRow("foo", "bar", "baz"),
7274
testedLine: 0,
7375
lineCount: 1,
7476
expected: BlameLine{},
@@ -78,7 +80,19 @@ func TestBlameEval(t *testing.T) {
7880
name: "no commit",
7981
repo: expression.NewGetField(0, sql.Text, "repository_id", false),
8082
commit: expression.NewGetField(1, sql.Text, "commit_hash", false),
81-
row: sql.NewRow("worktree", "foo"),
83+
file: expression.NewGetField(2, sql.Text, "file", false),
84+
row: sql.NewRow("worktree", "foo", "bar"),
85+
testedLine: 0,
86+
lineCount: 1,
87+
expected: BlameLine{},
88+
expectedNil: true,
89+
},
90+
{
91+
name: "no file",
92+
repo: expression.NewGetField(0, sql.Text, "repository_id", false),
93+
commit: expression.NewGetField(1, sql.Text, "commit_hash", false),
94+
file: expression.NewGetField(2, sql.Text, "file", false),
95+
row: sql.NewRow("worktree", "b8e471f58bcbca63b07bda20e428190409c2db47", "foo"),
8296
testedLine: 0,
8397
lineCount: 1,
8498
expected: BlameLine{},
@@ -88,7 +102,7 @@ func TestBlameEval(t *testing.T) {
88102

89103
for _, tc := range testCases {
90104
t.Run(tc.name, func(t *testing.T) {
91-
blame := NewBlame(tc.repo, tc.commit)
105+
blame := NewBlame(tc.repo, tc.commit, tc.file)
92106
blameGen, err := blame.Eval(ctx, tc.row)
93107
require.NoError(t, err)
94108

@@ -105,9 +119,6 @@ func TestBlameEval(t *testing.T) {
105119
lineCount := 0
106120
for i, err := bg.Next(); err == nil; i, err = bg.Next() {
107121
i := i.(BlameLine)
108-
if i.File != tc.expected.File {
109-
continue
110-
}
111122
if lineCount != tc.testedLine {
112123
lineCount++
113124
continue

Diff for: internal/function/registry.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ var Functions = []sql.Function{
1717
sql.Function1{Name: "uast_children", Fn: NewUASTChildren},
1818
sql.Function1{Name: "uast_imports", Fn: NewUASTImports},
1919
sql.Function1{Name: "is_vendor", Fn: NewIsVendor},
20-
sql.Function2{Name: "blame", Fn: NewBlame},
20+
sql.Function3{Name: "blame", Fn: NewBlame},
2121
}

0 commit comments

Comments
 (0)