Skip to content

Commit 4ad5818

Browse files
committed
Add better docs; implement the trimmed ",1" feature
1 parent 765137a commit 4ad5818

File tree

1 file changed

+88
-2
lines changed

1 file changed

+88
-2
lines changed

src/lib.rs

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)