@@ -252,16 +252,102 @@ pub fn diff(
252252 DiffLine :: MissingNL => { }
253253 }
254254 }
255+ // Let's imagine this diff file
256+ //
257+ // --- a/something
258+ // +++ b/something
259+ // @@ -2,0 +3,1 @@
260+ // + x
261+ //
262+ // In the unified diff format as implemented by GNU diff and patch,
263+ // this is an instruction to insert the x *after* the preexisting line 2,
264+ // not before. You can demonstrate it this way:
265+ //
266+ // $ echo -ne '--- a/something\t\n+++ b/something\t\n@@ -2,0 +3,1 @@\n+ x\n' > diff
267+ // $ echo -ne 'a\nb\nc\nd\n' > something
268+ // $ patch -p1 < diff
269+ // patching file something
270+ // $ cat something
271+ // a
272+ // b
273+ // x
274+ // c
275+ // d
276+ //
277+ // Notice how the x winds up at line 3, not line 2. This requires contortions to
278+ // work with our diffing algorithm, which keeps track of the "intended destination line",
279+ // not a line that things are supposed to be placed after. It's changing the first number,
280+ // not the second, that actually affects where the x goes.
281+ //
282+ // # change the first number from 2 to 3, and now the x is on line 4 (it's placed after line 3)
283+ // $ echo -ne '--- a/something\t\n+++ b/something\t\n@@ -3,0 +3,1 @@\n+ x\n' > diff
284+ // $ echo -ne 'a\nb\nc\nd\n' > something
285+ // $ patch -p1 < diff
286+ // patching file something
287+ // $ cat something
288+ // a
289+ // b
290+ // c
291+ // x
292+ // d
293+ // # change the third number from 3 to 1000, and it's obvious that it's the first number that's
294+ // # actually being read
295+ // $ echo -ne '--- a/something\t\n+++ b/something\t\n@@ -2,0 +1000,1 @@\n+ x\n' > diff
296+ // $ echo -ne 'a\nb\nc\nd\n' > something
297+ // $ patch -p1 < diff
298+ // patching file something
299+ // $ cat something
300+ // a
301+ // b
302+ // x
303+ // c
304+ // d
305+ //
306+ // Now watch what happens if I add a context line:
307+ //
308+ // $ echo -ne '--- a/something\t\n+++ b/something\t\n@@ -2,1 +3,2 @@\n+ x\n c\n' > diff
309+ // $ echo -ne 'a\nb\nc\nd\n' > something
310+ // $ patch -p1 < diff
311+ // patching file something
312+ // Hunk #1 succeeded at 3 (offset 1 line).
313+ //
314+ // It technically "succeeded", but this is a warning. We want to produce clean diffs.
315+ // Now that I have a context line, I'm supposed to say what line it's actually on, which is the
316+ // line that the x will wind up on, and not the line immediately before.
317+ //
318+ // $ echo -ne '--- a/something\t\n+++ b/something\t\n@@ -3,1 +3,2 @@\n+ x\n c\n' > diff
319+ // $ echo -ne 'a\nb\nc\nd\n' > something
320+ // $ patch -p1 < diff
321+ // patching file something
322+ // $ cat something
323+ // a
324+ // b
325+ // x
326+ // c
327+ // d
328+ //
329+ // I made this comment because this stuff is not obvious from GNU's
330+ // documentation on the format at all.
255331 if expected_count == 0 {
256332 line_number_expected -= 1
257333 }
258334 if actual_count == 0 {
259335 line_number_actual -= 1
260336 }
337+ let exp_ct = if expected_count == 1 {
338+ String :: new ( )
339+ } else {
340+ format ! ( ",{}" , expected_count)
341+ } ;
342+ let act_ct = if actual_count == 1 {
343+ String :: new ( )
344+ } else {
345+ format ! ( ",{}" , actual_count)
346+ } ;
261347 writeln ! (
262348 output,
263- "@@ -{}, {} +{}, {} @@" ,
264- line_number_expected, expected_count , line_number_actual, actual_count
349+ "@@ -{}{} +{}{} @@" ,
350+ line_number_expected, exp_ct , line_number_actual, act_ct
265351 )
266352 . expect ( "write to Vec is infallible" ) ;
267353 for line in result. lines {
0 commit comments