Fossil Forum

Fossil diff output for deleted lines — non standard?
Login

Fossil diff output for deleted lines — non standard?

Fossil diff output for deleted lines — non standard?

(1.1) By Joel Dueck (joeld) on 2019-02-04 04:35:59 edited from 1.0 [link] [source]

In filing an issue with a vim plugin that professes Fossil compatibility, we’ve run up against a difference between Fossil’s diff output and that of the standalone diff command and Git’s diff output.

See here

Hmm, this line in [Fossil’s] diff output looks odd:

@@ -28,1 +0,0 @@

With one line deleted at line 28, our code would expect -28,1 +27,0 or -28 +27,0 instead. And that's exactly what the output of git diff -U0 and diff -U0 looks like.

So, either our code is too strict or fossil's diff output is broken.

I’m not an expert on diff output conventions. Is there a recognized standard by which this output from Fossil is considered valid or acceptable? (editing because I don’t mean this to sound so critical. I just genuinely want to know if there’s a place I can point at to show the plugin author that he clearly needs to account for more edge cases, or if this is actually in some sense a bug, given that it differs from the most common diff tools)

I get the same diff output with fossil 2.7 [9aa9ba8bd2] and fossil 2.8 [357d5e82ad].

(2) By Richard Hipp (drh) on 2019-02-04 12:55:27 in reply to 1.1 [link] [source]

I don't think there is a specification for diff output, or at least I've never heard of one. So the "standard" is like "do whatever it is that gnu-diff does".

Do you have a pair of files, A and B, for which the output from "fossil test-diff A B" is sufficiently different from the output of just "diff A B" to cause problems for vim? Having an actual test case will help to debug the problem.

(3) By ddumitriu on 2019-02-04 14:31:22 in reply to 2 [source]

I don't know whether this is "sufficiently different" to cause problems for vim, but the following test does differ from GNU diff, and precisely in the markers:

difftest.txt
---
alpha
beta
omega
gamma
epsilon
zetta
eta

difftest-1.txt
---
alpha
beta
gamma
delta
epsilon
zeta
eta

$ fossil test-diff --unified -c 0 difftest.txt difftest-1.txt
--- difftest.txt
+++ difftest-1.txt
@@ -3,1 +0,0 @@
-omega
@@ -0,0 +4,1 @@
+delta
@@ -6,1 +6,1 @@
-zetta
+zeta

$ diff -u0 difftest.txt difftest-1.txt
--- difftest.txt        2019-02-04 15:14:00.897315000 +0100
+++ difftest-1.txt      2019-02-04 15:14:36.442554100 +0100
@@ -3 +2,0 @@
-omega
@@ -4,0 +4 @@
+delta
@@ -6 +6 @@
-zetta
+zeta

And, for completeness:

$ git diff --no-color --no-ext-diff -U0 --no-index -- difftest.txt difftest-1.txt
diff --git a/difftest.txt b/difftest-1.txt
index 705a5d7..e88c482 100644
--- a/difftest.txt
+++ b/difftest-1.txt
@@ -3 +2,0 @@ beta
-omega
@@ -4,0 +4 @@ gamma
+delta
@@ -6 +6 @@ epsilon
-zetta
+zeta

The fossil diff differs, notably, only in the hunk ranges description (",1" may be omitted). Obviously only the start of the first range is needed (the other three values can be deducted). For this reason, it can be argued that fossil incorrectly outputs @@ -0,0 +4,1 @@ for the "omega" line.

As for specification, there is seemingly none, but maybe this comment of Guido van Rossum is useful, albeit pretty old.

(4) By ddumitriu on 2019-02-04 15:04:20 in reply to 3 [link] [source]

This seems to have to do with the number of lines of context, see this code section and the comment above it. The following patch seems to correct it, but I did not test this thoroughly. Probably some extra math has to be done, involving nContext and depending on the code 50 lines higher.

Index: src/diff.c
==================================================================
--- src/diff.c
+++ src/diff.c
@@ -443,6 +443,6 @@
		*/
	   blob_appendf(pOut,"@@ -%d,%d +%d,%d @@",
-        na ? a+skip+1 : 0, na,
-        nb ? b+skip+1 : 0, nb);
+        na ? a+skip+1 : a+skip, na,
+        nb ? b+skip+1 : b+skip, nb);
	   if( html ) blob_appendf(pOut, "</span>");
	   blob_append(pOut, "\n", 1);

(5) By Joel Dueck (joeld) on 2019-02-04 15:09:15 in reply to 3 [link] [source]

Thank you! This is exactly the type of example I was about to cook up.

And yes, the +0,0 portion of @@ -3,1 +0,0 @@ for the deleted "omega" line and the -0,0 portion of the following part @@ -0,0 +4,1 @@ that are causing problems with this particular plugin.

