1- namespace GitContentSearch
1+ using GitContentSearch . Helpers ;
2+
3+ namespace GitContentSearch
24{
3- public class GitContentSearcher
5+ public class GitContentSearcher : IGitContentSearcher
46 {
57 private readonly IGitHelper _gitHelper ;
68 private readonly IFileSearcher _fileSearcher ;
9+ private readonly IFileManager _fileManager ;
710
8- public GitContentSearcher ( IFileSearcher fileSearcher , IProcessWrapper processWrapper )
9- {
10- _gitHelper = new GitHelper ( processWrapper ) ;
11- _fileSearcher = fileSearcher ;
12- }
13-
14- public GitContentSearcher ( IGitHelper gitHelper , IFileSearcher fileSearcher )
11+ public GitContentSearcher ( IGitHelper gitHelper , IFileSearcher fileSearcher , IFileManager fileManager )
1512 {
1613 _gitHelper = gitHelper ;
1714 _fileSearcher = fileSearcher ;
15+ _fileManager = fileManager ;
1816 }
1917
2018 public void SearchContent ( string filePath , string searchString , string earliestCommit = "" , string latestCommit = "" , TextWriter ? logWriter = null )
2119 {
22- // If no logWriter is provided, log to both console and file
23- if ( logWriter == null )
24- {
25- logWriter = new CompositeTextWriter (
26- Console . Out ,
27- new StreamWriter ( "search_log.txt" , append : true )
28- ) ;
29- }
20+ logWriter ??= new CompositeTextWriter (
21+ Console . Out ,
22+ new StreamWriter ( "search_log.txt" , append : true )
23+ ) ;
3024
3125 var commits = _gitHelper . GetGitCommits ( earliestCommit , latestCommit ) ;
26+ commits = commits . Reverse ( ) . ToArray ( ) ;
3227
3328 if ( commits == null || commits . Length == 0 )
3429 {
3530 logWriter . WriteLine ( "No commits found in the specified range." ) ;
3631 return ;
3732 }
3833
34+ int firstMatchIndex = FindFirstMatchIndex ( commits , filePath , searchString , logWriter ) ;
35+ int lastMatchIndex = FindLastMatchIndex ( commits , filePath , searchString , logWriter , firstMatchIndex ) ;
36+
37+ LogResults ( firstMatchIndex , lastMatchIndex , commits , searchString , logWriter ) ;
38+ }
39+
40+ private int FindFirstMatchIndex ( string [ ] commits , string filePath , string searchString , TextWriter logWriter )
41+ {
3942 int left = 0 ;
4043 int right = commits . Length - 1 ;
44+ int ? firstMatchIndex = null ;
4145
4246 while ( left <= right )
4347 {
4448 int mid = left + ( right - left ) / 2 ;
4549 string commit = commits [ mid ] ;
46-
47- string tempFileName = $ "temp_{ commit } { Path . GetExtension ( filePath ) } ";
50+ string tempFileName = _fileManager . GenerateTempFileName ( commit , filePath ) ;
4851
4952 try
5053 {
@@ -58,46 +61,98 @@ public void SearchContent(string filePath, string searchString, string earliestC
5861 }
5962
6063 bool found = _fileSearcher . SearchInFile ( tempFileName , searchString ) ;
64+ string commitTime = GetCommitTime ( commit , logWriter ) ;
65+
66+ logWriter . WriteLine ( $ "Checked commit: { commit } at { commitTime } , found: { found } ") ;
67+ logWriter . Flush ( ) ;
68+
69+ if ( found )
70+ {
71+ firstMatchIndex = mid ;
72+ right = mid - 1 ; // Continue searching to the left to find the first match
73+ }
74+ else
75+ {
76+ left = mid + 1 ;
77+ }
78+
79+ _fileManager . DeleteTempFile ( tempFileName ) ;
80+ }
81+
82+ return firstMatchIndex ?? - 1 ;
83+ }
84+
85+ private int FindLastMatchIndex ( string [ ] commits , string filePath , string searchString , TextWriter logWriter , int searchStartIndex )
86+ {
87+ int left = searchStartIndex == - 1 ? 0 : searchStartIndex ;
88+ int right = commits . Length - 1 ;
89+ int ? lastMatchIndex = null ;
90+
91+ while ( left <= right )
92+ {
93+ int mid = left + ( right - left ) / 2 ;
94+ string commit = commits [ mid ] ;
95+ string tempFileName = _fileManager . GenerateTempFileName ( commit , filePath ) ;
6196
62- string commitTime ;
6397 try
6498 {
65- commitTime = _gitHelper . GetCommitTime ( commit ) ;
99+ _gitHelper . RunGitShow ( commit , filePath , tempFileName ) ;
66100 }
67101 catch ( Exception ex )
68102 {
69- commitTime = $ "unknown time ({ ex . Message } )";
103+ logWriter . WriteLine ( $ "Error retrieving file at commit { commit } : { ex . Message } ") ;
104+ right = mid - 1 ;
105+ continue ;
70106 }
71107
108+ bool found = _fileSearcher . SearchInFile ( tempFileName , searchString ) ;
109+ string commitTime = GetCommitTime ( commit , logWriter ) ;
110+
72111 logWriter . WriteLine ( $ "Checked commit: { commit } at { commitTime } , found: { found } ") ;
73112 logWriter . Flush ( ) ;
74113
75114 if ( found )
76115 {
77- left = mid + 1 ;
116+ lastMatchIndex = mid ;
117+ left = mid + 1 ; // Continue searching to the right to find the last match
78118 }
79119 else
80120 {
81121 right = mid - 1 ;
82122 }
83123
84- if ( File . Exists ( tempFileName ) )
85- {
86- File . Delete ( tempFileName ) ;
87- }
124+ _fileManager . DeleteTempFile ( tempFileName ) ;
88125 }
89126
90- if ( right < 0 )
127+ return lastMatchIndex ?? - 1 ;
128+ }
129+
130+ private string GetCommitTime ( string commit , TextWriter logWriter )
131+ {
132+ try
91133 {
92- logWriter . WriteLine ( $ "Search string \" { searchString } \" does not appear in any of the checked commits.") ;
134+ return _gitHelper . GetCommitTime ( commit ) ;
135+ }
136+ catch ( Exception ex )
137+ {
138+ logWriter . WriteLine ( $ "Error retrieving commit time for { commit } : { ex . Message } ") ;
139+ return "unknown time" ;
93140 }
94- else if ( left >= commits . Length )
141+ }
142+
143+ private void LogResults ( int firstMatchIndex , int lastMatchIndex , string [ ] commits , string searchString , TextWriter logWriter )
144+ {
145+ if ( firstMatchIndex == - 1 )
95146 {
96- logWriter . WriteLine ( $ "Search string \" { searchString } \" appears in all checked commits.") ;
147+ logWriter . WriteLine ( $ "Search string \" { searchString } \" does not appear in any of the checked commits.") ;
97148 }
98149 else
99150 {
100- logWriter . WriteLine ( $ "Search string \" { searchString } \" appears in commit { commits [ right ] } .") ;
151+ logWriter . WriteLine ( $ "Search string \" { searchString } \" first appears in commit { commits [ firstMatchIndex ] } .") ;
152+ if ( lastMatchIndex != - 1 )
153+ {
154+ logWriter . WriteLine ( $ "Search string \" { searchString } \" last appears in commit { commits [ lastMatchIndex ] } .") ;
155+ }
101156 }
102157 }
103158 }
0 commit comments