]> git.eshelyaron.com Git - emacs.git/commitdiff
vc-checkin: Check whether the fileset or patches have changed
authorSean Whitton <spwhitton@spwhitton.name>
Sun, 6 Jul 2025 12:43:24 +0000 (13:43 +0100)
committerEshel Yaron <me@eshelyaron.com>
Thu, 24 Jul 2025 07:45:33 +0000 (09:45 +0200)
* lisp/vc/vc-dispatcher.el (vc-finish-logentry): Delay popping
to vc-parent-buffer until after calling the log operation.
That way if the log operation exits early, the current buffer
remains *vc-log*.
(vc-dir-marked-files, dired-get-marked-files): Declare.
(vc-dispatcher--explicit-marks-p): New function.
* lisp/vc/vc.el (vc-checkin): Check the user isn't likely to be
surprised by what is included in the checkin.  Specifically,
check whether the fileset or patches implied by vc-parent-buffer
are unchanged.
* doc/emacs/maintaining.texi (VC With A Merging VCS): Explain
how the fileset or patch string is fixed once *vc-log* pops up.

(cherry picked from commit 7a0bfa3ee7fa447a0fe994ac8f64bcb5752cacb2)

doc/emacs/maintaining.texi
lisp/vc/vc-dispatcher.el
lisp/vc/vc.el

index 49effd05ce9e97d1fc21324d23669f3abd398594..1a893a83860af195ababcf2aafe9432f9a92340c 100644 (file)
@@ -567,6 +567,23 @@ then applies the changes to the respective files and commits the changes
 after popping up the @file{*vc-log*} buffer to allow you to type a
 suitable commit log message.
 
+Once you type @kbd{C-x v v}, the fileset or patches cannot be changed
+without first cancelling the commit by typing @kbd{C-c C-k} in the
+@file{*vc-log*} buffer.  For example, if you change which files are
+marked in the @file{*vc-dir*} buffer after Emacs has already popped up
+the @file{*vc-log*} buffer, the old fileset will remain in effect for
+this commit.  (This is in contrast to changes made to the
+@emph{contents} of files in the fileset: all such changes will be
+included in the commit even if they are made after Emacs has popped up
+the @file{*vc-dir*} buffer.)
+
+When you cancel a commit, Emacs saves your log message.  This means that
+if you need to adjust the fileset or patches, it is easy to restart the
+commit operation again: type @w{@kbd{C-c C-k C-x v v M-p}}.  Here
+@kbd{C-c C-k} cancels the commit, @kbd{C-x v v} initiates another with
+the new fileset or patches, and finally @kbd{M-p} recalls your previous
+log message.
+
 With modern decentralized version control systems (Git, Mercurial,
 etc.), the changes are committed locally and not automatically
 propagated to the upstream repository (which is usually on a remote
index dc068adf5ff295ba112c4c6cfe32f3c41f10a837..486e07ac93d066590b73ee88bacdce5a9548d6eb 100644 (file)
@@ -864,18 +864,13 @@ the buffer contents as a comment."
   ;; save the parameters held in buffer-local variables
   (let ((logbuf (current-buffer))
        (log-operation vc-log-operation)
-        ;; FIXME: When coming from VC-Dir, we should check that the
-        ;; set of selected files is still equal to vc-log-fileset,
-        ;; to avoid surprises.
        (log-fileset vc-log-fileset)
        (log-entry (buffer-string))
        (after-hook vc-log-after-operation-hook))
-    (pop-to-buffer vc-parent-buffer)
     ;; OK, do it to it
-    (save-excursion
-      (funcall log-operation
-              log-fileset
-              log-entry))
+    (with-current-buffer vc-parent-buffer
+      (funcall log-operation log-fileset log-entry))
+    (pop-to-buffer vc-parent-buffer)
     (setq vc-log-operation nil)
 
     ;; Quit windows on logbuf.
@@ -896,6 +891,16 @@ the buffer contents as a comment."
       (derived-mode-p 'diff-mode)
       (derived-mode-p 'log-view-mode)))
 
+(declare-function vc-dir-marked-files "vc-dir")
+(declare-function dired-get-marked-files "dired")
+
+(defun vc-dispatcher--explicit-marks-p ()
+  "Are any files in the directory browser explicitly marked?"
+  (or (and (derived-mode-p 'vc-dir-mode)
+           (vc-dir-marked-files))
+      (and (derived-mode-p 'dired-mode)
+           (length> (dired-get-marked-files nil nil nil t) 1))))
+
 ;; These are unused.
 ;; (defun vc-dispatcher-in-fileset-p (fileset)
 ;;   (let ((member nil))
index cee726312fd9d524041fa6b418095e0d393071d2..18f2bb1fd8b097d8f60ac748efdf96a2846f6a00 100644 (file)
@@ -1948,6 +1948,48 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
     (lambda ()
       (vc-call-backend backend 'log-edit-mode))
     (lambda (files comment)
+      ;; Check the user isn't likely to be surprised by what is included
+      ;; in the checkin.  Once a log operation is started, the fileset
+      ;; or patch string is locked in.  In particular, it's probably too
+      ;; late to offer to change it now -- checks in hooks and/or the
+      ;; backend's Log Edit derived mode have all already okayed the
+      ;; checkin.  Restarting with the new fileset or patch is easy.
+      (let* ((start-again
+              (substitute-command-keys "\\[vc-next-action] to check in again"))
+             (instructions
+              (substitute-command-keys
+               (string-join
+                (list "type \\<log-edit-mode-map>\\[log-edit-kill-buffer] to cancel"
+                      start-again
+                      "\\[log-edit-previous-comment] to recall your message")
+                ", "))))
+        (cond (patch-string
+               (unless (or (not (derived-mode-p 'diff-mode))
+                           (equal patch-string (buffer-string))
+                           (yes-or-no-p
+                            (format-message "Patch in buffer \"%s\" \
+has changed; continue with old patch?" (current-buffer))))
+                 (user-error "%s %s"
+                             "To check in the new patch" instructions)))
+              ((vc-dispatcher-browsing)
+               (unless (or (and (length= files 1)
+                                ;; If no files in the dispatcher were
+                                ;; marked and it was just that point
+                                ;; moved to a different line, we don't
+                                ;; want to bother the user.  This isn't
+                                ;; foolproof because we don't know
+                                ;; whether FILES was selected by means
+                                ;; of marking a single file or the
+                                ;; implicit selection of the file at
+                                ;; point in the absence of any marks.
+                                (not (vc-dispatcher--explicit-marks-p)))
+                           (equal files (cadr (vc-deduce-fileset)))
+                           (yes-or-no-p
+                            (format-message "Selected file(s) in buffer \"%s\" \
+have changed; continue with old fileset?" (current-buffer))))
+                 (user-error "%s %s"
+                             "To use the new fileset" instructions)))))
+
       ;; "This log message intentionally left almost blank".
       ;; RCS 5.7 gripes about whitespace-only comments too.
       (unless (and comment (string-match "[^\t\n ]" comment))