11using System ;
22using System . Collections . Generic ;
33using System . Diagnostics ;
4+ using System . IO ;
45using System . Text ;
56using System . Text . RegularExpressions ;
67using System . Threading . Tasks ;
@@ -45,22 +46,28 @@ public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespa
4546 using var proc = new Process ( ) ;
4647 proc . StartInfo = CreateGitStartInfo ( true ) ;
4748 proc . Start ( ) ;
48- using var ms = new System . IO . MemoryStream ( ) ;
49+
50+ using var ms = new MemoryStream ( ) ;
4951 await proc . StandardOutput . BaseStream . CopyToAsync ( ms , CancellationToken ) . ConfigureAwait ( false ) ;
52+
5053 var bytes = ms . ToArray ( ) ;
5154 var start = 0 ;
5255 while ( start < bytes . Length )
5356 {
5457 var end = Array . IndexOf ( bytes , ( byte ) '\n ' , start ) ;
5558 if ( end < 0 )
56- end = bytes . Length ;
57- var next = end + 1 ;
58- if ( start <= end - 1 && bytes [ end - 1 ] == '\r ' )
59- end -- ;
60- if ( ! _result . IsBinary )
61- ParseLine ( bytes [ start ..end ] ) ;
62- start = next ;
59+ {
60+ ParseLine ( bytes [ start ..] ) ;
61+ break ;
62+ }
63+
64+ ParseLine ( bytes [ start ..end ] ) ;
65+ if ( _result . IsBinary )
66+ break ;
67+
68+ start = end + 1 ;
6369 }
70+
6471 await proc . WaitForExitAsync ( CancellationToken ) . ConfigureAwait ( false ) ;
6572 }
6673 catch
@@ -84,62 +91,11 @@ public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespa
8491 private void ParseLine ( byte [ ] lineBytes )
8592 {
8693 var line = Encoding . UTF8 . GetString ( lineBytes ) ;
87-
88- if ( line . StartsWith ( "old mode " , StringComparison . Ordinal ) )
89- {
90- _result . OldMode = line . Substring ( 9 ) ;
91- return ;
92- }
93-
94- if ( line . StartsWith ( "new mode " , StringComparison . Ordinal ) )
95- {
96- _result . NewMode = line . Substring ( 9 ) ;
94+ if ( ParseFileModeChange ( line ) )
9795 return ;
98- }
9996
100- if ( line . StartsWith ( "deleted file mode " , StringComparison . Ordinal ) )
101- {
102- _result . OldMode = line . Substring ( 18 ) ;
97+ if ( ParseLFSChange ( line ) )
10398 return ;
104- }
105-
106- if ( line . StartsWith ( "new file mode " , StringComparison . Ordinal ) )
107- {
108- _result . NewMode = line . Substring ( 14 ) ;
109- return ;
110- }
111-
112- if ( _result . IsLFS )
113- {
114- var ch = line [ 0 ] ;
115- if ( ch == '-' )
116- {
117- if ( line . StartsWith ( "-oid sha256:" , StringComparison . Ordinal ) )
118- {
119- _result . LFSDiff . Old . Oid = line . Substring ( 12 ) ;
120- }
121- else if ( line . StartsWith ( "-size " , StringComparison . Ordinal ) )
122- {
123- _result . LFSDiff . Old . Size = long . Parse ( line . AsSpan ( 6 ) ) ;
124- }
125- }
126- else if ( ch == '+' )
127- {
128- if ( line . StartsWith ( "+oid sha256:" , StringComparison . Ordinal ) )
129- {
130- _result . LFSDiff . New . Oid = line . Substring ( 12 ) ;
131- }
132- else if ( line . StartsWith ( "+size " , StringComparison . Ordinal ) )
133- {
134- _result . LFSDiff . New . Size = long . Parse ( line . AsSpan ( 6 ) ) ;
135- }
136- }
137- else if ( line . StartsWith ( " size " , StringComparison . Ordinal ) )
138- {
139- _result . LFSDiff . New . Size = _result . LFSDiff . Old . Size = long . Parse ( line . AsSpan ( 6 ) ) ;
140- }
141- return ;
142- }
14399
144100 if ( _result . TextDiff . Lines . Count == 0 )
145101 {
@@ -166,7 +122,7 @@ private void ParseLine(byte[] lineBytes)
166122
167123 _oldLine = int . Parse ( match . Groups [ 1 ] . Value ) ;
168124 _newLine = int . Parse ( match . Groups [ 2 ] . Value ) ;
169- _last = new Models . TextDiffLine ( Models . TextDiffLineType . Indicator , lineBytes , 0 , 0 ) ;
125+ _last = new Models . TextDiffLine ( Models . TextDiffLineType . Indicator , line , lineBytes , 0 , 0 ) ;
170126 _result . TextDiff . Lines . Add ( _last ) ;
171127 }
172128 }
@@ -175,7 +131,7 @@ private void ParseLine(byte[] lineBytes)
175131 if ( line . Length == 0 )
176132 {
177133 ProcessInlineHighlights ( ) ;
178- _last = new Models . TextDiffLine ( Models . TextDiffLineType . Normal , Array . Empty < byte > ( ) , _oldLine , _newLine ) ;
134+ _last = new Models . TextDiffLine ( Models . TextDiffLineType . Normal , "" , [ ] , _oldLine , _newLine ) ;
179135 _result . TextDiff . Lines . Add ( _last ) ;
180136 _oldLine ++ ;
181137 _newLine ++ ;
@@ -185,29 +141,15 @@ private void ParseLine(byte[] lineBytes)
185141 var ch = line [ 0 ] ;
186142 if ( ch == '-' )
187143 {
188- if ( _oldLine == 1 && _newLine == 0 && line . StartsWith ( PREFIX_LFS_DEL , StringComparison . Ordinal ) )
189- {
190- _result . IsLFS = true ;
191- _result . LFSDiff = new Models . LFSDiff ( ) ;
192- return ;
193- }
194-
195144 _result . TextDiff . DeletedLines ++ ;
196- _last = new Models . TextDiffLine ( Models . TextDiffLineType . Deleted , lineBytes [ 1 ..] , _oldLine , 0 ) ;
145+ _last = new Models . TextDiffLine ( Models . TextDiffLineType . Deleted , line . Substring ( 1 ) , lineBytes [ 1 ..] , _oldLine , 0 ) ;
197146 _deleted . Add ( _last ) ;
198147 _oldLine ++ ;
199148 }
200149 else if ( ch == '+' )
201150 {
202- if ( _oldLine == 0 && _newLine == 1 && line . StartsWith ( PREFIX_LFS_NEW , StringComparison . Ordinal ) )
203- {
204- _result . IsLFS = true ;
205- _result . LFSDiff = new Models . LFSDiff ( ) ;
206- return ;
207- }
208-
209151 _result . TextDiff . AddedLines ++ ;
210- _last = new Models . TextDiffLine ( Models . TextDiffLineType . Added , lineBytes [ 1 ..] , 0 , _newLine ) ;
152+ _last = new Models . TextDiffLine ( Models . TextDiffLineType . Added , line . Substring ( 1 ) , lineBytes [ 1 ..] , 0 , _newLine ) ;
211153 _added . Add ( _last ) ;
212154 _newLine ++ ;
213155 }
@@ -219,19 +161,12 @@ private void ParseLine(byte[] lineBytes)
219161 {
220162 _oldLine = int . Parse ( match . Groups [ 1 ] . Value ) ;
221163 _newLine = int . Parse ( match . Groups [ 2 ] . Value ) ;
222- _last = new Models . TextDiffLine ( Models . TextDiffLineType . Indicator , lineBytes , 0 , 0 ) ;
164+ _last = new Models . TextDiffLine ( Models . TextDiffLineType . Indicator , line , lineBytes , 0 , 0 ) ;
223165 _result . TextDiff . Lines . Add ( _last ) ;
224166 }
225167 else
226168 {
227- if ( _oldLine == 1 && _newLine == 1 && line . StartsWith ( PREFIX_LFS_MODIFY , StringComparison . Ordinal ) )
228- {
229- _result . IsLFS = true ;
230- _result . LFSDiff = new Models . LFSDiff ( ) ;
231- return ;
232- }
233-
234- _last = new Models . TextDiffLine ( Models . TextDiffLineType . Normal , lineBytes [ 1 ..] , _oldLine , _newLine ) ;
169+ _last = new Models . TextDiffLine ( Models . TextDiffLineType . Normal , line . Substring ( 1 ) , lineBytes [ 1 ..] , _oldLine , _newLine ) ;
235170 _result . TextDiff . Lines . Add ( _last ) ;
236171 _oldLine ++ ;
237172 _newLine ++ ;
@@ -244,6 +179,70 @@ private void ParseLine(byte[] lineBytes)
244179 }
245180 }
246181
182+ private bool ParseFileModeChange ( string line )
183+ {
184+ if ( line . StartsWith ( "old mode " , StringComparison . Ordinal ) )
185+ {
186+ _result . OldMode = line . Substring ( 9 ) ;
187+ return true ;
188+ }
189+
190+ if ( line . StartsWith ( "new mode " , StringComparison . Ordinal ) )
191+ {
192+ _result . NewMode = line . Substring ( 9 ) ;
193+ return true ;
194+ }
195+
196+ if ( line . StartsWith ( "deleted file mode " , StringComparison . Ordinal ) )
197+ {
198+ _result . OldMode = line . Substring ( 18 ) ;
199+ return true ;
200+ }
201+
202+ if ( line . StartsWith ( "new file mode " , StringComparison . Ordinal ) )
203+ {
204+ _result . NewMode = line . Substring ( 14 ) ;
205+ return true ;
206+ }
207+
208+ return false ;
209+ }
210+
211+ private bool ParseLFSChange ( string line )
212+ {
213+ if ( _result . IsLFS )
214+ {
215+ if ( line . StartsWith ( "-oid sha256:" , StringComparison . Ordinal ) )
216+ _result . LFSDiff . Old . Oid = line . Substring ( 12 ) ;
217+ else if ( line . StartsWith ( "-size " , StringComparison . Ordinal ) )
218+ _result . LFSDiff . Old . Size = long . Parse ( line . AsSpan ( 6 ) ) ;
219+ else if ( line . StartsWith ( "+oid sha256:" , StringComparison . Ordinal ) )
220+ _result . LFSDiff . New . Oid = line . Substring ( 12 ) ;
221+ else if ( line . StartsWith ( "+size " , StringComparison . Ordinal ) )
222+ _result . LFSDiff . New . Size = long . Parse ( line . AsSpan ( 6 ) ) ;
223+ else if ( line . StartsWith ( " size " , StringComparison . Ordinal ) )
224+ _result . LFSDiff . New . Size = _result . LFSDiff . Old . Size = long . Parse ( line . AsSpan ( 6 ) ) ;
225+
226+ return true ;
227+ }
228+
229+ if ( _result . TextDiff . Lines . Count != 1 )
230+ return false ;
231+
232+ var isLFS = ( _oldLine == 1 && _newLine == 1 && line . StartsWith ( PREFIX_LFS_MODIFY , StringComparison . Ordinal ) ) ||
233+ ( _oldLine == 1 && _newLine == 0 && line . StartsWith ( PREFIX_LFS_DEL , StringComparison . Ordinal ) ) ||
234+ ( _oldLine == 0 && _newLine == 1 && line . StartsWith ( PREFIX_LFS_NEW , StringComparison . Ordinal ) ) ;
235+
236+ if ( isLFS )
237+ {
238+ _result . IsLFS = true ;
239+ _result . LFSDiff = new Models . LFSDiff ( ) ;
240+ return true ;
241+ }
242+
243+ return false ;
244+ }
245+
247246 private void ProcessInlineHighlights ( )
248247 {
249248 if ( _deleted . Count > 0 )
0 commit comments