@@ -8,6 +8,8 @@ import * as _ from 'lodash';
8
8
9
9
const blameMatcher = / ^ ( [ \^ 0 - 9 a - f A - F ] { 8 } ) \s ( [ \S ] * ) \s + ( [ 0 - 9 \S ] + ) \s \( ( .* ) \s ( [ 0 - 9 ] { 4 } - [ 0 - 9 ] { 2 } - [ 0 - 9 ] { 2 } \s [ 0 - 9 ] { 2 } : [ 0 - 9 ] { 2 } : [ 0 - 9 ] { 2 } \s [ - | + ] [ 0 - 9 ] { 4 } ) \s + ( [ 0 - 9 ] + ) \) ( .* ) $ / gm;
10
10
const commitMessageMatcher = / ^ ( [ \^ 0 - 9 a - f A - F ] { 7 } ) \s ( .* ) $ / gm;
11
+ const blamePorcelainMatcher = / ^ ( [ \^ 0 - 9 a - f A - F ] { 40 } ) \s ( [ 0 - 9 ] + ) \s ( [ 0 - 9 ] + ) (?: \s ( [ 0 - 9 ] + ) ) ? $ \n (?: ^ a u t h o r \s ( .* ) $ \n ^ a u t h o r - m a i l \s ( .* ) $ \n ^ a u t h o r - t i m e \s ( .* ) $ \n ^ a u t h o r - t z \s ( .* ) $ \n ^ c o m m i t t e r \s ( .* ) $ \n ^ c o m m i t t e r - m a i l \s ( .* ) $ \n ^ c o m m i t t e r - t i m e \s ( .* ) $ \n ^ c o m m i t t e r - t z \s ( .* ) $ \n ^ s u m m a r y \s ( .* ) $ \n (?: ^ p r e v i o u s \s ( .* ) ? \s ( .* ) $ \n ) ? ^ f i l e n a m e \s ( .* ) $ \n ) ? ^ ( .* ) $ / gm;
12
+ const blameLinePorcelainMatcher = / ^ ( [ \^ 0 - 9 a - f A - F ] { 40 } ) \s ( [ 0 - 9 ] + ) \s ( [ 0 - 9 ] + ) (?: \s ( [ 0 - 9 ] + ) ) ? $ \n ^ a u t h o r \s ( .* ) $ \n ^ a u t h o r - m a i l \s ( .* ) $ \n ^ a u t h o r - t i m e \s ( .* ) $ \n ^ a u t h o r - t z \s ( .* ) $ \n ^ c o m m i t t e r \s ( .* ) $ \n ^ c o m m i t t e r - m a i l \s ( .* ) $ \n ^ c o m m i t t e r - t i m e \s ( .* ) $ \n ^ c o m m i t t e r - t z \s ( .* ) $ \n ^ s u m m a r y \s ( .* ) $ \n (?: ^ p r e v i o u s \s ( .* ) ? \s ( .* ) $ \n ) ? ^ f i l e n a m e \s ( .* ) $ \n ^ ( .* ) $ / gm;
11
13
12
14
export default class GitProvider extends Disposable {
13
15
public repoPath : string ;
@@ -43,53 +45,138 @@ export default class GitProvider extends Disposable {
43
45
return Git . repoPath ( cwd ) ;
44
46
}
45
47
48
+ // getBlameForFile(fileName: string) {
49
+ // fileName = Git.normalizePath(fileName, this.repoPath);
50
+
51
+ // let blame = this._blames.get(fileName);
52
+ // if (blame !== undefined) return blame;
53
+
54
+ // blame = Git.blame(fileName, this.repoPath)
55
+ // .then(data => {
56
+ // const authors: Map<string, IGitAuthor> = new Map();
57
+ // const commits: Map<string, IGitCommit> = new Map();
58
+ // const lines: Array<IGitCommitLine> = [];
59
+
60
+ // let m: Array<string>;
61
+ // while ((m = blameMatcher.exec(data)) != null) {
62
+ // const authorName = m[4].trim();
63
+ // let author = authors.get(authorName);
64
+ // if (!author) {
65
+ // author = {
66
+ // name: authorName,
67
+ // lineCount: 0
68
+ // };
69
+ // authors.set(authorName, author);
70
+ // }
71
+
72
+ // const sha = m[1];
73
+ // let commit = commits.get(sha);
74
+ // if (!commit) {
75
+ // commit = {
76
+ // sha,
77
+ // fileName: fileName,
78
+ // author: authorName,
79
+ // date: new Date(m[5]),
80
+ // lines: []
81
+ // };
82
+
83
+ // const file = m[2].trim();
84
+ // if (!fileName.toLowerCase().endsWith(file.toLowerCase())) {
85
+ // commit.originalFileName = file;
86
+ // }
87
+
88
+ // commits.set(sha, commit);
89
+ // }
90
+
91
+ // const line: IGitCommitLine = {
92
+ // sha,
93
+ // line: parseInt(m[6], 10) - 1,
94
+ // originalLine: parseInt(m[3], 10) - 1
95
+ // //code: m[7]
96
+ // }
97
+
98
+ // commit.lines.push(line);
99
+ // lines.push(line);
100
+ // }
101
+
102
+ // commits.forEach(c => authors.get(c.author).lineCount += c.lines.length);
103
+
104
+ // const sortedAuthors: Map<string, IGitAuthor> = new Map();
105
+ // const values = Array.from(authors.values())
106
+ // .sort((a, b) => b.lineCount - a.lineCount)
107
+ // .forEach(a => sortedAuthors.set(a.name, a));
108
+
109
+ // const sortedCommits = new Map();
110
+ // Array.from(commits.values())
111
+ // .sort((a, b) => b.date.getTime() - a.date.getTime())
112
+ // .forEach(c => sortedCommits.set(c.sha, c));
113
+
114
+ // return {
115
+ // authors: sortedAuthors,
116
+ // commits: sortedCommits,
117
+ // lines: lines
118
+ // };
119
+ // });
120
+
121
+ // this._blames.set(fileName, blame);
122
+ // return blame;
123
+ // }
124
+
46
125
getBlameForFile ( fileName : string ) {
47
126
fileName = Git . normalizePath ( fileName , this . repoPath ) ;
48
127
49
128
let blame = this . _blames . get ( fileName ) ;
50
129
if ( blame !== undefined ) return blame ;
51
130
52
- blame = Git . blame ( fileName , this . repoPath )
131
+ blame = Git . blamePorcelain ( fileName , this . repoPath )
53
132
. then ( data => {
54
133
const authors : Map < string , IGitAuthor > = new Map ( ) ;
55
134
const commits : Map < string , IGitCommit > = new Map ( ) ;
56
135
const lines : Array < IGitCommitLine > = [ ] ;
57
136
58
137
let m : Array < string > ;
59
- while ( ( m = blameMatcher . exec ( data ) ) != null ) {
60
- const authorName = m [ 4 ] . trim ( ) ;
61
- let author = authors . get ( authorName ) ;
62
- if ( ! author ) {
63
- author = {
64
- name : authorName ,
65
- lineCount : 0
66
- } ;
67
- authors . set ( authorName , author ) ;
68
- }
69
-
70
- const sha = m [ 1 ] ;
138
+ while ( ( m = blamePorcelainMatcher . exec ( data ) ) != null ) {
139
+ const sha = m [ 1 ] . substring ( 0 , 8 ) ;
71
140
let commit = commits . get ( sha ) ;
72
141
if ( ! commit ) {
142
+ const authorName = m [ 5 ] . trim ( ) ;
143
+ let author = authors . get ( authorName ) ;
144
+ if ( ! author ) {
145
+ author = {
146
+ name : authorName ,
147
+ lineCount : 0
148
+ } ;
149
+ authors . set ( authorName , author ) ;
150
+ }
151
+
73
152
commit = {
74
153
sha,
75
154
fileName : fileName ,
76
- author : m [ 4 ] . trim ( ) ,
77
- date : new Date ( m [ 5 ] ) ,
155
+ author : authorName ,
156
+ date : moment ( `${ m [ 7 ] } ${ m [ 8 ] } ` , 'X Z' ) . toDate ( ) ,
157
+ message : m [ 13 ] ,
78
158
lines : [ ]
79
159
} ;
160
+
161
+ const originalFileName = m [ 16 ] ;
162
+ if ( ! fileName . toLowerCase ( ) . endsWith ( originalFileName . toLowerCase ( ) ) ) {
163
+ commit . originalFileName = originalFileName ;
164
+ }
165
+
166
+ const previousSha = m [ 14 ] ;
167
+ if ( previousSha ) {
168
+ commit . previousSha = previousSha . substring ( 0 , 8 ) ;
169
+ commit . previousFileName = m [ 15 ] ;
170
+ }
171
+
80
172
commits . set ( sha , commit ) ;
81
173
}
82
174
83
175
const line : IGitCommitLine = {
84
176
sha,
85
- line : parseInt ( m [ 6 ] , 10 ) - 1 ,
86
- originalLine : parseInt ( m [ 3 ] , 10 ) - 1
87
- //code: m[7]
88
- }
89
-
90
- const file = m [ 2 ] . trim ( ) ;
91
- if ( ! fileName . toLowerCase ( ) . endsWith ( file . toLowerCase ( ) ) ) {
92
- line . originalFileName = file ;
177
+ line : parseInt ( m [ 3 ] , 10 ) - 1 ,
178
+ originalLine : parseInt ( m [ 2 ] , 10 ) - 1
179
+ //code: m[17]
93
180
}
94
181
95
182
commit . lines . push ( line ) ;
@@ -116,8 +203,7 @@ export default class GitProvider extends Disposable {
116
203
} ) ;
117
204
118
205
this . _blames . set ( fileName , blame ) ;
119
- return blame ;
120
- }
206
+ return blame ; }
121
207
122
208
getBlameForLine ( fileName : string , line : number ) : Promise < IGitBlameLine > {
123
209
return this . getBlameForFile ( fileName ) . then ( blame => {
@@ -192,8 +278,8 @@ export default class GitProvider extends Disposable {
192
278
Array . from ( blame . commits . values ( ) )
193
279
. forEach ( ( c , i ) => {
194
280
const uri = this . toBlameUri ( c , i + 1 , commitCount , range ) ;
195
- c . lines . forEach ( l => locations . push ( new Location ( l . originalFileName
196
- ? this . toBlameUri ( c , i + 1 , commitCount , range , l . originalFileName )
281
+ c . lines . forEach ( l => locations . push ( new Location ( c . originalFileName
282
+ ? this . toBlameUri ( c , i + 1 , commitCount , range , c . originalFileName )
197
283
: uri ,
198
284
new Position ( l . originalLine , 0 ) ) ) ) ;
199
285
} ) ;
@@ -202,6 +288,24 @@ export default class GitProvider extends Disposable {
202
288
} ) ;
203
289
}
204
290
291
+ // getHistoryLocations(fileName: string, range: Range) {
292
+ // return this.getBlameForRange(fileName, range).then(blame => {
293
+ // const commitCount = blame.commits.size;
294
+
295
+ // const locations: Array<Location> = [];
296
+ // Array.from(blame.commits.values())
297
+ // .forEach((c, i) => {
298
+ // const uri = this.toBlameUri(c, i + 1, commitCount, range);
299
+ // c.lines.forEach(l => locations.push(new Location(c.originalFileName
300
+ // ? this.toBlameUri(c, i + 1, commitCount, range, c.originalFileName)
301
+ // : uri,
302
+ // new Position(l.originalLine, 0))));
303
+ // });
304
+
305
+ // return locations;
306
+ // });
307
+ // }
308
+
205
309
getCommitMessage ( sha : string ) {
206
310
return Git . getCommitMessage ( sha , this . repoPath ) ;
207
311
}
@@ -303,15 +407,17 @@ export interface IGitCommit {
303
407
fileName : string ;
304
408
author : string ;
305
409
date : Date ;
410
+ message : string ;
306
411
lines : IGitCommitLine [ ] ;
307
- message ?: string ;
412
+ originalFileName ?: string ;
413
+ previousSha ?: string ;
414
+ previousFileName ?: string ;
308
415
}
309
416
310
417
export interface IGitCommitLine {
311
418
sha : string ;
312
419
line : number ;
313
420
originalLine : number ;
314
- originalFileName ?: string ;
315
421
code ?: string ;
316
422
}
317
423
0 commit comments