And to clarify for DRH/everyone, fossil's diff output isn’t causing problems with vim itself, but with a plugin, "vim-signify", that marks changes in the buffer relative to that file's most current checkin on the current branch. The plugin, after detecting that Fossil is the SCM in use, runs fossil diff --unified -c 0 -- '/path/to/file' and parses the output.

(6) By anonymous on 2019-02-04 20:29:08 in reply to 2 [link] [source]

> So the "standard" is like "do whatever it is that gnu-diff does".

Or BSD diff since that is actually more likely standardized. :-)

At any rate, I've never really seen a problem with the diff output that Fossil produces.

Here's what Fossil produces:

------------------------------------------------------------------------
$ fossil diff --checkin current
Index: file
==================================================================
--- file
+++ file
@@ -1,1 +1,2 @@
 15647
+11620

------------------------------------------------------------------------

Notice this difference though:

------------------------------------------------------------------------
$ fossil test-diff file.old file
--- file.old
+++ file
@@ -1,1 +1,2 @@
 15647
+11620
------------------------------------------------------------------------

And here's what BSD diff produces:

------------------------------------------------------------------------
$ diff -u file.old file  
--- file.old    Mon Feb  4 13:12:27 2019
+++ file        Mon Feb  4 13:12:29 2019
@@ -1 +1,2 @@
 15647
+11620
------------------------------------------------------------------------

I do see a trailing newline in the Fossil diff that isn't present in BSD diff, however, it seems to not cause any problems (interestingly enough the fossil test-diff command does not have the extra newline).  Also, the range in the Fossil diff output is different.  Fossil has a range of -1,1, while BSD produces a range of just -1.  I believe both range specifications are technically correct.

Interesting reference:

https://www.artima.com/weblogs/viewpost.jsp?thread=164293

I applied the diffs and they all produce the same file.

(7) By anonymous on 2019-02-04 20:40:59 in reply to 3 [link] [source]

> And, for completeness:

And for more completeness, BSD diff produces:

------------------------------------------------------------------------
$ diff -U 0 difftest.txt difftest-1.txt
--- difftest.txt        Mon Feb  4 13:31:28 2019
+++ difftest-1.txt      Mon Feb  4 13:31:42 2019
@@ -3 +2,0 @@
-omega
@@ -4,0 +4 @@
+delta
@@ -6 +6 @@
-zetta
+zeta
------------------------------------------------------------------------

Looks like at least in this instance, BSD diff produces the same output that git diff does.

However, attempting to apply the diff produced by fossil does not work at all.  

First the BSD diff:

$ patch < difftest.patch-bsd
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- difftest.txt       Mon Feb  4 13:31:28 2019
|+++ difftest-1.txt     Mon Feb  4 13:31:42 2019
--------------------------
Patching file difftest.txt using Plan A...
Hunk #1 succeeded at 1 (offset -1 lines).
Empty context always matches.
Hunk #2 succeeded at 3 (offset -1 lines).
Hunk #3 succeeded at 7 (offset 1 line).
done

Now the Fossil diff:

$ patch < difftest.patch-fossil
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- difftest.txt
|+++ difftest-1.txt
--------------------------
Patching file difftest.txt using Plan A...
Hunk #1 succeeded at 0.
Empty context always matches.
patch: **** misordered hunks! output would be garbled

(8) By Joel Dueck (joeld) on 2019-02-05 03:31:11 in reply to 6 [link] [source]

I've never really seen a problem with the diff output that Fossil produces.

I’m not sure what input you’re using, but it’s not reproducing the problem we’re discussing.

(9) By anonymous on 2019-02-05 15:03:07 in reply to 8 [link] [source]

> I’m not sure what input you’re using, but it’s not reproducing the problem we’re discussing.

You're right, the input was insufficient, however, with the inputs provided by another commenter, I showed that the problem is worse than the simple problem that a vim plugin isn't able to grok the Fossil diff output.  The Fossil diff output simply won't apply using a standard patch tool.

(10) By anonymous on 2019-02-05 15:04:19 in reply to 5 [link] [source]

> And to clarify for DRH/everyone, fossil's diff output isn’t causing problems with vim itself, but with a plugin, "vim-signify",

It's not just the plugin, the diff produced won't even apply cleanly with the patch command.

(11) By Joel Dueck (joeld) on 2019-02-05 15:09:17 in reply to 9 [link] [source]

I see. Since you’re posting anonymously I didn’t connect that the other responses were also yours. I get it now, thanks!

(12) By Richard Hipp (drh) on 2019-02-05 15:50:25 in reply to 4 [link] [source]

(13) By Joel Dueck (joeld) on 2019-02-09 19:04:49 in reply to 12 [link] [source]

Belated thanks to both of you! Finally got around to testing this morning, it is working well.