@@ -95,6 +95,16 @@ public final class HistoryGuru {
95
95
*/
96
96
private final RepositoryLookup repositoryLookup ;
97
97
98
+ private boolean historyIndexDone = false ;
99
+
100
+ public void setHistoryIndexDone () {
101
+ historyIndexDone = true ;
102
+ }
103
+
104
+ public boolean isHistoryIndexDone () {
105
+ return historyIndexDone ;
106
+ }
107
+
98
108
/**
99
109
* Creates a new instance of HistoryGuru, and try to set the default source
100
110
* control system.
@@ -230,6 +240,16 @@ public History getHistoryUI(File file) throws HistoryException {
230
240
return getHistory (file , true , true );
231
241
}
232
242
243
+ /**
244
+ * The idea is that some repositories require reaching out to remote server whenever
245
+ * a history operation is done. Sometimes this is unwanted and this method decides that.
246
+ * This should be consulted before the actual repository operation, i.e. not when fetching
247
+ * history from a cache since that is inherently local operation.
248
+ * @param repo repository
249
+ * @param file file to decide the operation for
250
+ * @param ui whether coming from UI
251
+ * @return whether to perform the history operation
252
+ */
233
253
boolean isRepoHistoryEligible (Repository repo , File file , boolean ui ) {
234
254
RemoteSCM rscm = env .getRemoteScmSupported ();
235
255
boolean doRemote = (ui && (rscm == RemoteSCM .UIONLY ))
@@ -241,17 +261,19 @@ boolean isRepoHistoryEligible(Repository repo, File file, boolean ui) {
241
261
}
242
262
243
263
@ Nullable
244
- private History getHistoryFromCache (File file , Repository repository , boolean withFiles , boolean fallback )
264
+ private History getHistoryFromCache (File file , Repository repository , boolean withFiles )
245
265
throws HistoryException , ForbiddenSymlinkException {
246
266
247
267
if (useCache () && historyCache .supportsRepository (repository )) {
248
- return historyCache .get (file , repository , withFiles , fallback );
268
+ return historyCache .get (file , repository , withFiles );
249
269
}
250
270
251
271
return null ;
252
272
}
253
273
254
274
/**
275
+ * Get last {@link HistoryEntry} for a file. First, try to retrieve it from the cache.
276
+ * If that fails, fallback to the repository method.
255
277
* @param file file to get the history entry for
256
278
* @param ui is the request coming from the UI
257
279
* @return last (newest) history entry for given file or {@code null}
@@ -264,15 +286,9 @@ public HistoryEntry getLastHistoryEntry(File file, boolean ui) throws HistoryExc
264
286
final File dir = file .isDirectory () ? file : file .getParentFile ();
265
287
final Repository repository = getRepository (dir );
266
288
267
- if (!isRepoHistoryEligible (repository , file , ui )) {
268
- LOGGER .log (Level .FINER , "cannot retrieve the last history entry for ''{0}'' in {1} because of settings" ,
269
- new Object []{file , repository });
270
- return null ;
271
- }
272
-
273
289
History history ;
274
290
try {
275
- history = getHistoryFromCache (file , repository , false , false );
291
+ history = getHistoryFromCache (file , repository , false );
276
292
if (history != null ) {
277
293
HistoryEntry lastHistoryEntry = history .getLastHistoryEntry ();
278
294
if (lastHistoryEntry != null ) {
@@ -286,14 +302,21 @@ public HistoryEntry getLastHistoryEntry(File file, boolean ui) throws HistoryExc
286
302
return null ;
287
303
}
288
304
305
+ if (!isRepoHistoryEligible (repository , file , ui )) {
306
+ LOGGER .log (Level .FINER , "cannot retrieve the last history entry for ''{0}'' in {1} because of settings" ,
307
+ new Object []{file , repository });
308
+ return null ;
309
+ }
310
+
311
+ // Fallback to the repository method.
289
312
HistoryEntry lastHistoryEntry = repository .getLastHistoryEntry (file , ui );
290
313
if (lastHistoryEntry != null ) {
291
314
LOGGER .log (Level .FINEST , "got latest history entry {0} for ''{1}'' using repository {2}" ,
292
315
new Object []{lastHistoryEntry , file , repository });
293
316
}
294
317
statistics .report (LOGGER , Level .FINEST ,
295
318
String .format ("finished retrieval of last history entry for '%s' (%s)" ,
296
- file , lastHistoryEntry != null ? "success" : "fail" ), "history.lasthistoryentry " );
319
+ file , lastHistoryEntry != null ? "success" : "fail" ), "history.entry.latest " );
297
320
return lastHistoryEntry ;
298
321
}
299
322
@@ -318,22 +341,52 @@ public History getHistory(File file, boolean withFiles, boolean ui, boolean fall
318
341
final File dir = file .isDirectory () ? file : file .getParentFile ();
319
342
final Repository repository = getRepository (dir );
320
343
321
- if (!isRepoHistoryEligible (repository , file , ui )) {
322
- return null ;
323
- }
324
-
325
344
History history ;
326
345
try {
327
- history = getHistoryFromCache (file , repository , withFiles , fallback );
346
+ history = getHistoryFromCache (file , repository , withFiles );
328
347
if (history != null ) {
329
348
return history ;
330
349
}
350
+
351
+ return getHistoryFromRepository (file , repository , ui );
331
352
} catch (ForbiddenSymlinkException e ) {
332
353
LOGGER .log (Level .FINER , e .getMessage ());
333
354
return null ;
334
355
}
356
+ }
335
357
336
- return null ;
358
+ @ Nullable
359
+ private History getHistoryFromRepository (File file , Repository repository , boolean ui ) throws HistoryException {
360
+ History history ;
361
+
362
+ if (!isRepoHistoryEligible (repository , file , ui )) {
363
+ return null ;
364
+ }
365
+
366
+ /*
367
+ * Some mirrors of repositories which are capable of fetching history
368
+ * for directories may contain lots of files untracked by given SCM.
369
+ * For these it would be waste of time to get their history
370
+ * since the history of all files in this repository should have been
371
+ * fetched in the first phase of indexing.
372
+ */
373
+ if (isHistoryIndexDone () && repository .isHistoryEnabled () && repository .hasHistoryForDirectories ()) {
374
+ return null ;
375
+ }
376
+
377
+ if (!env .getPathAccepter ().accept (file )) {
378
+ return null ;
379
+ }
380
+
381
+ try {
382
+ history = repository .getHistory (file );
383
+ } catch (UnsupportedOperationException e ) {
384
+ // In this case, we've found a file for which the SCM has no history
385
+ // An example is a non-SCCS file somewhere in an SCCS-controlled workspace.
386
+ return null ;
387
+ }
388
+
389
+ return history ;
337
390
}
338
391
339
392
/**
@@ -684,7 +737,7 @@ private void createCacheReal(Collection<Repository> repositories) {
684
737
"Failed optimizing the history cache database" , he );
685
738
}
686
739
elapsed .report (LOGGER , "Done history cache for all repositories" , "indexer.history.cache" );
687
- historyCache . setHistoryIndexDone ();
740
+ setHistoryIndexDone ();
688
741
}
689
742
690
743
/**
0 commit comments