Subject: Re: bug#72556: 29.1.90; vc-diff does not undo hunk in end of source file

From: Tomas Nordin <[email-masked]>
Date: Wed, 12 Mar 2025 22:19:54 +0000

Dmitry Gutov <[email-masked]> writes:

> On 12/03/2025 00:33, Tomas Nordin wrote:
>> In the meantime I wrote two test cases in
>> test/lisp/vc/diff-mode-tests.el, one for a topmost and one for a
>> bottommost addition. They both fail before the patch but pass after it.
>> Maybe I could present them here as an attached patch as well?
>
> Yes, please!

Here it is, on top of todays master

>From 6b2760a686517cfb3a9822a5dd425250ca62c808 Mon Sep 17 00:00:00 2001
From: Tomas Nordin <[email-masked]>
Date: Sun, 2 Mar 2025 19:01:07 +0100
Subject: [PATCH 1/2] Tests for diff-mode undos

* test/lisp/vc/diff-mode-tests.el: Add tests for undoing hunks
from diffs with addtions only in the beginning or end of the
source file.  (bug#72556)
---
 test/lisp/vc/diff-mode-tests.el | 96 +++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/test/lisp/vc/diff-mode-tests.el b/test/lisp/vc/diff-mode-tests.el
index bbd66824e48..0dd8e3c5013 100644
--- a/test/lisp/vc/diff-mode-tests.el
+++ b/test/lisp/vc/diff-mode-tests.el
@@ -597,5 +597,101 @@ diff-mode-test-git-patch/signature
      (should (eq (get-text-property (match-beginning 0) 'face)
                   'diff-context)))))
 
+(ert-deftest diff-mode-test-topmost-addition-undo ()
+  (let ((patch "diff --git a/fruits b/fruits
+index 0dcecd3..d0eb2e7 100644
+--- a/fruits
++++ b/fruits
+@@ -1,2 +1,3 @@
++fruits
+ apple
+ orange
+")
+        (text-before "apple
+orange
+")
+        (text-after "fruits
+apple
+orange
+"))
+    (ert-with-temp-directory temp-dir
+      (let ((buf-after
+             (find-file-noselect (format "%s/%s" temp-dir "fruits"))))
+        (cd temp-dir)
+
+        (with-current-buffer buf-after (insert text-after) (save-buffer))
+        (with-temp-buffer
+          (insert patch)
+          (goto-char (point-min))
+          (diff-hunk-next)
+          ;; Undo hunk by non-nil REVERSE argument (C-u C-c C-a)
+          (diff-apply-hunk '(4)))
+        (with-current-buffer buf-after
+          (should (string-equal (buffer-string) text-before)))
+
+        (with-current-buffer buf-after
+          (erase-buffer) (insert text-after) (save-buffer))
+        (with-temp-buffer
+          (insert patch)
+          (goto-char (point-min))
+          (diff-hunk-next)
+          ;; Undo hunk by dwim behaviour
+          (cl-letf (((symbol-function 'y-or-n-p) #'always))
+            (diff-apply-hunk)))
+        (with-current-buffer buf-after
+          (should (string-equal (buffer-string) text-before)))
+
+        (with-current-buffer buf-after
+          (set-buffer-modified-p nil)
+          (kill-buffer buf-after))))))
+
+(ert-deftest diff-mode-test-bottommost-addition-undo ()
+  (let ((patch "diff --git a/fruits b/fruits
+index 0dcecd3..6f210ff 100644
+--- a/fruits
++++ b/fruits
+@@ -1,2 +1,3 @@
+ apple
+ orange
++plum
+")
+        (text-before "apple
+orange
+")
+        (text-after "apple
+orange
+plum
+"))
+    (ert-with-temp-directory temp-dir
+      (let ((buf-after
+             (find-file-noselect (format "%s/%s" temp-dir "fruits"))))
+        (cd temp-dir)
+
+        (with-current-buffer buf-after (insert text-after) (save-buffer))
+        (with-temp-buffer
+          (insert patch)
+          (goto-char (point-min))
+          (diff-hunk-next)
+          ;; Undo hunk by non-nil REVERSE argument (C-u C-c C-a)
+          (diff-apply-hunk '(4)))
+        (with-current-buffer buf-after
+          (should (string-equal (buffer-string) text-before)))
+
+        (with-current-buffer buf-after
+          (erase-buffer) (insert text-after) (save-buffer))
+        (with-temp-buffer
+          (insert patch)
+          (goto-char (point-min))
+          (diff-hunk-next)
+          ;; Undo hunk by dwim behaviour
+          (cl-letf (((symbol-function 'y-or-n-p) #'always))
+            (diff-apply-hunk)))
+        (with-current-buffer buf-after
+          (should (string-equal (buffer-string) text-before)))
+
+        (with-current-buffer buf-after
+          (set-buffer-modified-p nil)
+          (kill-buffer buf-after))))))
+
 (provide 'diff-mode-tests)
 ;;; diff-mode-tests.el ends here
-- 
2.39.5