git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] combine-diff.c: Fix output when changes are exactly 3 lines apart

From
Matthijs Kooijman <matthijs@stdin.nl>
Date
May 15, 2013, 17:42 UTC
Message-ID
<1368639734-27746-1-git-send-email-matthijs@stdin.nl>
In-Reply-To
<20130515173312.GR25742@login.drsnuggles.stderr.nl>

When a deletion is followed by exactly 3 (or whatever the number of context lines) unchanged lines, followed by another change, the combined diff output would hide the first deletion, resulting in a malformed diff.

This happened because the 3 lines before each change are painted interesting, but also marked as no_pre_delete to prevent showing deletes that were previously marked as uninteresting. This behaviour was introduced in c86fbe53 (diff -c/--cc: do not include uninteresting deletion before leading context). However, as a side effect, this could also mark deletes that were already interesting as no_pre_delete. This would happen only if the delete was exactly 3 lines away from the next change, since lines farther away would not be touched by the "paint three lines before the change" code and lines closer would be painted by the "merge two adjacent hunks" code instead, which does not set the no_pre_delete flag.

This commit fixes this problem by only setting the no_pre_delete flag for changes that were previously uninteresting.

Signed-off-by: Matthijs Kooijman <matthijs@stdin.nl>
---
 combine-diff.c           |  7 +++++--
 t/t4038-diff-combined.sh | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/combine-diff.c b/combine-diff.c
index 77d7872..3e8bb17 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -518,8 +518,11 @@ static int give_context(struct sline *sline, unsigned long cnt, int num_parent)
 		unsigned long k;
 
 		/* Paint a few lines before the first interesting line. */
-		while (j < i)
-			sline[j++].flag |= mark | no_pre_delete;
+		while (j < i) {
+			if (!(sline[j].flag & mark))
+				sline[j].flag |= no_pre_delete;
+			sline[j++].flag |= mark;
+		}
 
 	again:
 		/* we know up to i is to be included.  where does the
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 1261dbb..a23ca7e 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -353,4 +353,51 @@ test_expect_failure 'combine diff coalesce three parents' '
 	compare_diff_patch expected actual
 '
 
+# Test for a bug reported at
+# http://thread.gmane.org/gmane.comp.version-control.git/224410
+# where a delete lines were missing from combined diff output when they
+# occurred exactly before the context lines of a later change.
+test_expect_success 'combine diff missing delete bug' '
+	git commit -m initial --allow-empty &&
+	cat <<-\EOF >test &&
+	1
+	2
+	3
+	4
+	EOF
+	git add test
+	git commit -a -m side1 &&
+	git checkout -B side1 &&
+	git checkout HEAD^ &&
+	cat <<-\EOF >test &&
+	0
+	1
+	2
+	3
+	4modified
+	EOF
+	git commit -a -m side2 &&
+	git branch -f side2 &&
+	test_must_fail git merge --no-commit side1 &&
+	cat <<-\EOF >test &&
+	1
+	2
+	3
+	4modified
+	EOF
+	git add test &&
+	git commit -a -m merge &&
+	git diff-tree -c -p HEAD >actual.tmp &&
+	sed -e "1,/^@@@/d" < actual.tmp >actual &&
+	tr -d Q <<-\EOF >expected &&
+	- 0
+	  1
+	  2
+	  3
+	 -4
+	 +4modified
+	EOF
+	compare_diff_patch expected actual
+'
+
 test_done
-- 
1.8.3.rc1
Previous: Matthijs KooijmanNext: Junio C Hamano
Message 5 of 8 in “Lines missing from git diff-tree -p -c output?”
  1. Matthijs KooijmanMay 15, 2013
  2. Matthijs KooijmanMay 15, 2013
  3. Junio C HamanoMay 15, 2013
  4. Matthijs KooijmanMay 15, 2013
  5. combine-diff.c: Fix output when changes are exactly 3 lines apartMatthijs Kooijman, May 15, 2013
  6. Junio C HamanoMay 15, 2013
  7. Matthijs KooijmanMay 15, 2013
  8. Junio C HamanoMay 15, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.