Subject: bug#41779: Fall back between vc-diff and diff-backup

From: Juri Linkov <[email-masked]>
Date: Wed, 10 Jun 2020 02:35:48 +0300

Tags: patch

>> Which reminds me -- why doesn't `C-x v =' work on normal files that have
>> backups?  I think that would be pretty nice, natural and useful...
>
> I have the same problem of sometimes typing `C-x v =' instead of `M-='
> (dired-backup-diff) on backuped files in dired, and vice versa - `M-='
> instead of `C-x v =' on VC files.

Now this annoyance finally got me - using these keys throws an error
most of the time: when files are not yet registered in vc I use `M-=',
but after registering them in vc, I continue typing the same key `M-='
and get that annoying error.  The situation with `C-x v =' is not better:
often after forgetting that a file is not yet under vc control, typing
`C-x v =' raises the same error.  Therefore, this patch to the rescue:

diff --git a/lisp/vc/diff.el b/lisp/vc/diff.el
index 9e7e771963..c94c442af8 100644
--- a/lisp/vc/diff.el
+++ b/lisp/vc/diff.el
@@ -230,10 +233,16 @@ diff-backup
     (if (backup-file-name-p file)
 	(setq bak file
 	      ori (file-name-sans-versions file))
-      (setq bak (or (diff-latest-backup-file file)
-		    (error "No backup found for %s" file))
+      (setq bak (diff-latest-backup-file file)
 	    ori file))
-    (diff bak ori switches)))
+    (if bak
+        (diff bak ori switches)
+      ;; Fall back to vc-diff
+      (if (vc-backend file)
+          (let ((vc-diff-switches switches))
+            (vc-diff-internal
+             t (list (vc-backend file) (list file)) nil nil t))
+        (error "No backup found for %s" file)))))
 
 ;;;###autoload
 (defun diff-latest-backup-file (fn)
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index c640ba0420..a0363bd774 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1888,11 +1890,15 @@ vc-diff
 The optional argument NOT-URGENT non-nil means it is ok to say no to
 saving the buffer."
   (interactive (list current-prefix-arg t))
-  (if historic
-      (call-interactively 'vc-version-diff)
-    (when buffer-file-name (vc-buffer-sync not-urgent))
-    (vc-diff-internal t (vc-deduce-fileset t) nil nil
-		      (called-interactively-p 'interactive))))
+  (if (vc-deduce-backend)
+      (if historic
+          (call-interactively 'vc-version-diff)
+        (when buffer-file-name (vc-buffer-sync not-urgent))
+        (vc-diff-internal t (vc-deduce-fileset t) nil nil
+		          (called-interactively-p 'interactive)))
+    ;; Fall back to non-vc diff-backup
+    (diff-backup (if (derived-mode-p 'dired-mode) (dired-get-filename) buffer-file-name)
+                 vc-diff-switches)))
 
 ;;;###autoload
 (defun vc-diff-mergebase (_files rev1 rev2)