aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Whitton2025-04-27 11:45:54 +0800
committerSean Whitton2025-04-27 11:52:53 +0800
commit07c2b169edc2c5aaad1c8f494663a8198b2d4ca2 (patch)
tree04f09dd67ab76edec7acb4e9d6e23d824d300a20
parentd047a89e769f3c8429c43a40d5f251a895590d3a (diff)
downloademacs-07c2b169edc2c5aaad1c8f494663a8198b2d4ca2.tar.gz
emacs-07c2b169edc2c5aaad1c8f494663a8198b2d4ca2.zip
Improve syncing VC buffers before generating diffs
* lisp/vc/vc.el (vc-maybe-buffer-sync): Delete. Correct handling of indirect buffers is now implicitly achieved by vc-buffer-sync-fileset. (vc-buffer-sync-fileset): Make NOT-ESSENTIAL argument optional, new MISSING-IN-DIRS optional argument. Rewrite to handle directories named in the fileset, not only files. (vc-ediff): Replace call to vc-maybe-buffer-sync with a call to vc-buffer-sync-fileset. (vc-root-diff): Similarly replace call to vc-maybe-buffer-sync. This means the user is prompted to save additional buffers, that they likely want to save before generating the diffs. * test/lisp/vc/vc-misc-tests.el: New file.
-rw-r--r--lisp/vc/vc.el58
-rw-r--r--test/lisp/vc/vc-misc-tests.el67
2 files changed, 109 insertions, 16 deletions
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 4b7d2f7b53b..0d135854d69 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -2281,10 +2281,6 @@ state of each file in the fileset."
2281 t (list backend (list rootdir)) rev1 rev2 2281 t (list backend (list rootdir)) rev1 rev2
2282 (called-interactively-p 'interactive))))) 2282 (called-interactively-p 'interactive)))))
2283 2283
2284(defun vc-maybe-buffer-sync (not-essential)
2285 (with-current-buffer (or (buffer-base-buffer) (current-buffer))
2286 (when buffer-file-name (vc-buffer-sync not-essential))))
2287
2288;;;###autoload 2284;;;###autoload
2289(defun vc-diff (&optional historic not-essential fileset) 2285(defun vc-diff (&optional historic not-essential fileset)
2290 "Display diffs between file revisions. 2286 "Display diffs between file revisions.
@@ -2303,11 +2299,40 @@ Optional argument FILESET, if non-nil, overrides the fileset."
2303 (vc-diff-internal t fileset nil nil 2299 (vc-diff-internal t fileset nil nil
2304 (called-interactively-p 'interactive))))) 2300 (called-interactively-p 'interactive)))))
2305 2301
2306(defun vc-buffer-sync-fileset (fileset not-essential) 2302(defun vc-buffer-sync-fileset (fileset &optional not-essential missing-in-dirs)
2307 (dolist (filename (cadr fileset)) 2303 "Call `vc-buffer-sync' for most buffers visiting files in FILESET.
2308 (when-let* ((buffer (find-buffer-visiting filename))) 2304NOT-ESSENTIAL means it is okay to continue if the user says not to save.
2309 (with-current-buffer buffer 2305
2310 (vc-buffer-sync not-essential))))) 2306For files named explicitly in FILESET, this function always syncs their
2307buffers. By contrast, for directories named in FILESET, its behavior
2308depends on MISSING-IN-DIRS. For each directory named in FILESET, it
2309considers buffers visiting any file contained within that directory or
2310its subdirectories. If MISSING-IN-DIRS is nil, it syncs only those
2311buffers whose files exist on disk. Otherwise it syncs all of them."
2312 ;; This treatment of directories named in FILESET is wanted for, at
2313 ;; least, users with `vc-find-revision-no-save' set to non-nil: not
2314 ;; treating directories this way would imply calling `vc-buffer-sync'
2315 ;; on all buffers generated by \\`C-x v ~' during \\`C-x v D'.
2316 (let (dirs buffers)
2317 (dolist (name (cadr fileset))
2318 (if (file-directory-p name)
2319 (push name dirs)
2320 (when-let* ((buf (find-buffer-visiting name)))
2321 (push buf buffers))))
2322 (when dirs
2323 (setq buffers
2324 (cl-nunion buffers
2325 (match-buffers
2326 (lambda (buf)
2327 (and-let*
2328 ((file (buffer-local-value 'buffer-file-name buf))
2329 ((or missing-in-dirs (file-exists-p file)))
2330 ((cl-some (lambda (dir)
2331 (file-in-directory-p file dir))
2332 dirs)))))))))
2333 (dolist (buf buffers)
2334 (with-current-buffer buf
2335 (vc-buffer-sync not-essential)))))
2311 2336
2312;;;###autoload 2337;;;###autoload
2313(defun vc-diff-mergebase (_files rev1 rev2) 2338(defun vc-diff-mergebase (_files rev1 rev2)
@@ -2384,8 +2409,9 @@ saving the buffer."
2384 (interactive (list current-prefix-arg t)) 2409 (interactive (list current-prefix-arg t))
2385 (if historic 2410 (if historic
2386 (call-interactively 'vc-version-ediff) 2411 (call-interactively 'vc-version-ediff)
2387 (vc-maybe-buffer-sync not-essential) 2412 (let ((fileset (vc-deduce-fileset)))
2388 (vc-version-ediff (cadr (vc-deduce-fileset t)) nil nil))) 2413 (vc-buffer-sync-fileset fileset not-essential)
2414 (vc-version-ediff (cadr fileset) nil nil))))
2389 2415
2390;;;###autoload 2416;;;###autoload
2391(defun vc-root-diff (historic &optional not-essential) 2417(defun vc-root-diff (historic &optional not-essential)
@@ -2401,7 +2427,6 @@ saving the buffer."
2401 (if historic 2427 (if historic
2402 ;; We want the diff for the VC root dir. 2428 ;; We want the diff for the VC root dir.
2403 (call-interactively 'vc-root-version-diff) 2429 (call-interactively 'vc-root-version-diff)
2404 (vc-maybe-buffer-sync not-essential)
2405 (let ((backend (vc-deduce-backend)) 2430 (let ((backend (vc-deduce-backend))
2406 (default-directory default-directory) 2431 (default-directory default-directory)
2407 rootdir) 2432 rootdir)
@@ -2416,10 +2441,11 @@ saving the buffer."
2416 ;; relative to it. Bind default-directory to the root directory 2441 ;; relative to it. Bind default-directory to the root directory
2417 ;; here, this way the *vc-diff* buffer is setup correctly, so 2442 ;; here, this way the *vc-diff* buffer is setup correctly, so
2418 ;; relative file names work. 2443 ;; relative file names work.
2419 (let ((default-directory rootdir)) 2444 (let ((default-directory rootdir)
2420 (vc-diff-internal 2445 (fileset `(,backend (,rootdir))))
2421 t (list backend (list rootdir)) nil nil 2446 (vc-buffer-sync-fileset fileset not-essential)
2422 (called-interactively-p 'interactive)))))) 2447 (vc-diff-internal t fileset nil nil
2448 (called-interactively-p 'interactive))))))
2423 2449
2424;;;###autoload 2450;;;###autoload
2425(defun vc-root-dir () 2451(defun vc-root-dir ()
diff --git a/test/lisp/vc/vc-misc-tests.el b/test/lisp/vc/vc-misc-tests.el
new file mode 100644
index 00000000000..d19dda36d2f
--- /dev/null
+++ b/test/lisp/vc/vc-misc-tests.el
@@ -0,0 +1,67 @@
1;;; vc-misc-tests.el --- backend-agnostic VC tests -*- lexical-binding:t -*-
2
3;; Copyright (C) 2025 Free Software Foundation, Inc.
4
5;; Author: Sean Whitton <spwhitton@spwhitton.name>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;;; Code:
25
26(require 'ert-x)
27(require 'vc)
28
29(ert-deftest vc-test-buffer-sync-fileset ()
30 "Test `vc-buffer-sync-fileset'."
31 (cl-flet ((test-it (&rest args)
32 (let (buffers)
33 (cl-letf (((symbol-function 'vc-buffer-sync)
34 (lambda (&rest _)
35 (push (current-buffer) buffers))))
36 (apply #'vc-buffer-sync-fileset args)
37 (sort buffers)))))
38 (ert-with-temp-directory temp
39 (let* ((default-directory temp)
40 (present (find-file-noselect "present"))
41 (missing (find-file-noselect "missing"))
42 (only-present (list present))
43 (only-missing (list missing))
44 (missing+present (list missing present)))
45 (with-current-buffer present (basic-save-buffer))
46 (with-temp-file "unvisited")
47 ;; Regular behavior for files.
48 (should (equal (test-it `(Git ("missing")))
49 only-missing))
50 (should (equal (test-it `(Git ("present" "missing")))
51 missing+present))
52 ;; Regular behavior for directories.
53 (should (equal (test-it `(Git (,temp)))
54 only-present))
55 ;; Two ways to override regular behavior for directories.
56 (should (equal (test-it `(Git (,temp)) nil t)
57 missing+present))
58 (should (equal (test-it `(Git (,temp "missing")))
59 missing+present))
60 ;; Doesn't sync PRESENT twice.
61 (should (equal (test-it `(Git ("present" ,temp)))
62 only-present))
63 (should (equal (test-it `(Git ("missing" ,temp "present")))
64 missing+present))))))
65
66(provide 'vc-misc-tests)
67;;; vc-misc-tests.el ends here