@@ -5,13 +5,15 @@ final class DiffusionLintSaveRunner {
5
5
private $ severity = ArcanistLintSeverity::SEVERITY_ADVICE ;
6
6
private $ all = false ;
7
7
private $ chunkSize = 256 ;
8
+ private $ needsBlame = false ;
8
9
9
10
private $ svnRoot ;
10
11
private $ lintCommit ;
11
12
private $ branch ;
12
13
private $ conn ;
13
14
private $ deletes = array ();
14
15
private $ inserts = array ();
16
+ private $ blame = array ();
15
17
16
18
17
19
public function setArc ($ path ) {
@@ -34,6 +36,11 @@ public function setChunkSize($number) {
34
36
return $ this ;
35
37
}
36
38
39
+ public function setNeedsBlame ($ boolean ) {
40
+ $ this ->needsBlame = $ boolean ;
41
+ return $ this ;
42
+ }
43
+
37
44
38
45
public function run ($ dir ) {
39
46
$ working_copy = ArcanistWorkingCopyIdentity::newFromPath ($ dir );
@@ -44,7 +51,7 @@ public function run($dir) {
44
51
$ svn_fetch = $ api ->getGitConfig ('svn-remote.svn.fetch ' );
45
52
list ($ this ->svnRoot ) = explode (': ' , $ svn_fetch );
46
53
if ($ this ->svnRoot != '' ) {
47
- $ this ->svnRoot = '/ ' . $ this ->svnRoot ;
54
+ $ this ->svnRoot = '/ ' . $ this ->svnRoot ;
48
55
}
49
56
}
50
57
@@ -98,8 +105,6 @@ public function run($dir) {
98
105
$ all_files = $ api ->getAllFiles ();
99
106
}
100
107
101
- $ this ->deletes = array ();
102
- $ this ->inserts = array ();
103
108
$ count = 0 ;
104
109
105
110
$ files = array ();
@@ -123,9 +128,16 @@ public function run($dir) {
123
128
124
129
$ this ->runArcLint ($ files );
125
130
$ this ->saveLintMessages ();
126
- $ this ->branch ->setLintCommit ($ api ->getUnderlyingWorkingCopyRevision ());
131
+
132
+ $ this ->lintCommit = $ api ->getUnderlyingWorkingCopyRevision ();
133
+ $ this ->branch ->setLintCommit ($ this ->lintCommit );
127
134
$ this ->branch ->save ();
128
135
136
+ if ($ this ->blame ) {
137
+ $ this ->blameAuthors ();
138
+ $ this ->blame = array ();
139
+ }
140
+
129
141
return $ count ;
130
142
}
131
143
@@ -156,22 +168,26 @@ private function runArcLint(array $files) {
156
168
}
157
169
158
170
foreach ($ messages as $ message ) {
171
+ $ line = idx ($ message , 'line ' , 0 );
172
+
159
173
$ this ->inserts [] = qsprintf (
160
174
$ this ->conn ,
161
175
'(%d, %s, %d, %s, %s, %s, %s) ' ,
162
176
$ this ->branch ->getID (),
163
177
$ this ->svnRoot .'/ ' .$ path ,
164
- idx ( $ message , ' line ' , 0 ) ,
178
+ $ line ,
165
179
idx ($ message , 'code ' , '' ),
166
180
idx ($ message , 'severity ' , '' ),
167
181
idx ($ message , 'name ' , '' ),
168
182
idx ($ message , 'description ' , '' ));
183
+
184
+ if ($ line && $ this ->needsBlame ) {
185
+ $ this ->blame [$ path ][$ line ] = true ;
186
+ }
169
187
}
170
188
171
189
if (count ($ this ->deletes ) >= 1024 || count ($ this ->inserts ) >= 256 ) {
172
- $ this ->saveLintMessages ($ this ->branch );
173
- $ this ->deletes = array ();
174
- $ this ->inserts = array ();
190
+ $ this ->saveLintMessages ();
175
191
}
176
192
}
177
193
}
@@ -205,6 +221,67 @@ private function saveLintMessages() {
205
221
}
206
222
207
223
$ this ->conn ->saveTransaction ();
224
+
225
+ $ this ->deletes = array ();
226
+ $ this ->inserts = array ();
227
+ }
228
+
229
+
230
+ private function blameAuthors () {
231
+ $ repository = id (new PhabricatorRepository ())->load (
232
+ $ this ->branch ->getRepositoryID ());
233
+
234
+ $ queries = array ();
235
+ $ futures = array ();
236
+ foreach ($ this ->blame as $ path => $ lines ) {
237
+ $ drequest = DiffusionRequest::newFromDictionary (array (
238
+ 'repository ' => $ repository ,
239
+ 'branch ' => $ this ->branch ->getName (),
240
+ 'path ' => $ path ,
241
+ 'commit ' => $ this ->lintCommit ,
242
+ ));
243
+ $ query = DiffusionFileContentQuery::newFromDiffusionRequest ($ drequest )
244
+ ->setNeedsBlame (true );
245
+ $ queries [$ path ] = $ query ;
246
+ $ futures [$ path ] = $ query ->getFileContentFuture ();
247
+ }
248
+
249
+ $ authors = array ();
250
+
251
+ foreach (Futures ($ futures )->limit (8 ) as $ path => $ future ) {
252
+ $ queries [$ path ]->loadFileContentFromFuture ($ future );
253
+ list (, $ rev_list , $ blame_dict ) = $ queries [$ path ]->getBlameData ();
254
+ foreach (array_keys ($ this ->blame [$ path ]) as $ line ) {
255
+ $ commit_identifier = $ rev_list [$ line - 1 ];
256
+ $ author = idx ($ blame_dict [$ commit_identifier ], 'authorPHID ' );
257
+ if ($ author ) {
258
+ $ authors [$ author ][$ path ][] = $ line ;
259
+ }
260
+ }
261
+ }
262
+
263
+ if ($ authors ) {
264
+ $ this ->conn ->openTransaction ();
265
+
266
+ foreach ($ authors as $ author => $ paths ) {
267
+ $ where = array ();
268
+ foreach ($ paths as $ path => $ lines ) {
269
+ $ where [] = qsprintf (
270
+ $ this ->conn ,
271
+ '(path = %s AND line IN (%Ld)) ' ,
272
+ $ this ->svnRoot .'/ ' .$ path ,
273
+ $ lines );
274
+ }
275
+ queryfx (
276
+ $ this ->conn ,
277
+ 'UPDATE %T SET authorPHID = %s WHERE %Q ' ,
278
+ PhabricatorRepository::TABLE_LINTMESSAGE ,
279
+ $ author ,
280
+ implode (' OR ' , $ where ));
281
+ }
282
+
283
+ $ this ->conn ->saveTransaction ();
284
+ }
208
285
}
209
286
210
287
}
0 commit comments