1- use gix_diff:: blob:: unified_diff:: { ConsumeHunk , ContextSize } ;
1+ use gix_diff:: blob:: unified_diff:: { ConsumeHunk , ContextSize , NewlineSeparator } ;
22use gix_diff:: blob:: { Algorithm , UnifiedDiff } ;
33
44#[ test]
@@ -10,7 +10,12 @@ fn removed_modified_added() -> crate::Result {
1010 let actual = gix_diff:: blob:: diff (
1111 Algorithm :: Myers ,
1212 & interner,
13- UnifiedDiff :: new ( & interner, String :: new ( ) , "\n " , ContextSize :: symmetrical ( 3 ) ) ,
13+ UnifiedDiff :: new (
14+ & interner,
15+ String :: new ( ) ,
16+ NewlineSeparator :: AfterHeaderAndLine ( "\n " ) ,
17+ ContextSize :: symmetrical ( 3 ) ,
18+ ) ,
1419 ) ?;
1520
1621 // merged by context.
@@ -34,7 +39,12 @@ fn removed_modified_added() -> crate::Result {
3439 let actual = gix_diff:: blob:: diff (
3540 Algorithm :: Myers ,
3641 & interner,
37- UnifiedDiff :: new ( & interner, String :: new ( ) , "\n " , ContextSize :: symmetrical ( 1 ) ) ,
42+ UnifiedDiff :: new (
43+ & interner,
44+ String :: new ( ) ,
45+ NewlineSeparator :: AfterHeaderAndLine ( "\n " ) ,
46+ ContextSize :: symmetrical ( 1 ) ,
47+ ) ,
3848 ) ?;
3949 // Small context lines keeps hunks separate.
4050 insta:: assert_snapshot!( actual, @r"
@@ -55,7 +65,12 @@ fn removed_modified_added() -> crate::Result {
5565 let actual = gix_diff:: blob:: diff (
5666 Algorithm :: Myers ,
5767 & interner,
58- UnifiedDiff :: new ( & interner, String :: new ( ) , "\n " , ContextSize :: symmetrical ( 0 ) ) ,
68+ UnifiedDiff :: new (
69+ & interner,
70+ String :: new ( ) ,
71+ NewlineSeparator :: AfterHeaderAndLine ( "\n " ) ,
72+ ContextSize :: symmetrical ( 0 ) ,
73+ ) ,
5974 ) ?;
6075 // No context is also fine
6176 insta:: assert_snapshot!( actual, @r"
@@ -69,41 +84,15 @@ fn removed_modified_added() -> crate::Result {
6984 +twelve
7085 " ) ;
7186
72- #[ derive( Default ) ]
73- struct Recorder {
74- #[ allow( clippy:: type_complexity) ]
75- hunks : Vec < ( ( u32 , u32 ) , ( u32 , u32 ) , String ) > ,
76- }
77-
78- impl ConsumeHunk for Recorder {
79- type Out = Vec < ( ( u32 , u32 ) , ( u32 , u32 ) , String ) > ;
80-
81- fn consume_hunk (
82- & mut self ,
83- before_hunk_start : u32 ,
84- before_hunk_len : u32 ,
85- after_hunk_start : u32 ,
86- after_hunk_len : u32 ,
87- header : & str ,
88- _hunk : & [ u8 ] ,
89- ) -> std:: io:: Result < ( ) > {
90- self . hunks . push ( (
91- ( before_hunk_start, before_hunk_len) ,
92- ( after_hunk_start, after_hunk_len) ,
93- header. to_string ( ) ,
94- ) ) ;
95- Ok ( ( ) )
96- }
97-
98- fn finish ( self ) -> Self :: Out {
99- self . hunks
100- }
101- }
102-
10387 let actual = gix_diff:: blob:: diff (
10488 Algorithm :: Myers ,
10589 & interner,
106- UnifiedDiff :: new ( & interner, Recorder :: default ( ) , "\n " , ContextSize :: symmetrical ( 1 ) ) ,
90+ UnifiedDiff :: new (
91+ & interner,
92+ Recorder :: default ( ) ,
93+ NewlineSeparator :: AfterHeaderAndLine ( "\n " ) ,
94+ ContextSize :: symmetrical ( 1 ) ,
95+ ) ,
10796 ) ?;
10897 assert_eq ! (
10998 actual,
@@ -117,6 +106,119 @@ fn removed_modified_added() -> crate::Result {
117106 Ok ( ( ) )
118107}
119108
109+ #[ test]
110+ fn removed_modified_added_with_newlines_in_tokens ( ) -> crate :: Result {
111+ let a = "1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10" ;
112+ let b = "2\n 3\n 4\n 5\n six\n 7\n 8\n 9\n 10\n eleven\n twelve" ;
113+
114+ let a = gix_diff:: blob:: sources:: lines_with_terminator ( a) ;
115+ let b = gix_diff:: blob:: sources:: lines_with_terminator ( b) ;
116+ let interner = gix_diff:: blob:: intern:: InternedInput :: new ( a, b) ;
117+ let actual = gix_diff:: blob:: diff (
118+ Algorithm :: Myers ,
119+ & interner,
120+ UnifiedDiff :: new (
121+ & interner,
122+ String :: new ( ) ,
123+ NewlineSeparator :: AfterHeaderAndWhenNeeded ( "\n " ) ,
124+ ContextSize :: symmetrical ( 3 ) ,
125+ ) ,
126+ ) ?;
127+
128+ // merged by context.
129+ // newline diffs differently.
130+ insta:: assert_snapshot!( actual, @r"
131+ @@ -1,10 +1,11 @@
132+ -1
133+ 2
134+ 3
135+ 4
136+ 5
137+ -6
138+ +six
139+ 7
140+ 8
141+ 9
142+ -10
143+ +10
144+ +eleven
145+ +twelve
146+ " ) ;
147+
148+ let actual = gix_diff:: blob:: diff (
149+ Algorithm :: Myers ,
150+ & interner,
151+ UnifiedDiff :: new (
152+ & interner,
153+ String :: new ( ) ,
154+ NewlineSeparator :: AfterHeaderAndWhenNeeded ( "\n " ) ,
155+ ContextSize :: symmetrical ( 1 ) ,
156+ ) ,
157+ ) ?;
158+ // Small context lines keeps hunks separate.
159+ insta:: assert_snapshot!( actual, @r"
160+ @@ -1,2 +1,1 @@
161+ -1
162+ 2
163+ @@ -5,3 +4,3 @@
164+ 5
165+ -6
166+ +six
167+ 7
168+ @@ -9,2 +8,4 @@
169+ 9
170+ -10
171+ +10
172+ +eleven
173+ +twelve
174+ " ) ;
175+
176+ let actual = gix_diff:: blob:: diff (
177+ Algorithm :: Myers ,
178+ & interner,
179+ UnifiedDiff :: new (
180+ & interner,
181+ String :: new ( ) ,
182+ NewlineSeparator :: AfterHeaderAndWhenNeeded ( "\n " ) ,
183+ ContextSize :: symmetrical ( 0 ) ,
184+ ) ,
185+ ) ?;
186+ // No context is also fine
187+ insta:: assert_snapshot!( actual, @r"
188+ @@ -1,1 +1,0 @@
189+ -1
190+ @@ -6,1 +5,1 @@
191+ -6
192+ +six
193+ @@ -10,1 +9,3 @@
194+ -10
195+ +10
196+ +eleven
197+ +twelve
198+ " ) ;
199+
200+ let actual = gix_diff:: blob:: diff (
201+ Algorithm :: Myers ,
202+ & interner,
203+ UnifiedDiff :: new (
204+ & interner,
205+ Recorder :: default ( ) ,
206+ NewlineSeparator :: AfterHeaderAndWhenNeeded ( "\r \n " ) ,
207+ ContextSize :: symmetrical ( 1 ) ,
208+ ) ,
209+ ) ?;
210+ assert_eq ! (
211+ actual,
212+ & [
213+ ( ( 1 , 2 ) , ( 1 , 1 ) , "@@ -1,2 +1,1 @@\r \n " . to_string( ) ) ,
214+ ( ( 5 , 3 ) , ( 4 , 3 ) , "@@ -5,3 +4,3 @@\r \n " . into( ) ) ,
215+ ( ( 9 , 2 ) , ( 8 , 4 ) , "@@ -9,2 +8,4 @@\r \n " . into( ) )
216+ ]
217+ ) ;
218+
219+ Ok ( ( ) )
220+ }
221+
120222#[ test]
121223fn all_added_or_removed ( ) -> crate :: Result {
122224 let content = "1\n 2\n 3\n 4\n 5" ;
@@ -127,7 +229,12 @@ fn all_added_or_removed() -> crate::Result {
127229 let actual = gix_diff:: blob:: diff (
128230 Algorithm :: Myers ,
129231 & interner,
130- UnifiedDiff :: new ( & interner, String :: new ( ) , "\n " , ContextSize :: symmetrical ( context_lines) ) ,
232+ UnifiedDiff :: new (
233+ & interner,
234+ String :: new ( ) ,
235+ NewlineSeparator :: AfterHeaderAndLine ( "\n " ) ,
236+ ContextSize :: symmetrical ( context_lines) ,
237+ ) ,
131238 ) ?;
132239 assert_eq ! (
133240 actual,
@@ -147,7 +254,12 @@ fn all_added_or_removed() -> crate::Result {
147254 let actual = gix_diff:: blob:: diff (
148255 Algorithm :: Myers ,
149256 & interner,
150- UnifiedDiff :: new ( & interner, String :: new ( ) , "\n " , ContextSize :: symmetrical ( context_lines) ) ,
257+ UnifiedDiff :: new (
258+ & interner,
259+ String :: new ( ) ,
260+ NewlineSeparator :: AfterHeaderAndLine ( "\n " ) ,
261+ ContextSize :: symmetrical ( context_lines) ,
262+ ) ,
151263 ) ?;
152264 assert_eq ! (
153265 actual,
@@ -170,9 +282,45 @@ fn empty() -> crate::Result {
170282 let actual = gix_diff:: blob:: diff (
171283 Algorithm :: Myers ,
172284 & interner,
173- UnifiedDiff :: new ( & interner, String :: new ( ) , "\n " , ContextSize :: symmetrical ( 3 ) ) ,
285+ UnifiedDiff :: new (
286+ & interner,
287+ String :: new ( ) ,
288+ NewlineSeparator :: AfterHeaderAndLine ( "\n " ) ,
289+ ContextSize :: symmetrical ( 3 ) ,
290+ ) ,
174291 ) ?;
175292
176293 insta:: assert_snapshot!( actual, @r"" ) ;
177294 Ok ( ( ) )
178295}
296+
297+ #[ derive( Default ) ]
298+ struct Recorder {
299+ #[ allow( clippy:: type_complexity) ]
300+ hunks : Vec < ( ( u32 , u32 ) , ( u32 , u32 ) , String ) > ,
301+ }
302+
303+ impl ConsumeHunk for Recorder {
304+ type Out = Vec < ( ( u32 , u32 ) , ( u32 , u32 ) , String ) > ;
305+
306+ fn consume_hunk (
307+ & mut self ,
308+ before_hunk_start : u32 ,
309+ before_hunk_len : u32 ,
310+ after_hunk_start : u32 ,
311+ after_hunk_len : u32 ,
312+ header : & str ,
313+ _hunk : & [ u8 ] ,
314+ ) -> std:: io:: Result < ( ) > {
315+ self . hunks . push ( (
316+ ( before_hunk_start, before_hunk_len) ,
317+ ( after_hunk_start, after_hunk_len) ,
318+ header. to_string ( ) ,
319+ ) ) ;
320+ Ok ( ( ) )
321+ }
322+
323+ fn finish ( self ) -> Self :: Out {
324+ self . hunks
325+ }
326+ }
0 commit comments