11using GitContentSearch . Interfaces ;
2- using System . Threading ;
32
43namespace GitContentSearch
54{
6- /// <summary>
7- /// Locates files in a Git repository's history using an efficient binary search approach combined with rename tracking.
8- ///
9- /// Algorithm Overview:
10- /// 1. Quick HEAD Check:
11- /// - First checks if the file exists in the latest commit (HEAD)
12- /// - If found, returns immediately without further searching
13- ///
14- /// 2. Binary Search Phase (if not found in HEAD):
15- /// - Gets a list of all commit hashes in chronological order
16- /// - Uses binary search to efficiently find any occurrence of the target file
17- /// - For each checked commit, uses 'git ls-tree' to list files and find matches
18- /// - Displays the file path when found and when it changes between commits
19- ///
20- /// 3. Rename Tracking Phase:
21- /// - Once the file is found in a commit, tracks its history forward to HEAD
22- /// - Uses 'git log --follow --name-status' to detect renames and deletions
23- /// - Maintains a chronological history of all paths the file has had
24- /// - Returns the most recent valid path and commit where the file exists
25- ///
26- /// Performance Considerations:
27- /// - First checks HEAD to avoid expensive operations when file exists in current state
28- /// - Uses binary search to quickly find first occurrence instead of scanning all commits
29- /// - Only tracks renames forward from first found commit, not entire history
30- /// - Caches commit times and reuses them to minimize git command calls
31- /// - Handles large repositories efficiently by avoiding full history traversal
32- /// </summary>
33- public class GitFileLocator : IGitFileLocator
5+ /// <summary>
6+ /// Locates files in a Git repository's history using an efficient binary search approach combined with rename tracking.
7+ ///
8+ /// Algorithm Overview:
9+ /// 1. Quick HEAD Check:
10+ /// - First checks if the file exists in the latest commit (HEAD)
11+ /// - If found, returns immediately without further searching
12+ ///
13+ /// 2. Binary Search Phase (if not found in HEAD):
14+ /// - Gets a list of all commit hashes in chronological order
15+ /// - Uses binary search to efficiently find any occurrence of the target file
16+ /// - For each checked commit, uses 'git ls-tree' to list files and find matches
17+ /// - Displays the file path when found and when it changes between commits
18+ ///
19+ /// 3. Rename Tracking Phase:
20+ /// - Once the file is found in a commit, tracks its history forward to HEAD
21+ /// - Uses 'git log --follow --name-status' to detect renames and deletions
22+ /// - Maintains a chronological history of all paths the file has had
23+ /// - Returns the most recent valid path and commit where the file exists
24+ ///
25+ /// Performance Considerations:
26+ /// - First checks HEAD to avoid expensive operations when file exists in current state
27+ /// - Uses binary search to quickly find first occurrence instead of scanning all commits
28+ /// - Only tracks renames forward from first found commit, not entire history
29+ /// - Caches commit times and reuses them to minimize git command calls
30+ /// - Handles large repositories efficiently by avoiding full history traversal
31+ /// </summary>
32+ public class GitFileLocator : IGitFileLocator
3433 {
3534 private readonly IGitHelper _gitHelper ;
3635 private readonly ISearchLogger _logger ;
@@ -110,7 +109,7 @@ public GitFileLocator(IGitHelper gitHelper, ISearchLogger logger, IProcessWrappe
110109 _gitHelper . GetRepositoryPath ( ) ,
111110 line =>
112111 {
113- if ( line . EndsWith ( fileName , StringComparison . OrdinalIgnoreCase ) )
112+ if ( Path . GetFileName ( line ) . Equals ( fileName , StringComparison . OrdinalIgnoreCase ) )
114113 {
115114 foundPath = line ;
116115 }
@@ -229,7 +228,7 @@ public GitFileLocator(IGitHelper gitHelper, ISearchLogger logger, IProcessWrappe
229228 _gitHelper . GetRepositoryPath ( ) ,
230229 line =>
231230 {
232- if ( line . EndsWith ( fileName , StringComparison . OrdinalIgnoreCase ) )
231+ if ( Path . GetFileName ( line ) . Equals ( fileName , StringComparison . OrdinalIgnoreCase ) )
233232 {
234233 foundPath = line ;
235234 }
@@ -318,7 +317,7 @@ public GitFileLocator(IGitHelper gitHelper, ISearchLogger logger, IProcessWrappe
318317 {
319318 var oldPath = parts [ 1 ] ;
320319 var newPath = parts [ 2 ] ;
321- if ( oldPath == currentFilePath )
320+ if ( Path . GetFileName ( oldPath ) . Equals ( currentFilePath , StringComparison . OrdinalIgnoreCase ) )
322321 {
323322 var commitTime = _gitHelper . GetCommitTime ( currentCommitHash ) ;
324323 _logger . WriteLine ( $ "File renamed in commit { currentCommitHash } at { commitTime } :") ;
@@ -331,7 +330,7 @@ public GitFileLocator(IGitHelper gitHelper, ISearchLogger logger, IProcessWrappe
331330 }
332331 }
333332 }
334- else if ( line . StartsWith ( "D" ) && line . EndsWith ( currentFilePath , StringComparison . OrdinalIgnoreCase ) )
333+ else if ( line . StartsWith ( "D" ) && Path . GetFileName ( line ) . Equals ( currentFilePath , StringComparison . OrdinalIgnoreCase ) )
335334 {
336335 var commitTime = _gitHelper . GetCommitTime ( currentCommitHash ) ;
337336 _logger . WriteLine ( $ "File was deleted in commit { currentCommitHash } at { commitTime } ") ;
0 commit comments