@@ -83,7 +83,7 @@ public OutputChecker(
8383
8484 private readonly Lazy < bool > DoesGitWork ;
8585
86- private string [ ] RunGitCommand ( params string [ ] args )
86+ private Process StartGitProcess ( System . Text . Encoding encoding , params string [ ] args )
8787 {
8888#if DEBUG
8989 Console . WriteLine ( "Running git command: " + string . Join ( " " , args ) ) ;
@@ -97,25 +97,18 @@ private string[] RunGitCommand(params string[] args)
9797 RedirectStandardError = true ,
9898 RedirectStandardInput = true ,
9999 CreateNoWindow = true ,
100- StandardOutputEncoding = System . Text . Encoding . UTF8 ,
101- StandardErrorEncoding = System . Text . Encoding . UTF8 ,
100+ StandardOutputEncoding = encoding ,
101+ StandardErrorEncoding = encoding ,
102102 } ;
103103 foreach ( var a in args )
104104 procInfo . ArgumentList . Add ( a ) ;
105105
106106
107- var proc = Process . Start ( procInfo ) ;
108-
109- var outputLines = new List < string > ( ) ;
110- var outputReaderTask = Task . Run ( ( ) => {
111- string line = null ;
112- while ( ( line = proc . StandardOutput . ReadLine ( ) ) != null )
113- {
114- if ( line . Length > 0 )
115- outputLines . Add ( line ) ;
116- }
117- } ) ;
107+ return Process . Start ( procInfo ) ;
108+ }
118109
110+ private void HandleProcessExit ( Process proc , Task outputReaderTask , params string [ ] args )
111+ {
119112 // Literally, a Raspberry PI with a shitty SD card has faster IO than Azure Windows VM
120113 var timeout = RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ? 15_000 : 3_000 ;
121114 if ( ! proc . WaitForExit ( timeout ) )
@@ -128,10 +121,52 @@ private string[] RunGitCommand(params string[] args)
128121 throw new Exception ( $ "`git { string . Join ( " " , args ) } ` command failed: " + proc . StandardError . ReadToEnd ( ) ) ;
129122
130123 outputReaderTask . Wait ( ) ;
124+ }
125+
126+ private string [ ] RunGitCommand ( params string [ ] args )
127+ {
128+ var proc = StartGitProcess ( System . Text . Encoding . UTF8 , args ) ;
129+
130+ var outputLines = new List < string > ( ) ;
131+ var outputReaderTask = Task . Run ( ( ) =>
132+ {
133+ string line ;
134+ while ( ( line = proc . StandardOutput . ReadLine ( ) ) != null )
135+ {
136+ if ( line . Length > 0 )
137+ outputLines . Add ( line ) ;
138+ }
139+ } ) ;
140+
141+ HandleProcessExit ( proc , outputReaderTask , args ) ;
131142
132143 return outputLines . ToArray ( ) ;
133144 }
134145
146+ private byte [ ] RunGitBinaryCommand ( params string [ ] args )
147+ {
148+ const int BUFFER_SIZE = 1024 ;
149+
150+ var proc = StartGitProcess ( System . Text . Encoding . ASCII , args ) ;
151+
152+ List < char > ret = new ( ) ;
153+
154+ var outputReaderTask = Task . Run ( ( ) =>
155+ {
156+ char [ ] buffer = new char [ BUFFER_SIZE ] ;
157+
158+ int charsRead = 0 ;
159+ while ( ( charsRead = proc . StandardOutput . ReadBlock ( buffer , 0 , BUFFER_SIZE ) ) != 0 )
160+ {
161+ ret . AddRange ( buffer . AsSpan ( 0 , charsRead ) . ToArray ( ) ) ;
162+ }
163+ } ) ;
164+
165+ HandleProcessExit ( proc , outputReaderTask , args ) ;
166+
167+ return ret . ConvertAll ( c => ( byte ) c ) . ToArray ( ) ;
168+ }
169+
135170 static string [ ] ReadAllLines ( StreamReader reader )
136171 {
137172 var lines = new List < string > ( ) ;
@@ -162,7 +197,24 @@ private string GetOldContent(string file)
162197
163198 private byte [ ] GetOldBinaryContent ( string file )
164199 {
165- return File . ReadAllBytes ( file ) ;
200+ if ( DoesGitWork . Value )
201+ {
202+ var lsFiles = RunGitCommand ( "ls-files" , "-s" , file ) ;
203+ if ( lsFiles . Length == 0 )
204+ return null ;
205+
206+ var hash = lsFiles [ 0 ] . Split ( new [ ] { '\t ' , ' ' } , StringSplitOptions . RemoveEmptyEntries ) . ElementAtOrDefault ( 1 ) ;
207+ if ( String . IsNullOrEmpty ( hash ) )
208+ return null ;
209+
210+ var data = RunGitBinaryCommand ( "cat-file" , "blob" , hash ) ;
211+
212+ return data ;
213+ }
214+ else
215+ {
216+ return File . ReadAllBytes ( file ) ;
217+ }
166218 }
167219
168220 private bool IsModified ( string file )
@@ -300,7 +352,7 @@ internal void CheckOutputBinaryCore(byte[] outputBytes, string checkName, string
300352 return ;
301353 }
302354 throw new Exception (
303- $ "{ Path . GetFileName ( filename ) } has changed, the actual output differs from the previous accepted output!"
355+ $ "{ Path . GetFileName ( filename ) } has changed, the actual output differs from the previous accepted output!"
304356 + "Is the change OK? To let the test pass, stage the file in git. Confused? See https://github.com/exyi/CheckTestOutput/blob/master/trouble.md#changed-file\n "
305357 ) ;
306358 }
0 commit comments