6
6
//
7
7
// This package also provides a pretty print function to output the
8
8
// results of a blame in a similar format to the git-blame command.
9
- package blame
9
+ package git
10
10
11
11
import (
12
12
"bytes"
@@ -16,14 +16,18 @@ import (
16
16
"strings"
17
17
"unicode/utf8"
18
18
19
- "gopkg.in/src-d/go-git.v2"
20
19
"gopkg.in/src-d/go-git.v2/core"
21
20
"gopkg.in/src-d/go-git.v2/diff"
22
- "gopkg.in/src-d/go-git.v2/revlist"
23
21
)
24
22
25
- // Blame returns the last commit that modified each line of a file in
26
- // a repository.
23
+ type Blame struct {
24
+ Path string
25
+ Rev core.Hash
26
+ Lines []* line
27
+ }
28
+
29
+ // Blame returns the last commit that modified each line of a file in a
30
+ // repository.
27
31
//
28
32
// The file to blame is identified by the input arguments: repo, commit and path.
29
33
// The output is a slice of commits, one for each line in the file.
@@ -66,19 +70,9 @@ import (
66
70
// 1. Add memoization between revlist and assign.
67
71
//
68
72
// 2. It is using much more memory than needed, see the TODOs below.
69
-
70
- type Blame struct {
71
- Repo string
72
- Path string
73
- Rev string
74
- Lines []* line
75
- }
76
-
77
- func New (repo * git.Repository , path string , commit * git.Commit ) (* Blame , error ) {
78
- // init the internal blame struct
73
+ func (c * Commit ) Blame (path string ) (* Blame , error ) {
79
74
b := new (blame )
80
- b .repo = repo
81
- b .fRev = commit
75
+ b .fRev = c
82
76
b .path = path
83
77
84
78
// get all the file revisions
@@ -104,9 +98,8 @@ func New(repo *git.Repository, path string, commit *git.Commit) (*Blame, error)
104
98
}
105
99
106
100
return & Blame {
107
- Repo : repo .URL ,
108
101
Path : path ,
109
- Rev : commit .Hash . String () ,
102
+ Rev : c .Hash ,
110
103
Lines : lines ,
111
104
}, nil
112
105
}
@@ -123,7 +116,7 @@ func newLine(author, text string) *line {
123
116
}
124
117
}
125
118
126
- func newLines (contents []string , commits []* git. Commit ) ([]* line , error ) {
119
+ func newLines (contents []string , commits []* Commit ) ([]* line , error ) {
127
120
if len (contents ) != len (commits ) {
128
121
return nil , errors .New ("contents and commits have different length" )
129
122
}
@@ -138,18 +131,18 @@ func newLines(contents []string, commits []*git.Commit) ([]*line, error) {
138
131
// this struct is internally used by the blame function to hold its
139
132
// inputs, outputs and state.
140
133
type blame struct {
141
- repo * git.Repository // the repo holding the history of the file to blame
142
- path string // the path of the file to blame
143
- fRev * git.Commit // the commit of the final revision of the file to blame
144
- revs revlist.Revs // the chain of revisions affecting the the file to blame
145
- data []string // the contents of the file across all its revisions
146
- graph [][]* git.Commit // the graph of the lines in the file across all the revisions TODO: not all commits are needed, only the current rev and the prev
134
+ path string // the path of the file to blame
135
+ fRev * Commit // the commit of the final revision of the file to blame
136
+ revs []* Commit // the chain of revisions affecting the the file to blame
137
+ data []string // the contents of the file across all its revisions
138
+ graph [][]* Commit // the graph of the lines in the file across all the revisions TODO: not all commits are needed, only the current rev and the prev
147
139
}
148
140
149
141
// calculte the history of a file "path", starting from commit "from", sorted by commit date.
150
142
func (b * blame ) fillRevs () error {
151
143
var err error
152
- b .revs , err = revlist .NewRevs (b .repo , b .fRev , b .path )
144
+
145
+ b .revs , err = b .fRev .References (b .path )
153
146
if err != nil {
154
147
return err
155
148
}
@@ -158,7 +151,7 @@ func (b *blame) fillRevs() error {
158
151
159
152
// build graph of a file from its revision history
160
153
func (b * blame ) fillGraphAndData () error {
161
- b .graph = make ([][]* git. Commit , len (b .revs ))
154
+ b .graph = make ([][]* Commit , len (b .revs ))
162
155
b .data = make ([]string , len (b .revs )) // file contents in all the revisions
163
156
// for every revision of the file, starting with the first
164
157
// one...
@@ -169,15 +162,15 @@ func (b *blame) fillGraphAndData() error {
169
162
return nil
170
163
}
171
164
b .data [i ] = file .Contents ()
172
- nLines := git . CountLines (b .data [i ])
165
+ nLines := countLines (b .data [i ])
173
166
// create a node for each line
174
- b .graph [i ] = make ([]* git. Commit , nLines )
167
+ b .graph [i ] = make ([]* Commit , nLines )
175
168
// assign a commit to each node
176
169
// if this is the first revision, then the node is assigned to
177
170
// this first commit.
178
171
if i == 0 {
179
172
for j := 0 ; j < nLines ; j ++ {
180
- b.graph [i ][j ] = (* git . Commit )(b .revs [i ])
173
+ b.graph [i ][j ] = (* Commit )(b .revs [i ])
181
174
}
182
175
} else {
183
176
// if this is not the first commit, then assign to the old
@@ -191,11 +184,11 @@ func (b *blame) fillGraphAndData() error {
191
184
192
185
// sliceGraph returns a slice of commits (one per line) for a particular
193
186
// revision of a file (0=first revision).
194
- func (b * blame ) sliceGraph (i int ) []* git. Commit {
187
+ func (b * blame ) sliceGraph (i int ) []* Commit {
195
188
fVs := b .graph [i ]
196
- result := make ([]* git. Commit , 0 , len (fVs ))
189
+ result := make ([]* Commit , 0 , len (fVs ))
197
190
for _ , v := range fVs {
198
- c := git . Commit (* v )
191
+ c := Commit (* v )
199
192
result = append (result , & c )
200
193
}
201
194
return result
@@ -209,7 +202,7 @@ func (b *blame) assignOrigin(c, p int) {
209
202
sl := - 1 // source line
210
203
dl := - 1 // destination line
211
204
for h := range hunks {
212
- hLines := git . CountLines (hunks [h ].Text )
205
+ hLines := countLines (hunks [h ].Text )
213
206
for hl := 0 ; hl < hLines ; hl ++ {
214
207
switch {
215
208
case hunks [h ].Type == 0 :
@@ -218,7 +211,7 @@ func (b *blame) assignOrigin(c, p int) {
218
211
b.graph [c ][dl ] = b.graph [p ][sl ]
219
212
case hunks [h ].Type == 1 :
220
213
dl ++
221
- b.graph [c ][dl ] = (* git . Commit )(b .revs [c ])
214
+ b.graph [c ][dl ] = (* Commit )(b .revs [c ])
222
215
case hunks [h ].Type == - 1 :
223
216
sl ++
224
217
default :
@@ -255,7 +248,7 @@ func (b *blame) GoString() string {
255
248
}
256
249
257
250
// utility function to pretty print the author.
258
- func prettyPrintAuthor (c * git. Commit ) string {
251
+ func prettyPrintAuthor (c * Commit ) string {
259
252
return fmt .Sprintf ("%s %s" , c .Author .Name , c .Author .When .Format ("2006-01-02" ))
260
253
}
261
254
0 commit comments