1818 */
1919
2020/*
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.
2222 * Portions Copyright (c) 2017, 2020, Chris Fraire <cfraire@me.com>.
2323 */
2424package org .opengrok .indexer .history ;
4747import java .util .logging .Logger ;
4848import java .util .stream .Collectors ;
4949
50+ import org .apache .lucene .document .Document ;
51+ import org .apache .lucene .queryparser .classic .ParseException ;
5052import org .jetbrains .annotations .Nullable ;
5153import org .jetbrains .annotations .VisibleForTesting ;
52- import org .opengrok .indexer .analysis .AbstractAnalyzer ;
53- import org .opengrok .indexer .analysis .AnalyzerGuru ;
5454import org .opengrok .indexer .configuration .CommandTimeoutType ;
5555import org .opengrok .indexer .configuration .Configuration ;
5656import org .opengrok .indexer .configuration .Configuration .RemoteSCM ;
5959import org .opengrok .indexer .configuration .RuntimeEnvironment ;
6060import org .opengrok .indexer .logger .LoggerFactory ;
6161import org .opengrok .indexer .search .DirectoryEntry ;
62+ import org .opengrok .indexer .search .QueryBuilder ;
6263import org .opengrok .indexer .util .ForbiddenSymlinkException ;
6364import org .opengrok .indexer .util .PathUtils ;
6465import org .opengrok .indexer .util .Progress ;
6566import org .opengrok .indexer .util .Statistics ;
6667
68+ import static org .opengrok .indexer .analysis .AnalyzerGuru .isXrefable ;
69+ import static org .opengrok .indexer .index .IndexDatabase .getDocument ;
70+
6771/**
6872 * The HistoryGuru is used to implement an transparent layer to the various
6973 * source control systems.
@@ -229,10 +233,14 @@ public String getAnnotationCacheInfo() {
229233 */
230234 @ Nullable
231235 private Annotation getAnnotation (File file , @ Nullable String rev , boolean fallback ) throws IOException {
232- Annotation annotation ;
233-
234236 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 ()) {
236244 try {
237245 annotation = annotationCache .get (file , rev );
238246 if (annotation != null ) {
@@ -248,9 +256,13 @@ private Annotation getAnnotation(File file, @Nullable String rev, boolean fallba
248256 return null ;
249257 }
250258
259+ if (!HistoryGuru .getInstance ().hasAnnotation (file )) {
260+ LOGGER .log (Level .FINER , "skipped getting annotation for file ''{0}}''" , file );
261+ return null ;
262+ }
263+
251264 // 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 );
254266 if (annotation != null ) {
255267 annotation .setRevision (LatestRevisionUtil .getLatestRevision (file ));
256268 }
@@ -260,24 +272,21 @@ private Annotation getAnnotation(File file, @Nullable String rev, boolean fallba
260272
261273 /**
262274 * 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.
263276 * @param file file object to generate the annotation for
264277 * @param rev revision to get the annotation for or {@code null} for latest revision of given file
278+ * @param repository {@link Repository} instance
265279 * @return annotation object or {@code null}
266280 * @throws IOException on error when getting the annotation
267281 */
268282 @ 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 {
270284 if (!env .getPathAccepter ().accept (file )) {
271285 LOGGER .log (Level .FINEST , "file ''{0}'' not accepted for annotation" , file );
272286 return null ;
273287 }
274288
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 );
281290 }
282291
283292 /**
@@ -681,35 +690,60 @@ public boolean hasHistoryCacheForFile(File file) {
681690 }
682691
683692 /**
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.
686697 * @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
689700 */
690- public boolean hasAnnotation (File file ) {
701+ public boolean hasAnnotation (File file , @ Nullable Document document ) {
691702 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 );
694704 return false ;
695705 }
696706
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+ }
701715 }
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 );
704728 return false ;
705729 }
706730
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 ) {
707742 Repository repo = getRepository (file );
708743 if (repo == null ) {
709744 LOGGER .log (Level .FINEST , "cannot find repository for ''{0}'' to check annotation presence" , file );
710745 return false ;
711746 }
712-
713747 if (!repo .isWorking ()) {
714748 LOGGER .log (Level .FINEST , "repository {0} for ''{1}'' is not working to check annotation presence" ,
715749 new Object []{repo , file });
@@ -1116,7 +1150,7 @@ public void createAnnotationCache(File file, String latestRev) throws CacheExcep
11161150 LOGGER .log (Level .FINEST , "creating annotation cache for ''{0}''" , file );
11171151 try {
11181152 Statistics statistics = new Statistics ();
1119- Annotation annotation = getAnnotationFromRepository (file , null );
1153+ Annotation annotation = getAnnotationFromRepository (file , null , repository );
11201154 statistics .report (LOGGER , Level .FINEST , String .format ("retrieved annotation for ''%s''" , file ),
11211155 "annotation.retrieve.latency" );
11221156
0 commit comments