From: Sean Whitton Date: Fri, 6 Jun 2025 10:52:32 +0000 (+0100) Subject: New revert-files VC backend function for faster mass reverts X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=b8ff1d0d40f2bbd1506170937f54c437ee0639a8;p=emacs.git New revert-files VC backend function for faster mass reverts * lisp/vc/vc-git.el (vc-git-revert-files): * lisp/vc/vc-hg.el (vc-hg-revert-files): * lisp/vc/vc.el (vc-revert-files): New functions. (vc-revert-files): Incorporate vc-revert's calls to message here so that the messages are displayed more consistently. (vc-next-action, vc-default-checkin-patch, vc-revert): Use vc-revert-files instead of vc-revert-file. (cherry picked from commit 757f6cb0ac710533d5e18035e8b20a4bc7dcdc7c) --- diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index 4409af63041..fe75bd60f88 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -1333,12 +1333,17 @@ It is based on `log-edit-mode', and has Git-specific extensions." (vc-git-command nil 0 file "checkout" (or rev "HEAD"))) (defun vc-git-revert (file &optional contents-done) - "Revert FILE to the version stored in the git repository." + "Revert FILE to the version stored in the Git repository." (if contents-done (vc-git-command nil 0 file "update-index" "--") (vc-git-command nil 0 file "reset" "-q" "--") (vc-git-command nil nil file "checkout" "-q" "--"))) +(defun vc-git-revert-files (files) + "Revert FILES to the versions stored in the Git repository." + (vc-git-command nil 0 files "reset" "-q" "--") + (vc-git-command nil nil files "checkout" "-q" "--")) + (defvar vc-git-error-regexp-alist '(("^ \\(.+\\)\\> *|" 1 nil nil 0)) "Value of `compilation-error-regexp-alist' in *vc-git* buffers.") diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index 04a85fadd92..31506ee6493 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -1315,11 +1315,14 @@ REV is the revision to check out into WORKFILE." (defun vc-hg-revert (file &optional contents-done) (unless contents-done (with-temp-buffer - (apply #'vc-hg-command - t 0 file - "revert" + (apply #'vc-hg-command t 0 file "revert" (append (vc-switches 'hg 'revert)))))) +(defun vc-hg-revert-files (files) + (with-temp-buffer + (apply #'vc-hg-command t 0 files "revert" + (append (vc-switches 'hg 'revert))))) + ;;; Hg specific functionality. (defvar-keymap vc-hg-extra-menu-map) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 5c61f9b605b..86eed61f70f 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -280,6 +280,12 @@ ;; If FILE is in the `added' state it should be returned to the ;; `unregistered' state. ;; +;; - revert-files (files) +;; +;; As revert, except that the first argument is a list of files, all +;; of which require reversion, and reversion from version backups is +;; not done. Backends can implement this for faster mass reverts. +;; ;; - merge-file (file &optional rev1 rev2) ;; ;; Merge the changes between REV1 and REV2 into the current working @@ -1542,19 +1548,22 @@ from which to check out the file(s)." (read-only-mode -1))))))) ;; Allow user to revert files with no changes (save-excursion - (dolist (file files) - (let ((visited (get-file-buffer file))) - ;; For files with locking, if the file does not contain - ;; any changes, just let go of the lock, i.e. revert. - (when (and (not (eq model 'implicit)) - (eq state 'up-to-date) - ;; If buffer is modified, that means the user just - ;; said no to saving it; in that case, don't revert, - ;; because the user might intend to save after - ;; finishing the log entry and committing. - (not (and visited (buffer-modified-p visited)))) - (vc-revert-file file) - (setq ready-for-commit (delete file ready-for-commit)))))) + (let (to-revert) + (dolist (file files) + (let ((visited (get-file-buffer file))) + ;; For files with locking, if the file does not contain + ;; any changes, just let go of the lock, i.e. revert. + (when (and (not (eq model 'implicit)) + (eq state 'up-to-date) + ;; If buffer is modified, that means the user just + ;; said no to saving it; in that case, don't revert, + ;; because the user might intend to save after + ;; finishing the log entry and committing. + (not (and visited (buffer-modified-p visited)))) + (push file to-revert)))) + (vc-revert-files backend to-revert) + (setq ready-for-commit + (cl-nset-difference ready-for-commit to-revert)))) ;; Remaining files need to be committed (if (not ready-for-commit) (message "No files remain to be committed") @@ -1946,9 +1955,11 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'." (expand-file-name f tmpdir))) (unwind-protect (progn - (dolist (f files) - (with-current-buffer (find-file-noselect f) - (vc-revert-file buffer-file-name))) + (vc-revert-files backend + (mapcar (lambda (f) + (with-current-buffer (find-file-noselect f) + buffer-file-name)) + files)) (with-temp-buffer ;; Trying to support CVS too. Assuming that vc-diff ;; there will usually have diff root in default-directory. @@ -3350,6 +3361,7 @@ This asks for confirmation if the buffer contents are not identical to the working revision (except for keyword expansion)." (interactive) (let* ((vc-fileset (vc-deduce-fileset)) + (backend (car vc-fileset)) (files (cadr vc-fileset)) (queried nil) diff-buffer) @@ -3392,10 +3404,7 @@ to the working revision (except for keyword expansion)." (error "Revert canceled"))) (when diff-buffer (quit-windows-on diff-buffer (eq vc-revert-show-diff 'kill)))) - (dolist (file files) - (message "Reverting %s..." (vc-delistify files)) - (vc-revert-file file) - (message "Reverting %s...done" (vc-delistify files))))) + (vc-revert-files backend files))) ;;;###autoload (defun vc-pull (&optional arg) @@ -3528,6 +3537,23 @@ If FILE is a directory, revert all files inside that directory." (file-attributes file))))) (vc-resynch-buffer file t t)) +(defun vc-revert-files (backend files) + "Revert each of FILES to the repository working version it was based on. +For entries in FILES that are directories, revert all files inside them." + (when files + (message "Reverting %s..." (vc-delistify files)) + (if (not (vc-find-backend-function backend 'revert-files)) + (mapc #'vc-revert-file files) + (with-vc-properties files + (vc-call-backend backend 'revert-files files) + `((vc-state . up-to-date))) + (dolist (file files) + (vc-file-setprop file 'vc-checkout-time + (file-attribute-modification-time + (file-attributes file))) + (vc-resynch-buffer file t t))) + (message "Reverting %s...done" (vc-delistify files)))) + ;;;###autoload (defun vc-change-backend (file backend) "Make BACKEND the current version control system for FILE.