1818 */
1919
2020/*
21- * Copyright (c) 2005, 2021 , Oracle and/or its affiliates. All rights reserved.
21+ * Copyright (c) 2005, 2023 , Oracle and/or its affiliates. All rights reserved.
2222 * Portions Copyright (c) 2017, 2020, Chris Fraire <[email protected] >. 2323 */
2424package org .opengrok .indexer .search .context ;
3434import java .util .logging .Logger ;
3535
3636import org .apache .lucene .search .Query ;
37+ import org .jetbrains .annotations .Nullable ;
38+ import org .jetbrains .annotations .VisibleForTesting ;
3739import org .opengrok .indexer .history .History ;
3840import org .opengrok .indexer .history .HistoryEntry ;
3941import org .opengrok .indexer .history .HistoryException ;
@@ -119,32 +121,75 @@ public boolean getContext(File src, String path, Writer out, String context) thr
119121 return getHistoryContext (hist , path , out , null , context );
120122 }
121123
124+ private int matchLine (String line , String urlPrefix , String path , @ Nullable Writer out , @ Nullable List <Hit > hits ,
125+ String rev , String nrev ) throws IOException {
126+
127+ int matchedLines = 0 ;
128+ tokens .reInit (line );
129+ String token ;
130+ int matchState ;
131+ long start = -1 ;
132+ while ((token = tokens .next ()) != null ) {
133+ for (LineMatcher lineMatcher : m ) {
134+ matchState = lineMatcher .match (token );
135+ if (matchState == LineMatcher .MATCHED ) {
136+ if (start < 0 ) {
137+ start = tokens .getMatchStart ();
138+ }
139+ long end = tokens .getMatchEnd ();
140+ if (start > Integer .MAX_VALUE || end > Integer .MAX_VALUE ) {
141+ LOGGER .log (Level .WARNING , "Unexpected out of bounds for {0}" , path );
142+ } else if (hits != null ) {
143+ StringBuilder sb = new StringBuilder ();
144+ writeMatch (sb , line , (int ) start , (int ) end ,
145+ true , path , urlPrefix , nrev , rev );
146+ hits .add (new Hit (path , sb .toString (), "" , false , false ));
147+ } else {
148+ writeMatch (out , line , (int ) start , (int ) end ,
149+ false , path , urlPrefix , nrev , rev );
150+ }
151+ matchedLines ++;
152+ break ;
153+ } else if (matchState == LineMatcher .WAIT ) {
154+ if (start < 0 ) {
155+ start = tokens .getMatchStart ();
156+ }
157+ } else {
158+ start = -1 ;
159+ }
160+ }
161+ }
162+
163+ return matchedLines ;
164+ }
165+
122166 /**
123- * Writes matching History log entries from 'in' to 'out' or to 'hits'.
124- * @param in the history to fetch entries from
167+ * Writes matching history log entries to either 'out' or to 'hits'.
168+ * @param history the history to fetch entries from
125169 * @param out to write matched context
126170 * @param path path to the file
127- * @param hits list of hits
128- * @param wcontext web context - beginning of url
171+ * @param hits list of {@link Hit} instances
172+ * @param urlPrefix URL prefix
173+ * @return whether there was at least one line that matched
129174 */
130- private boolean getHistoryContext (
131- History in , String path , Writer out , List <Hit > hits , String wcontext ) {
132- if (in == null ) {
175+ @ VisibleForTesting
176+ boolean getHistoryContext (History history , String path , @ Nullable Writer out , @ Nullable List <Hit > hits ,
177+ String urlPrefix ) {
178+ if (history == null ) {
133179 throw new IllegalArgumentException ("`in' is null" );
134180 }
135181 if ((out == null ) == (hits == null )) {
136182 // There should be exactly one destination for the output. If
137183 // none or both are specified, it's a bug.
138- throw new IllegalArgumentException (
139- "Exactly one of out and hits should be non-null" );
184+ throw new IllegalArgumentException ("Exactly one of out and hits should be non-null" );
140185 }
141186
142187 if (m == null ) {
143188 return false ;
144189 }
145190
146191 int matchedLines = 0 ;
147- Iterator <HistoryEntry > it = in .getHistoryEntries ().iterator ();
192+ Iterator <HistoryEntry > it = history .getHistoryEntries (). stream (). filter ( HistoryEntry :: isActive ).iterator ();
148193 try {
149194 HistoryEntry he ;
150195 HistoryEntry nhe = null ;
@@ -153,10 +198,11 @@ private boolean getHistoryContext(
153198 if (nhe == null ) {
154199 he = it .next ();
155200 } else {
156- he = nhe ; //nhe is the lookahead revision
201+ he = nhe ; // nhe is the lookahead revision
157202 }
158203 String line = he .getLine ();
159204 String rev = he .getRevision ();
205+
160206 if (it .hasNext ()) {
161207 nhe = it .next ();
162208 } else {
@@ -169,40 +215,7 @@ private boolean getHistoryContext(
169215 } else {
170216 nrev = nhe .getRevision ();
171217 }
172- tokens .reInit (line );
173- String token ;
174- int matchState ;
175- long start = -1 ;
176- while ((token = tokens .next ()) != null ) {
177- for (LineMatcher lineMatcher : m ) {
178- matchState = lineMatcher .match (token );
179- if (matchState == LineMatcher .MATCHED ) {
180- if (start < 0 ) {
181- start = tokens .getMatchStart ();
182- }
183- long end = tokens .getMatchEnd ();
184- if (start > Integer .MAX_VALUE || end > Integer .MAX_VALUE ) {
185- LOGGER .log (Level .INFO , "Unexpected out of bounds for {0}" , path );
186- } else if (out == null ) {
187- StringBuilder sb = new StringBuilder ();
188- writeMatch (sb , line , (int ) start , (int ) end ,
189- true , path , wcontext , nrev , rev );
190- hits .add (new Hit (path , sb .toString (), "" , false , false ));
191- } else {
192- writeMatch (out , line , (int ) start , (int ) end ,
193- false , path , wcontext , nrev , rev );
194- }
195- matchedLines ++;
196- break ;
197- } else if (matchState == LineMatcher .WAIT ) {
198- if (start < 0 ) {
199- start = tokens .getMatchStart ();
200- }
201- } else {
202- start = -1 ;
203- }
204- }
205- }
218+ matchedLines += matchLine (line , urlPrefix , path , out , hits , rev , nrev );
206219 }
207220 } catch (Exception e ) {
208221 LOGGER .log (Level .WARNING , "Could not get history context for " + path , e );
@@ -219,24 +232,23 @@ private boolean getHistoryContext(
219232 * @param end position of the first char after the match
220233 * @param flatten should multi-line log entries be flattened to a single
221234 * @param path path to the file
222- * @param wcontext web context (begin of URL)
235+ * @param urlPrefix URL prefix
223236 * @param nrev old revision
224237 * @param rev current revision
225- * line? If {@code true}, replace newline with space.
226238 * @throws IOException IO exception
227239 */
228240 protected static void writeMatch (Appendable out , String line ,
229241 int start , int end , boolean flatten , String path ,
230- String wcontext , String nrev , String rev )
242+ String urlPrefix , String nrev , String rev )
231243 throws IOException {
232244
233245 String prefix = line .substring (0 , start );
234246 String match = line .substring (start , end );
235247 String suffix = line .substring (end );
236248
237- if (wcontext != null && nrev != null && !wcontext .isEmpty ()) {
249+ if (urlPrefix != null && nrev != null && !urlPrefix .isEmpty ()) {
238250 out .append ("<a href=\" " );
239- printHTML (out , wcontext + Prefix .DIFF_P +
251+ printHTML (out , urlPrefix + Prefix .DIFF_P +
240252 Util .uriEncodePath (path ) +
241253 "?" + QueryParameters .REVISION_2_PARAM_EQ + Util .uriEncodePath (path ) + "@" +
242254 rev + "&" + QueryParameters .REVISION_1_PARAM_EQ + Util .uriEncodePath (path ) +
0 commit comments