mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2026-09-10 07:46:51 -04:00
Fix "diff-apply-buffer applies to the wrong file"
* lisp/vc/diff-mode.el (diff-find-file-name): Inhibit the "drop dir" behavior in diffs produced by Git and Hg (bug#81210). Except for the virtual subdirectories like a/b/etc, which is moved and happens for all such diffs. Tighten the check for such virtual directory names, though (characters are the chars used by the configuration option 'diff.mnemonicPrefix'). (diff-setup-buffer-type): Recognize Hg diffs where only one revision is specified, too. * test/lisp/vc/diff-mode-tests.el (diff-mode-test-setup-buffer-type) (diff-mode-test-find-file-name-create): New tests.
This commit is contained in:
parent
14bf2a707c
commit
b6e7962700
|
|
@ -1176,6 +1176,10 @@ PREFIX is only used internally: don't use it."
|
|||
(or (ignore-errors (diff-beginning-of-file))
|
||||
(re-search-forward diff-file-header-re nil t)))
|
||||
(let ((fs (diff-hunk-file-names old)))
|
||||
(when (memq diff-buffer-type '(git hg))
|
||||
(setq fs
|
||||
(mapcar (lambda (f) (replace-regexp-in-string "\\`[icoawib]/" "" f))
|
||||
fs)))
|
||||
(if prefix (setq fs (mapcar (lambda (f) (concat prefix f)) fs)))
|
||||
(or
|
||||
;; use any previously used preference
|
||||
|
|
@ -1186,7 +1190,10 @@ PREFIX is only used internally: don't use it."
|
|||
(if (and newfile (file-exists-p newfile)) (cl-return newfile))))
|
||||
;; look for each file in turn. If none found, try again but
|
||||
;; ignoring the first level of directory, ...
|
||||
(cl-do* ((files fs (delq nil (mapcar #'diff-filename-drop-dir files)))
|
||||
(cl-do* ((files fs (and (not (and (memq diff-buffer-type '(git hg))
|
||||
(not old)
|
||||
(equal null-device (cadr files))))
|
||||
(delq nil (mapcar #'diff-filename-drop-dir files))))
|
||||
(file nil nil))
|
||||
((or (null files)
|
||||
(setq file (cl-do* ((files files (cdr files))
|
||||
|
|
@ -1212,10 +1219,6 @@ PREFIX is only used internally: don't use it."
|
|||
(let ((file (or (car fs) ""))
|
||||
(creation (equal null-device
|
||||
(car (diff-hunk-file-names (not old))))))
|
||||
(when (and (memq diff-buffer-type '(git hg))
|
||||
(string-match "/" file))
|
||||
;; Strip the dst prefix (like b/) if diff is from Git/Hg.
|
||||
(setq file (substring file (match-end 0))))
|
||||
(setq file (expand-file-name file))
|
||||
(setq file
|
||||
(read-file-name (format "Use file %s: " file)
|
||||
|
|
@ -1822,7 +1825,7 @@ modified lines of the diff."
|
|||
(setq-local diff-buffer-type
|
||||
(if (re-search-forward "^diff --git" nil t)
|
||||
'git
|
||||
(if (re-search-forward "^diff -r.*-r" nil t)
|
||||
(if (re-search-forward "^diff -r " nil t)
|
||||
'hg
|
||||
nil))))
|
||||
(when (eq diff-buffer-type 'git)
|
||||
|
|
|
|||
|
|
@ -744,5 +744,53 @@ plum
|
|||
(set-buffer-modified-p nil)
|
||||
(kill-buffer buf-after))))))
|
||||
|
||||
(ert-deftest diff-mode-test-setup-buffer-type ()
|
||||
"Check that `diff-setup-buffer-type' recognizes the diff's origin."
|
||||
(with-temp-buffer
|
||||
(insert "diff --git a/foo b/foo\n--- a/foo\n+++ b/foo\n")
|
||||
(diff-mode)
|
||||
(should (eq diff-buffer-type 'git)))
|
||||
(with-temp-buffer
|
||||
(insert "diff -r 0123456789ab foo\n--- a/foo\n+++ b/foo\n")
|
||||
(diff-mode)
|
||||
(should (eq diff-buffer-type 'hg)))
|
||||
(with-temp-buffer
|
||||
(insert "--- foo\n+++ foo\n@@ -1 +1 @@\n-a\n+b\n")
|
||||
(diff-mode)
|
||||
(should (eq diff-buffer-type nil))))
|
||||
|
||||
(ert-deftest diff-mode-test-find-file-name-create ()
|
||||
"Check `diff-find-file-name' for a Git/Hg file creation.
|
||||
It should not use existing file without subdirectory."
|
||||
(ert-with-temp-directory temp-dir
|
||||
(let ((default-directory temp-dir)
|
||||
call-dir call-initial call-mustmatch)
|
||||
;; A decoy with the same basename as the created file, but in a
|
||||
;; different directory.
|
||||
(with-temp-file (expand-file-name "created.txt" temp-dir)
|
||||
(insert "decoy\n"))
|
||||
(with-temp-buffer
|
||||
(insert "diff --git a/sub/created.txt b/sub/created.txt
|
||||
new file mode 100644
|
||||
index 0000000..3456789
|
||||
--- /dev/null
|
||||
+++ b/sub/created.txt
|
||||
@@ -0,0 +1 @@
|
||||
+new
|
||||
")
|
||||
(diff-mode)
|
||||
(goto-char (point-min))
|
||||
(let ((read-file-name-function
|
||||
(lambda (_p &optional dir _def mustmatch initial _pred)
|
||||
(setq call-dir dir
|
||||
call-initial initial
|
||||
call-mustmatch mustmatch)
|
||||
"magic")))
|
||||
(should (equal (diff-find-file-name)
|
||||
"magic"))
|
||||
(should (equal call-dir (expand-file-name "sub/" temp-dir)))
|
||||
(should (equal call-initial "created.txt"))
|
||||
(should (equal call-mustmatch nil)))))))
|
||||
|
||||
(provide 'diff-mode-tests)
|
||||
;;; diff-mode-tests.el ends here
|
||||
|
|
|
|||
Loading…
Reference in a new issue