18
18
*/
19
19
20
20
/*
21
- * Copyright (c) 2005, 2023 , Oracle and/or its affiliates. All rights reserved.
21
+ * Copyright (c) 2005, 2024 , Oracle and/or its affiliates. All rights reserved.
22
22
* Portions Copyright (c) 2017, 2020, Chris Fraire <[email protected] >.
23
23
*/
24
24
package org .opengrok .indexer .history ;
47
47
import java .util .logging .Logger ;
48
48
import java .util .stream .Collectors ;
49
49
50
+ import org .apache .lucene .document .Document ;
51
+ import org .apache .lucene .queryparser .classic .ParseException ;
50
52
import org .jetbrains .annotations .Nullable ;
51
53
import org .jetbrains .annotations .VisibleForTesting ;
52
- import org .opengrok .indexer .analysis .AbstractAnalyzer ;
53
- import org .opengrok .indexer .analysis .AnalyzerGuru ;
54
54
import org .opengrok .indexer .configuration .CommandTimeoutType ;
55
55
import org .opengrok .indexer .configuration .Configuration ;
56
56
import org .opengrok .indexer .configuration .Configuration .RemoteSCM ;
59
59
import org .opengrok .indexer .configuration .RuntimeEnvironment ;
60
60
import org .opengrok .indexer .logger .LoggerFactory ;
61
61
import org .opengrok .indexer .search .DirectoryEntry ;
62
+ import org .opengrok .indexer .search .QueryBuilder ;
62
63
import org .opengrok .indexer .util .ForbiddenSymlinkException ;
63
64
import org .opengrok .indexer .util .PathUtils ;
64
65
import org .opengrok .indexer .util .Progress ;
65
66
import org .opengrok .indexer .util .Statistics ;
66
67
68
+ import static org .opengrok .indexer .analysis .AnalyzerGuru .isXrefable ;
69
+ import static org .opengrok .indexer .index .IndexDatabase .getDocument ;
70
+
67
71
/**
68
72
* The HistoryGuru is used to implement an transparent layer to the various
69
73
* source control systems.
@@ -229,10 +233,14 @@ public String getAnnotationCacheInfo() {
229
233
*/
230
234
@ Nullable
231
235
private Annotation getAnnotation (File file , @ Nullable String rev , boolean fallback ) throws IOException {
232
- Annotation annotation ;
233
-
234
236
Repository repository = getRepository (file );
235
- if (annotationCache != null && repository != null && repository .isAnnotationCacheEnabled ()) {
237
+ if (repository == null ) {
238
+ LOGGER .log (Level .FINER , "no repository found for ''{0}'' to check for annotation" , file );
239
+ return null ;
240
+ }
241
+
242
+ Annotation annotation ;
243
+ if (annotationCache != null && repository .isAnnotationCacheEnabled ()) {
236
244
try {
237
245
annotation = annotationCache .get (file , rev );
238
246
if (annotation != null ) {
@@ -248,9 +256,13 @@ private Annotation getAnnotation(File file, @Nullable String rev, boolean fallba
248
256
return null ;
249
257
}
250
258
259
+ if (!HistoryGuru .getInstance ().hasAnnotation (file )) {
260
+ LOGGER .log (Level .FINER , "skipped getting annotation for file ''{0}}''" , file );
261
+ return null ;
262
+ }
263
+
251
264
// Fall back to repository based annotation.
252
- // It might be possible to store the annotation to the annotation cache here, needs further thought.
253
- annotation = getAnnotationFromRepository (file , rev );
265
+ annotation = getAnnotationFromRepository (file , rev , repository );
254
266
if (annotation != null ) {
255
267
annotation .setRevision (LatestRevisionUtil .getLatestRevision (file ));
256
268
}
@@ -260,24 +272,21 @@ private Annotation getAnnotation(File file, @Nullable String rev, boolean fallba
260
272
261
273
/**
262
274
* Annotate given file using repository method. Makes sure that the resulting annotation has the revision set.
275
+ * Assumes the {@link HistoryGuru#hasAnnotation(File)} check was already done.
263
276
* @param file file object to generate the annotation for
264
277
* @param rev revision to get the annotation for or {@code null} for latest revision of given file
278
+ * @param repository {@link Repository} instance
265
279
* @return annotation object or {@code null}
266
280
* @throws IOException on error when getting the annotation
267
281
*/
268
282
@ Nullable
269
- private Annotation getAnnotationFromRepository (File file , @ Nullable String rev ) throws IOException {
283
+ private Annotation getAnnotationFromRepository (File file , @ Nullable String rev , Repository repository ) throws IOException {
270
284
if (!env .getPathAccepter ().accept (file )) {
271
285
LOGGER .log (Level .FINEST , "file ''{0}'' not accepted for annotation" , file );
272
286
return null ;
273
287
}
274
288
275
- Repository repository = getRepository (file );
276
- if (repository != null && hasAnnotation (file )) {
277
- return repository .annotate (file , rev );
278
- }
279
-
280
- return null ;
289
+ return repository .annotate (file , rev );
281
290
}
282
291
283
292
/**
@@ -681,35 +690,60 @@ public boolean hasHistoryCacheForFile(File file) {
681
690
}
682
691
683
692
/**
684
- * Check if we can annotate the specified file.
685
- *
693
+ * Check if annotation can be produced for the specified file. If related document is specified,
694
+ * it will be used for negative check. If the document indicates that the type of file is xref-able
695
+ * or the document is {@code null}, the capability to produce annotation for the file will be checked
696
+ * in related repository.
686
697
* @param file the file to check
687
- * @return whether the file is under version control , can be annotated and the
688
- * version control system supports annotation
698
+ * @param document {@link Document} object related to the file , can be {@code null}.
699
+ * @return whether the file can be annotated
689
700
*/
690
- public boolean hasAnnotation (File file ) {
701
+ public boolean hasAnnotation (File file , @ Nullable Document document ) {
691
702
if (file .isDirectory ()) {
692
- LOGGER .log (Level .FINEST , "no annotations for directories (''{0}'') to check annotation presence" ,
693
- file );
703
+ LOGGER .log (Level .FINEST , "no annotations for directories (''{0}'')" , file );
694
704
return false ;
695
705
}
696
706
697
- AbstractAnalyzer .Genre genre = AnalyzerGuru .getGenre (file .toString ());
698
- if (genre == null ) {
699
- LOGGER .log (Level .INFO , "will not produce annotation for ''{0}'' with unknown genre" , file );
700
- return false ;
707
+ if (document != null ) {
708
+ // The "T" field is added to the document currently only for xref-able input data,
709
+ // however it does not hurt to check in case this will change.
710
+ String fileType = document .get (QueryBuilder .T );
711
+ if (fileType == null || !isXrefable (fileType )) {
712
+ LOGGER .log (Level .FINEST , "no file type found in document for ''{0}'' or not xref-able" , file );
713
+ return false ;
714
+ }
701
715
}
702
- if (genre .equals (AbstractAnalyzer .Genre .DATA ) || genre .equals (AbstractAnalyzer .Genre .IMAGE )) {
703
- LOGGER .log (Level .INFO , "no sense to produce annotation for binary file ''{0}''" , file );
716
+
717
+ return hasAnnotationInRepo (file );
718
+ }
719
+
720
+ /**
721
+ * Check if annotation can be produced for the specified file. Wrapper of {@link #hasAnnotation(File, Document)}
722
+ * @param file the file to check
723
+ * @return whether the file can be annotated
724
+ */
725
+ public boolean hasAnnotation (File file ) {
726
+ if (file .isDirectory ()) {
727
+ LOGGER .log (Level .FINEST , "no annotations for directories (''{0}'')" , file );
704
728
return false ;
705
729
}
706
730
731
+ Document document = null ;
732
+ try {
733
+ document = getDocument (file );
734
+ } catch (ParseException | IOException e ) {
735
+ LOGGER .log (Level .FINEST , String .format ("cannot get document for '%s' to check annotation" , file ), e );
736
+ }
737
+
738
+ return hasAnnotation (file , document );
739
+ }
740
+
741
+ private boolean hasAnnotationInRepo (File file ) {
707
742
Repository repo = getRepository (file );
708
743
if (repo == null ) {
709
744
LOGGER .log (Level .FINEST , "cannot find repository for ''{0}'' to check annotation presence" , file );
710
745
return false ;
711
746
}
712
-
713
747
if (!repo .isWorking ()) {
714
748
LOGGER .log (Level .FINEST , "repository {0} for ''{1}'' is not working to check annotation presence" ,
715
749
new Object []{repo , file });
@@ -1116,7 +1150,7 @@ public void createAnnotationCache(File file, String latestRev) throws CacheExcep
1116
1150
LOGGER .log (Level .FINEST , "creating annotation cache for ''{0}''" , file );
1117
1151
try {
1118
1152
Statistics statistics = new Statistics ();
1119
- Annotation annotation = getAnnotationFromRepository (file , null );
1153
+ Annotation annotation = getAnnotationFromRepository (file , null , repository );
1120
1154
statistics .report (LOGGER , Level .FINEST , String .format ("retrieved annotation for ''%s''" , file ),
1121
1155
"annotation.retrieve.latency" );
1122
1156
0 commit comments