commit 5995c27abb0937e8ca21a7e9b5cd891541bde430 Author: Sean Whitton Date: Fri Jun 26 15:52:38 2026 +0100 ; Fix last change. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index a9b72f471ae..7fe7e430860 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -4898,9 +4898,9 @@ tip revision are merged into the working file." ;; FIXME: Ideally we would only clear out the stored value for the ;; REMOTE-LOCATION from which we are pulling. (vc-run-delayed - (vc--repo-setprop backend 'vc-incoming-revision nil)) - (when vc-dir-buffers - (vc-dir--refresh-headers (vc-root-dir backend)))) + (vc--repo-setprop backend 'vc-incoming-revision nil) + (when vc-dir-buffers + (vc-dir--refresh-headers (vc-root-dir backend))))) ;; If VCS has `merge-news' functionality (CVS and SVN), use it. ((vc-find-backend-function backend 'merge-news) (save-some-buffers ; save buffers visiting files @@ -4943,9 +4943,9 @@ It also signals an error in a Bazaar bound branch." ;; FIXME: Ideally we would only clear out the ;; REMOTE-LOCATION to which we are pushing. (vc-run-delayed - (vc--repo-setprop backend 'vc-incoming-revision nil)) - (when vc-dir-buffers - (vc-dir--refresh-headers (vc-root-dir backend)))) + (vc--repo-setprop backend 'vc-incoming-revision nil) + (when vc-dir-buffers + (vc-dir--refresh-headers (vc-root-dir backend))))) (user-error "VC push is unsupported for `%s'" backend)))) ;;;###autoload commit 9f163754264f3b840502ecfa09b4fc551e7aabb1 Author: Sean Whitton Date: Fri Jun 26 15:51:46 2026 +0100 Refresh VC-Dir headers after pull or push * lisp/vc/vc-dir.el (vc-dir--buffers-dolist): New macro, factored out. (vc-dir-resynch-file): Use it. (vc-dir--refresh-headers): New function. * lisp/vc/vc.el (vc-pull, vc-push): Use it. diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el index f0a922e6639..8166384bbd6 100644 --- a/lisp/vc/vc-dir.el +++ b/lisp/vc/vc-dir.el @@ -1388,44 +1388,52 @@ that file." fileentries)) (vc-dir-update fileentries (current-buffer))))) +(defmacro vc-dir--buffers-dolist (status-buf &rest body) + "Bind STATUS-BUF to each of `vc-dir-buffers' in turn and execute BODY. +Also removes any out-of-date entries in `vc-dir-buffers'." + (declare (indent 1) (debug (sexp body))) + (cl-with-gensyms (drop) + `(let (,drop) + (save-current-buffer + (unwind-protect + (dolist (,status-buf vc-dir-buffers) + (if (not (buffer-live-p status-buf)) + (push ,status-buf ,drop) + (set-buffer ,status-buf) + (if (not (derived-mode-p 'vc-dir-mode)) + (push ,status-buf ,drop) + ,@body))) + ;; Remove out-of-date entries from `vc-dir-buffers'. + (setq vc-dir-buffers + (cl-nset-difference vc-dir-buffers ,drop :test #'eq))))))) + (defun vc-dir-resynch-file (&optional fname) "Update the entries for FNAME in any directory buffers that list it." - (let* ((file (file-truename (or fname buffer-file-name))) - (drop '())) - (save-current-buffer - ;; look for a vc-dir buffer that might show this file. - (dolist (status-buf vc-dir-buffers) - (if (not (buffer-live-p status-buf)) - (push status-buf drop) - (set-buffer status-buf) - (if (not (derived-mode-p 'vc-dir-mode)) - (push status-buf drop) - (let ((ddir (expand-file-name - ;; The actual contents of this VC-Dir buffer, - ;; which is what we care about here, is always - ;; relative to the toplevel value. - ;; If we invoked the current command from - ;; STATUS-BUF then it might have shadowed - ;; `default-directory' in order to do its work, - ;; but that's irrelevant to us here. - (buffer-local-toplevel-value 'default-directory)))) - (when (file-in-directory-p file ddir) - (if (file-directory-p file) - (progn - (vc-dir-resync-directory-files file) - (vc-dir--set-header ddir)) - (let* ((complete-state - ;; Pass two truenames (bug#80803, bug#80967). - (vc-dir-recompute-file-state file - (file-truename ddir))) - (state (cadr complete-state))) - (vc-dir-update (list complete-state) - status-buf - (or (not state) - (eq state 'up-to-date))))))))))) - ;; Remove out-of-date entries from vc-dir-buffers. - (setq vc-dir-buffers - (cl-nset-difference vc-dir-buffers drop :test #'eq)))) + (let ((file (file-truename (or fname buffer-file-name)))) + (vc-dir--buffers-dolist status-buf + ;; Look for a VC-Dir buffer that might show this file. + (let ((ddir (expand-file-name + ;; The actual contents of this VC-Dir buffer, which + ;; is what we care about here, is always relative to + ;; the toplevel value. If we invoked the current + ;; command from STATUS-BUF then it might have + ;; shadowed `default-directory' in order to do its + ;; work, but that's irrelevant to us here. + (buffer-local-toplevel-value 'default-directory)))) + (when (file-in-directory-p file ddir) + (if (file-directory-p file) + (progn + (vc-dir-resync-directory-files file) + (vc-dir--set-header ddir)) + (let* ((complete-state + ;; Pass two truenames (bug#80803, bug#80967). + (vc-dir-recompute-file-state file + (file-truename ddir))) + (state (cadr complete-state))) + (vc-dir-update (list complete-state) + status-buf + (or (not state) + (eq state 'up-to-date)))))))))) (defvar use-vc-backend) ;; dynamically bound @@ -1792,12 +1800,21 @@ Throw an error if another update process is in progress." (setq mode-line-process nil) (run-hooks 'vc-dir-refresh-hook)))))))))))) +(defun vc-dir--refresh-headers (directory) + "Refresh the headers for any VC-Dir buffers within DIRECTORY." + (let ((directory (expand-file-name directory))) + (vc-dir--buffers-dolist status-buf + (let ((ddir (buffer-local-toplevel-value 'default-directory))) + (when (file-in-directory-p ddir directory) + (vc-dir--set-header ddir)))))) + (defun vc-dir-show-fileentry (file) "Insert an entry for a specific file into the current *VC-Dir* listing. This is typically used if the file is up-to-date (or has been added outside of VC) and one wants to do some operation on it." (interactive "fShow file: ") - (vc-dir-update (list (list (file-relative-name file) (vc-state file))) (current-buffer))) + (vc-dir-update `((,(file-relative-name file) ,(vc-state file))) + (current-buffer))) (defun vc-dir-hide-state (&optional state) "Hide items that are in STATE from display. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index ecfca3847f0..a9b72f471ae 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -4859,6 +4859,8 @@ to the working revision (except for keyword expansion)." ;;;###autoload (defalias 'vc-restore #'vc-revert) +(declare-function vc-dir--refresh-headers "vc-dir") + ;;;###autoload (defun vc-pull (&optional arg) "Update the current fileset or branch. @@ -4896,7 +4898,9 @@ tip revision are merged into the working file." ;; FIXME: Ideally we would only clear out the stored value for the ;; REMOTE-LOCATION from which we are pulling. (vc-run-delayed - (vc--repo-setprop backend 'vc-incoming-revision nil))) + (vc--repo-setprop backend 'vc-incoming-revision nil)) + (when vc-dir-buffers + (vc-dir--refresh-headers (vc-root-dir backend)))) ;; If VCS has `merge-news' functionality (CVS and SVN), use it. ((vc-find-backend-function backend 'merge-news) (save-some-buffers ; save buffers visiting files @@ -4939,7 +4943,9 @@ It also signals an error in a Bazaar bound branch." ;; FIXME: Ideally we would only clear out the ;; REMOTE-LOCATION to which we are pushing. (vc-run-delayed - (vc--repo-setprop backend 'vc-incoming-revision nil))) + (vc--repo-setprop backend 'vc-incoming-revision nil)) + (when vc-dir-buffers + (vc-dir--refresh-headers (vc-root-dir backend)))) (user-error "VC push is unsupported for `%s'" backend)))) ;;;###autoload commit 268e055e0515ccec8159b13d4b2e97428bd63b5e Author: Sean Whitton Date: Fri Jun 26 14:53:13 2026 +0100 Limit VC-Dir status process output processing * lisp/emacs-lisp/ewoc.el (ewoc--set-buffer-bind-dll-let*): New debug declaration. (ewoc-set-hf): Make it possible to set only the header or footer. * lisp/vc/vc-dir.el (vc-dir--set-header): New RESET-FOOTER parameter. (vc-dir-refresh): Pass it. (vc-dir-process-output-limit): New variable. (vc-dir-show-more-button) (vc-dir-maybe-narrow-and-show-more-button): New functions. * lisp/vc/vc-bzr.el (vc-bzr-dir-status-files): * lisp/vc/vc-cvs.el (vc-cvs-dir-status-files): * lisp/vc/vc-git.el (vc-git-dir-status-goto-stage): * lisp/vc/vc-hg.el (vc-hg-dir-status-files): * lisp/vc/vc-svn.el (vc-svn-dir-status-files): Preserve a binding of vc-dir-process-output-limit in the delayed process. Call vc-dir-maybe-narrow-and-show-more-button. * lisp/vc/vc.el (dir-status-files): * etc/NEWS: Document the change. diff --git a/etc/NEWS b/etc/NEWS index c4e02890bbb..1537464d653 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -121,6 +121,17 @@ obsolete. To hide these, you can customize the new user option 'vc-dir-show-key-binding-hints' to nil. +--- +*** VC-Dir doesn't process very large status output by default. +If the VCS status process used to populate the VC-Dir buffer produces a +very large amount of output, it often means that you did something +accidental like renaming a subdirectory containing thousands of files, +and Emacs can become unresponsive while trying to process all the +output. Now Emacs stops early. When this happens, VC-Dir includes a +message saying so, with a button to override it. You can customize the +new user option 'vc-dir-process-output-limit' to control how early to +stop, and to disable this feature. + ** Outline mode *** New command 'outline-show-entry-and-parents'. diff --git a/lisp/emacs-lisp/ewoc.el b/lisp/emacs-lisp/ewoc.el index 387e5d3be5e..118b66eb15f 100644 --- a/lisp/emacs-lisp/ewoc.el +++ b/lisp/emacs-lisp/ewoc.el @@ -152,6 +152,7 @@ and (ewoc--node-nth dll -1) returns the last node." `dll' will be bound when VARLIST is initialized, but the current buffer will *not* have been changed. Return value of last form in FORMS." + (declare (debug (form let))) (let ((hnd (make-symbol "ewoc"))) `(let* ((,hnd ,ewoc) (dll (ewoc--dll ,hnd)) @@ -568,15 +569,21 @@ Return nil if the buffer has been deleted." (ewoc--node-data (ewoc--footer ewoc)))) (defun ewoc-set-hf (ewoc header footer) - "Set the HEADER and FOOTER of EWOC." + "Set the HEADER and/or FOOTER of EWOC. +To change only the header (respectively footer), pass nil for +FOOTER (respectively HEADER). +To clear the header (respectively footer), pass an empty string for +HEADER (respectively FOOTER)." (ewoc--set-buffer-bind-dll-let* ewoc ((head (ewoc--header ewoc)) (foot (ewoc--footer ewoc)) (hf-pp (ewoc--hf-pp ewoc))) - (setf (ewoc--node-data head) header - (ewoc--node-data foot) footer) - (ewoc--refresh-node hf-pp head dll) - (ewoc--refresh-node hf-pp foot dll))) + (when header + (setf (ewoc--node-data head) header) + (ewoc--refresh-node hf-pp head dll)) + (when footer + (setf (ewoc--node-data foot) footer) + (ewoc--refresh-node hf-pp foot dll)))) (provide 'ewoc) diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el index 3cf9b107913..a8ba9b17172 100644 --- a/lisp/vc/vc-bzr.el +++ b/lisp/vc/vc-bzr.el @@ -1030,22 +1030,29 @@ stream. Standard error output is discarded." (forward-line)) (funcall update-function result))) +(declare-function vc-dir-maybe-narrow-and-show-more-button "vc-dir") + (defun vc-bzr-dir-status-files (dir files update-function) "Return a list of conses (file . state) for DIR." - (set-process-query-on-exit-flag - (apply #'vc-bzr-command "status" (current-buffer) 'async dir "-v" "-S" files) - nil) - ;; FIXME: Consider `vc-run-delayed-success'. - (vc-run-delayed - (vc-bzr-after-dir-status update-function - ;; "bzr status" results are relative to - ;; the bzr root directory, NOT to the - ;; directory "bzr status" was invoked in. - ;; Ugh. - ;; We pass the relative directory here so - ;; that `vc-bzr-after-dir-status' can - ;; frob the results accordingly. - (file-relative-name dir (vc-bzr-root dir))))) + (require 'vc-dir) + (let ((limit vc-dir-process-output-limit)) + (set-process-query-on-exit-flag + (apply #'vc-bzr-command "status" (current-buffer) 'async dir + "-v" "-S" files) + nil) + ;; FIXME: Consider `vc-run-delayed-success'. + (vc-run-delayed + (let ((vc-dir-process-output-limit limit)) + (vc-dir-maybe-narrow-and-show-more-button) + (vc-bzr-after-dir-status update-function + ;; "bzr status" results are relative to + ;; the bzr root directory, NOT to the + ;; directory "bzr status" was invoked in. + ;; Ugh. + ;; We pass the relative directory here so + ;; that `vc-bzr-after-dir-status' can + ;; frob the results accordingly. + (file-relative-name dir (vc-bzr-root dir))))))) (defvar-keymap vc-bzr-shelve-map ;; Turn off vc-dir marking diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el index 293ebcca3e2..e5fc68ea25e 100644 --- a/lisp/vc/vc-cvs.el +++ b/lisp/vc/vc-cvs.el @@ -1077,10 +1077,15 @@ state." (if basedir result (funcall update-function result)))) +(declare-function vc-dir-maybe-narrow-and-show-more-button "vc-dir") +(defvar vc-dir-process-output-limit) + (defun vc-cvs-dir-status-files (dir files update-function) "Create a list of conses (file . state) for FILES in DIR. Query all files in DIR if files is nil." - (let ((local (vc-cvs-stay-local-p dir))) + (require 'vc-dir) + (let ((local (vc-cvs-stay-local-p dir)) + (limit vc-dir-process-output-limit)) (if (and (not files) local (not (eq local 'only-file))) (vc-cvs-dir-status-heuristic dir update-function)) (set-process-query-on-exit-flag @@ -1090,7 +1095,9 @@ Query all files in DIR if files is nil." nil) ;; FIXME: Consider `vc-run-delayed-success'. (vc-run-delayed - (vc-cvs-after-dir-status update-function)))) + (let ((vc-dir-process-output-limit limit)) + (vc-dir-maybe-narrow-and-show-more-button) + (vc-cvs-after-dir-status update-function))))) (defun vc-cvs-file-to-string (file) "Read the content of FILE and return it as a string." diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el index 189966e43f0..f0a922e6639 100644 --- a/lisp/vc/vc-dir.el +++ b/lisp/vc/vc-dir.el @@ -1632,8 +1632,10 @@ specific headers." "(\\[vc-dir-hide-up-to-date]) Hide up-to-date")) "\n")))) -(defun vc-dir--set-header (def-dir) - (ewoc-set-hf vc-ewoc (vc-dir-headers vc-dir-backend def-dir) "") +(defun vc-dir--set-header (def-dir &optional reset-footer) + (ewoc-set-hf vc-ewoc + (vc-dir-headers vc-dir-backend def-dir) + (and reset-footer "")) ;; Clear overlays in the header from the last run. (dolist (overlay (overlays-in (point-min) (length (car (ewoc-get-hf vc-ewoc))))) @@ -1694,6 +1696,55 @@ specific headers." (when vc-dir-auto-hide-up-to-date (vc-dir-hide-state))) +;; Assume that user normally has around 50 uncommitted files and the +;; status output for each is approximately 60 characters long. +(defcustom vc-dir-process-output-limit 3000 + "Maximum output from VC-Dir status process to use, in characters. +If non-nil, ignore status process output beyond this much. +If nil, process all the status process's output. +This is useful to prevent Emacs becoming unresponsive trying to process +too much status output because, say, you accidentally renamed or deleted +a subdirectory of your repository containing thousands of files." + :type 'natnum + :group 'vc + :version "32.1") + +(defun vc-dir-show-more-button (&optional text) + "Show a button to refresh VC-Dir with `vc-dir-process-output-limit' nil. +TEXT is added to the EWOC footer on a line after the button. +Called by VC backend `dir-status-files' implementations when the output +to process exceeds a non-nil `vc-dir-process-output-limit'." + (ewoc-set-hf + vc-ewoc nil + (with-temp-buffer + (insert (substitute-quotes "\nHit `")) + (insert-text-button "vc-dir-process-output-limit" + 'type 'help-variable + 'help-args '(vc-dir-process-output-limit)) + (insert (substitute-quotes "': ")) + (insert-text-button + "run again with no limit" + 'action (lambda (&rest _) + (let (vc-dir-process-output-limit) + (vc-dir-refresh))) + 'help-echo "Regenerate the VC-Dir buffer with no process output limit") + (when text (insert "\n" text)) + (buffer-string)))) + +(defun vc-dir-maybe-narrow-and-show-more-button (&optional text) + "Handle `vc-dir-process-output-limit' in `vc-dir-process-buffer'. +TEXT is passed on to `vc-dir-show-more-button'. +Called by VC backend `dir-status-files' implementations." + (when (and (natnump vc-dir-process-output-limit) + (> (buffer-size) vc-dir-process-output-limit)) + (narrow-to-region (point-min) + (save-excursion + (goto-char (+ (point-min) + vc-dir-process-output-limit)) + (pos-bol))) + (with-current-buffer vc-parent-buffer + (vc-dir-show-more-button text)))) + (defun vc-dir-refresh () "Refresh the contents of the *VC-Dir* buffer. Throw an error if another update process is in progress." @@ -1718,7 +1769,7 @@ Throw an error if another update process is in progress." vc-ewoc) ;; Bzr has serious locking problems, so setup the headers first (this is ;; mostly synchronous) rather than doing it while dir-status is running. - (vc-dir--set-header def-dir) + (vc-dir--set-header def-dir 'reset-footer) (let ((buffer (current-buffer))) (with-current-buffer vc-dir-process-buffer (setq default-directory def-dir) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index 83e624e618c..73b0df4d16b 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -722,14 +722,18 @@ or an empty string if none." ;; Follows vc-exec-after. (declare-function vc-set-async-update "vc-dispatcher" (process-buffer)) +(declare-function vc-dir-maybe-narrow-and-show-more-button "vc-dir") + (defun vc-git-dir-status-goto-stage (git-state) ;; TODO: Look into reimplementing this using `git status --porcelain=v2'. + (require 'vc-dir) (cl-flet ((git-cmd (&rest args) (set-process-query-on-exit-flag (apply #'vc-git-command (current-buffer) 'async args) nil))) (let ((files (vc-git-dir-status-state->files git-state)) - (allowed-exit 1)) + (allowed-exit 1) + (limit vc-dir-process-output-limit)) (erase-buffer) (pcase (vc-git-dir-status-state->stage git-state) ('update-index @@ -756,7 +760,10 @@ or an empty string if none." ('diff-index (git-cmd files "diff-index" "--relative" "-z" "-M" "HEAD" "--"))) (vc-run-delayed-success allowed-exit - (vc-git-after-dir-status-stage git-state))))) + (let ((vc-dir-process-output-limit limit)) + (vc-dir-maybe-narrow-and-show-more-button + "(reported states may be incorrect)") + (vc-git-after-dir-status-stage git-state)))))) (defun vc-git-dir-status-files (_dir files update-function) "Return a list of (FILE STATE EXTRA) entries for DIR." diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index a3ede6ad0ac..b3000534e7c 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -1528,6 +1528,8 @@ REV is the revision to check out into WORKFILE." ;; Follows vc-exec-after. (declare-function vc-set-async-update "vc-dispatcher" (process-buffer)) +(declare-function vc-dir-maybe-narrow-and-show-more-button "vc-dir") + (defvar vc-hg--program-version nil) (defun vc-hg--program-version () @@ -1542,18 +1544,22 @@ REV is the revision to check out into WORKFILE." (string-trim-right (match-string 1) "\\."))))))) (defun vc-hg-dir-status-files (dir files update-function) + (require 'vc-dir) ;; XXX: We can't pass DIR directly to 'hg status' because that ;; returns all ignored files if FILES is non-nil (bug#22481). - (let ((default-directory dir)) + (let ((default-directory dir) + (limit vc-dir-process-output-limit)) (set-process-query-on-exit-flag (apply #'vc-hg-command '(t nil) 'async files "status" (concat "-mardu" (if files "i")) "-C" (if (version<= "4.2" (vc-hg--program-version)) '("--config" "commands.status.relative=1") '("re:" "-I" "."))) - nil)) - (vc-run-delayed-success 0 - (vc-hg-after-dir-status update-function))) + nil) + (vc-run-delayed-success 0 + (let ((vc-dir-process-output-limit limit)) + (vc-dir-maybe-narrow-and-show-more-button) + (vc-hg-after-dir-status update-function))))) (defun vc-hg-dir-extra-headers (dir) "Generate extra status headers for a repository in DIR. diff --git a/lisp/vc/vc-src.el b/lisp/vc/vc-src.el index fbfbfa52228..6639f4e9f1e 100644 --- a/lisp/vc/vc-src.el +++ b/lisp/vc/vc-src.el @@ -176,6 +176,7 @@ For a description of possible values, see `vc-check-master-templates'." (autoload 'vc-expand-dirs "vc") +;; FIXME: Respect `vc-dir-process-output-limit'. (defun vc-src-dir-status-files (dir files update-function) (let* ((result nil) (status nil) diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el index 2aacc9229e7..3639e697c4d 100644 --- a/lisp/vc/vc-svn.el +++ b/lisp/vc/vc-svn.el @@ -222,16 +222,24 @@ A value of `default' means to use the value of `vc-resolve-conflicts'." (autoload 'vc-expand-dirs "vc") +(declare-function vc-dir-maybe-narrow-and-show-more-button "vc-dir") +(defvar vc-dir-process-output-limit) + (defun vc-svn-dir-status-files (_dir files callback) "Run \"svn status\" for DIR and update BUFFER via CALLBACK. CALLBACK is called as (CALLBACK RESULT BUFFER), where RESULT is a list of conses (FILE . STATE) for directory DIR." - ;; FIXME shouldn't this rather default to all the files in dir? - (set-process-query-on-exit-flag - (apply #'vc-svn-command (current-buffer) 'async nil "status" "-u" files) - nil) - ;; FIXME: Consider `vc-run-delayed-success'. - (vc-run-delayed (vc-svn-after-dir-status callback t))) + (require 'vc-dir) + (let ((limit vc-dir-process-output-limit)) + ;; FIXME shouldn't this rather default to all the files in dir? + (set-process-query-on-exit-flag + (apply #'vc-svn-command (current-buffer) 'async nil "status" "-u" files) + nil) + ;; FIXME: Consider `vc-run-delayed-success'. + (vc-run-delayed + (let ((vc-dir-process-output-limit limit)) + (vc-dir-maybe-narrow-and-show-more-button) + (vc-svn-after-dir-status callback t))))) (defun vc-svn-dir-extra-headers (_dir) "Generate extra status headers for a Subversion working copy." diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 734cea24113..ecfca3847f0 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -177,7 +177,9 @@ ;; ;; If a command needs to be run to compute this list, it should be ;; run asynchronously using (current-buffer) as the buffer for the -;; command. +;; command. It should respect `vc-dir-process-output-limit', usually +;; by calling `vc-dir-maybe-narrow-and-show-more-button' to narrow the +;; output buffer before processing it. ;; ;; When RESULT is computed, it should be passed back by doing: ;; (funcall UPDATE-FUNCTION RESULT nil). If the backend uses a commit 8eeb8174982feed836de9e0aa5fbc83f46b967ad Author: Sean Whitton Date: Fri Jun 26 14:20:03 2026 +0100 ; * test/lisp/vc/vc-tests/vc-test-misc.el: Fix compilation warnings. diff --git a/test/lisp/vc/vc-tests/vc-test-misc.el b/test/lisp/vc/vc-tests/vc-test-misc.el index 32c6b4d765d..4e3f883c1cd 100644 --- a/test/lisp/vc/vc-tests/vc-test-misc.el +++ b/test/lisp/vc/vc-tests/vc-test-misc.el @@ -316,7 +316,7 @@ See bug#80803 and bug#80967." (should (bobp)) (while (vc-dir--before-dotname-p) (vc-dir-next-line 1) - (should (and (looking-at "\\./$") (looking-back "^ +"))) + (should (and (looking-at "\\./$") (looking-back "^ +" (pos-bol)))) (incf n 1) (goto-char (point-min)) (forward-line n)) @@ -333,29 +333,29 @@ See bug#80803 and bug#80967." (should (equal (point) end))) (goto-char (point-min)) (vc-dir-next-directory) - (should (and (looking-at "\\./$") (looking-back "^ +"))) + (should (and (looking-at "\\./$") (looking-back "^ +" (pos-bol)))) (vc-dir-next-directory) - (should (and (looking-at "dir1/$") (looking-back "^ +"))) + (should (and (looking-at "dir1/$") (looking-back "^ +" (pos-bol)))) (vc-dir-next-directory) - (should (and (looking-at "dir1/$") (looking-back "^ +"))) + (should (and (looking-at "dir1/$") (looking-back "^ +" (pos-bol)))) (goto-char (point-max)) (vc-dir-previous-line 1) (should (looking-at "dir1/file11$")) (vc-dir-previous-line 1) - (should (and (looking-at "dir1/$") (looking-back "^ +"))) + (should (and (looking-at "dir1/$") (looking-back "^ +" (pos-bol)))) (vc-dir-previous-line 1) (should (looking-at "file01$")) (vc-dir-previous-line 1) - (should (and (looking-at "\\./$") (looking-back "^ +"))) + (should (and (looking-at "\\./$") (looking-back "^ +" (pos-bol)))) (vc-dir-previous-line 1) - (should (and (looking-at "\\./$") (looking-back "^ +"))) + (should (and (looking-at "\\./$") (looking-back "^ +" (pos-bol)))) (goto-char (point-max)) (vc-dir-previous-directory) - (should (and (looking-at "dir1/$") (looking-back "^ +"))) + (should (and (looking-at "dir1/$") (looking-back "^ +" (pos-bol)))) (vc-dir-previous-directory) - (should (and (looking-at "\\./$") (looking-back "^ +"))) + (should (and (looking-at "\\./$") (looking-back "^ +" (pos-bol)))) (vc-dir-previous-directory) - (should (and (looking-at "\\./$") (looking-back "^ +"))) + (should (and (looking-at "\\./$") (looking-back "^ +" (pos-bol)))) (kill-buffer vc-dir-buf)))))) (ert-deftest vc-test-vc-dir-mark/unmark-all-dir-entry () ; bug#81249 @@ -434,8 +434,7 @@ See bug#80803 and bug#80967." (ert-with-temp-directory tempdir (let ((default-directory tempdir) (files '("dir1/file11" "dir1/file12")) - vc-dir-buf - dir-children) + vc-dir-buf) (vc-test--create-repo-function 'Git) (dolist (file files) (make-empty-file file t)) commit 35d71606c2459333b17983f030af124a1b18e811 Author: Sean Whitton Date: Fri Jun 26 10:26:22 2026 +0100 vc-region-history: Respect vc-buffer-overriding-fileset * lisp/vc/vc.el (vc-region-history): Respect vc-buffer-overriding-fileset. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 46715d01693..734cea24113 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -4779,8 +4779,9 @@ mark." (interactive "r") (let* ((lfrom (line-number-at-pos from t)) (lto (line-number-at-pos (1- to) t)) - (file buffer-file-name) - (backend (vc-backend file)) + (fileset (vc-deduce-fileset t)) + (backend (car fileset)) + (file (caadr fileset)) (buf (get-buffer-create "*VC-history*"))) (unless backend (error "Buffer is not version controlled")) @@ -4790,7 +4791,7 @@ mark." (with-current-buffer buf (vc-call-backend backend 'region-history-mode) (setq-local log-view-vc-backend backend) - (setq-local log-view-vc-fileset (list file)) + (setq-local log-view-vc-fileset (cadr fileset)) (setq-local revert-buffer-function (lambda (_ignore-auto _noconfirm) (with-current-buffer buf