2424 */
2525package org .opengrok .indexer .history ;
2626
27- import java .io .BufferedReader ;
2827import java .io .File ;
2928import java .io .IOException ;
3029import java .io .InputStream ;
3736import java .util .HashSet ;
3837import java .util .List ;
3938import java .util .ArrayList ;
40- import java .util .Arrays ;
4139import java .util .HashMap ;
4240import java .util .Map ;
4341import java .util .Set ;
5250import java .util .function .Consumer ;
5351import java .util .logging .Level ;
5452import java .util .logging .Logger ;
55- import java .util .regex .Matcher ;
56- import java .util .regex .Pattern ;
5753
5854import org .eclipse .jgit .api .BlameCommand ;
5955import org .eclipse .jgit .api .Git ;
@@ -283,17 +279,17 @@ private String getPathRelativeToCanonicalRepositoryRoot(String fullpath)
283279 }
284280
285281 /**
286- * Get the name of file in given revision. The returned file name is relative
287- * to the repository root .
282+ * Get the name of file in given revision. The returned file name is relative to the repository root.
283+ * Assumes renamed file hanndling is on .
288284 *
289- * @param fullpath file path
290- * @param changeset changeset
285+ * @param fullpath full file path
286+ * @param changeset revision ID (could be short)
291287 * @return original filename relative to the repository root
292288 * @throws java.io.IOException if I/O exception occurred
293289 * @see #getPathRelativeToCanonicalRepositoryRoot(String)
294290 */
295- String findOriginalName (String fullpath , String changeset )
296- throws IOException {
291+ String findOriginalName (String fullpath , String changeset ) throws IOException {
292+
297293 if (fullpath == null || fullpath .isEmpty ()) {
298294 throw new IOException (String .format ("Invalid file path string: %s" , fullpath ));
299295 }
@@ -303,63 +299,57 @@ String findOriginalName(String fullpath, String changeset)
303299 fullpath , changeset ));
304300 }
305301
306- String fileInRepo = getPathRelativeToCanonicalRepositoryRoot (fullpath );
307-
308- /*
309- * Get the list of file renames for given file to the specified
310- * revision.
311- */
312- String [] argv = {
313- ensureCommand (CMD_PROPERTY_KEY , CMD_FALLBACK ),
314- "log" ,
315- "--follow" ,
316- "--summary" ,
317- ABBREV_LOG ,
318- "--abbrev-commit" ,
319- "--name-status" ,
320- "--pretty=format:commit %h%n%d" ,
321- "--" ,
322- fileInRepo
323- };
324-
325- Executor executor = new Executor (Arrays .asList (argv ), new File (getDirectoryName ()),
326- RuntimeEnvironment .getInstance ().getInteractiveCommandTimeout ());
327- int status = executor .exec ();
328-
329- String originalFile = null ;
330- try (BufferedReader in = new BufferedReader (newLogReader (executor .getOutputStream ()))) {
331- String line ;
332- String rev = null ;
333- Matcher m ;
334- Pattern pattern = Pattern .compile ("^R\\ d+\\ s(.*)\\ s(.*)" );
335- while ((line = in .readLine ()) != null ) {
336- if (line .startsWith ("commit " )) {
337- rev = line .substring (7 );
302+ String fileInRepo = getGitFilePath (getPathRelativeToCanonicalRepositoryRoot (fullpath ));
303+
304+ String originalFile = fileInRepo ;
305+ try (org .eclipse .jgit .lib .Repository repository = getJGitRepository (getDirectoryName ());
306+ RevWalk walk = new RevWalk (repository )) {
307+
308+ walk .markStart (walk .parseCommit (repository .resolve (Constants .HEAD )));
309+ walk .markUninteresting (walk .lookupCommit (repository .resolve (changeset )));
310+
311+ Config config = repository .getConfig ();
312+ config .setBoolean ("diff" , null , "renames" , true );
313+ org .eclipse .jgit .diff .DiffConfig dc = config .get (org .eclipse .jgit .diff .DiffConfig .KEY );
314+ FollowFilter followFilter = FollowFilter .create (getGitFilePath (fileInRepo ), dc );
315+ walk .setTreeFilter (followFilter );
316+
317+ for (RevCommit commit : walk ) {
318+ if (commit .getParentCount () > 1 && !isMergeCommitsEnabled ()) {
338319 continue ;
339320 }
340321
341- if (changeset .equals (rev )) {
342- if (originalFile == null ) {
343- originalFile = fileInRepo ;
344- }
322+ if (commit .getId ().getName ().startsWith (changeset )) {
345323 break ;
346324 }
347325
348- if ((m = pattern .matcher (line )).find ()) {
349- // git output paths with forward slashes so transform it if needed
350- originalFile = Paths .get (m .group (1 )).toString ();
326+ if (commit .getParentCount () >= 1 ) {
327+ OutputStream outputStream = NullOutputStream .INSTANCE ;
328+ try (DiffFormatter formatter = new DiffFormatter (outputStream )) {
329+ formatter .setRepository (repository );
330+ formatter .setDetectRenames (true );
331+
332+ List <DiffEntry > diffs = formatter .scan (prepareTreeParser (repository , commit .getParent (0 )),
333+ prepareTreeParser (repository , commit ));
334+
335+ for (DiffEntry diff : diffs ) {
336+ if (diff .getChangeType () == DiffEntry .ChangeType .RENAME &&
337+ originalFile .equals (diff .getNewPath ())) {
338+ originalFile = diff .getOldPath ();
339+ }
340+ }
341+ }
351342 }
352343 }
353344 }
354345
355- if (status != 0 || originalFile == null ) {
356- LOGGER .log (Level .WARNING ,
357- "Failed to get original name in revision {2} for: \" {0}\" Exit code: {1}" ,
358- new Object []{fullpath , String .valueOf (status ), changeset });
346+ if (originalFile == null ) {
347+ LOGGER .log (Level .WARNING , "Failed to get original name in revision {0} for: \" {1}\" " ,
348+ new Object []{changeset , fullpath });
359349 return null ;
360350 }
361351
362- return originalFile ;
352+ return getNativePath ( originalFile ) ;
363353 }
364354
365355 /**
0 commit comments