From: Sean Whitton <spwhitton@spwhitton.name>
To: 64055@debbugs.gnu.org, Eli Zaretskii <eliz@gnu.org>
Cc: Morgan Smith <Morgan.J.Smith@outlook.com>,
Dmitry Gutov <dgutov@yandex.ru>
Subject: bug#64055: Implementation of modifying VC change comments for Git
Date: Fri, 18 Oct 2024 17:26:28 +0800 [thread overview]
Message-ID: <874j59wym3.fsf@melete.silentflame.com> (raw)
In-Reply-To: <DM5PR03MB3163ADD665E6B3B1D8704A2AC555A@DM5PR03MB3163.namprd03.prod.outlook.com>
[-- Attachment #1: Type: text/plain, Size: 227 bytes --]
Hello,
This patch is the rest of this feature. Eli, would you kindly test on
MS-Windows, please? Just try to edit the message for an unpushed git
commit and add some Unicode, and see if it works correctly.
--
Sean Whitton
[-- Attachment #2: 0001-Support-modifying-VC-change-comments-for-Git.patch --]
[-- Type: text/x-diff, Size: 10737 bytes --]
From 674f7b7c636a4e2ebcb4955b564f8c9c36bd3ddd Mon Sep 17 00:00:00 2001
From: Sean Whitton <spwhitton@spwhitton.name>
Date: Fri, 18 Oct 2024 17:19:45 +0800
Subject: [PATCH] Support modifying VC change comments for Git
* lisp/vc/vc-git.el (vc-git-allow-rewriting-history): New option.
(vc-git--assert-allowed-rewrite, vc-git-modify-change-comment):
New functions (bug#64055).
(vc-git--current-branch): Factor out of vc-git-dir--branch-headers.
(vc-git--log-edit-extract-headers): Factor out of vc-git-checkin.
* etc/NEWS: Announce the new support and option.
---
etc/NEWS | 15 +++++
lisp/vc/vc-git.el | 147 +++++++++++++++++++++++++++++++++++++---------
2 files changed, 134 insertions(+), 28 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index 10d86173235..d2e72bc537a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -568,6 +568,21 @@ a desktop notification when the song changes, using
customized using the new user options 'mpc-notifications-title' and
'mpc-notifications-body'.
+** VC
+
+---
+*** Using 'e' from Log View mode to modify change comments now works for Git.
+
+---
+*** New user option 'vc-git-allow-rewriting-history'.
+Many Git commands can change your copy of published change history
+without warning. If VC commands detect that this could happen, they
+will stop. You can customize this variable to permit rewriting history
+even though Emacs thinks it is dangerous.
+
+So far, this applies only to the 'log-view-modify-change-comment'
+command.
+
\f
* New Modes and Packages in Emacs 31.1
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index f77bf0cc5ff..0680d8e7353 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -252,6 +252,27 @@ vc-git-revision-complete-only-branches
:type 'boolean
:version "28.1")
+;; The default is nil because only a VC user who also possesses a lot of
+;; Git-specific knowledge can know when it is okay to rewrite history,
+;; and we can't convey to a relatively Git-naïve user the potential
+;; risks in only the space of a minibuffer y/n prompt.
+(defcustom vc-git-allow-rewriting-history nil
+ "When non-nil, permit Git operations that may rewrite published history.
+
+Many Git commands can change your copy of published change history
+without warning. If this occurs, you won't be able to pull and push in
+the ordinary way until you take special action. See \"Recovering from
+Upstream Rebase\" in the Man page git-rebase(1).
+
+Normally, Emacs refuses to run Git commands that it thinks will rewrite
+published history. If you customize this variable to a non-nil value,
+Emacs will instead prompt you to confirm that you really want to perform
+the rewrite. A value of `no-ask' means to proceed with no prompting."
+ :type '(choice (const :tag "Don't allow" nil)
+ (const :tag "Prompt to allow" t)
+ (const :tag "Allow without prompting" no-ask))
+ :version "31.1")
+
;; History of Git commands.
(defvar vc-git-history nil)
@@ -728,11 +749,13 @@ vc-git-dir-status-files
:files files
:update-function update-function)))
+(defun vc-git--current-branch ()
+ (vc-git--out-match '("symbolic-ref" "HEAD")
+ "^\\(refs/heads/\\)?\\(.+\\)$" 2))
+
(defun vc-git-dir--branch-headers ()
"Return headers for branch-related information."
- (let ((branch (vc-git--out-match
- '("symbolic-ref" "HEAD")
- "^\\(refs/heads/\\)?\\(.+\\)$" 2))
+ (let ((branch (vc-git--current-branch))
tracking remote-url)
(if branch
(when-let ((branch-merge
@@ -1082,6 +1105,17 @@ vc-git-checkin-patch
(autoload 'vc-switches "vc")
+(defun vc-git--log-edit-extract-headers (comment)
+ (cl-flet ((boolean-arg-fn (argument)
+ (lambda (v) (and (equal v "yes") (list argument)))))
+ (log-edit-extract-headers
+ `(("Author" . "--author")
+ ("Date" . "--date")
+ ("Amend" . ,(boolean-arg-fn "--amend"))
+ ("No-Verify" . ,(boolean-arg-fn "--no-verify"))
+ ("Sign-Off" . ,(boolean-arg-fn "--signoff")))
+ comment)))
+
(defun vc-git-checkin (files comment &optional _rev)
(let* ((file1 (or (car files) default-directory))
(root (vc-git-root file1))
@@ -1180,31 +1214,23 @@ vc-git-checkin
(vc-git-command nil 0 patch-file "apply" "--cached")
(delete-file patch-file))))
(when to-stash (vc-git--stash-staged-changes files)))
- (cl-flet ((boolean-arg-fn
- (argument)
- (lambda (value) (when (equal value "yes") (list argument)))))
- ;; When operating on the whole tree, better pass "-a" than ".", since "."
- ;; fails when we're committing a merge.
- (apply #'vc-git-command nil 0 (if (and only (not vc-git-patch-string)) files)
- (nconc (if msg-file (list "commit" "-F"
- (file-local-name msg-file))
- (list "commit" "-m"))
- (let ((args
- (log-edit-extract-headers
- `(("Author" . "--author")
- ("Date" . "--date")
- ("Amend" . ,(boolean-arg-fn "--amend"))
- ("No-Verify" . ,(boolean-arg-fn "--no-verify"))
- ("Sign-Off" . ,(boolean-arg-fn "--signoff")))
- comment)))
- (when msg-file
- (let ((coding-system-for-write
- (or pcsw vc-git-commits-coding-system)))
- (write-region (car args) nil msg-file))
- (setq args (cdr args)))
- args)
- (unless vc-git-patch-string
- (if only (list "--only" "--") '("-a"))))))
+ ;; When operating on the whole tree, better pass "-a" than ".",
+ ;; since "." fails when we're committing a merge.
+ (apply #'vc-git-command nil 0
+ (if (and only (not vc-git-patch-string)) files)
+ (nconc (if msg-file (list "commit" "-F"
+ (file-local-name msg-file))
+ (list "commit" "-m"))
+ (let ((args
+ (vc-git--log-edit-extract-headers comment)))
+ (when msg-file
+ (let ((coding-system-for-write
+ (or pcsw vc-git-commits-coding-system)))
+ (write-region (car args) nil msg-file))
+ (setq args (cdr args)))
+ args)
+ (unless vc-git-patch-string
+ (if only (list "--only" "--") '("-a")))))
(if (and msg-file (file-exists-p msg-file)) (delete-file msg-file))
(when to-stash
(let ((cached (make-nearby-temp-file "git-cached")))
@@ -1960,6 +1986,71 @@ vc-git-get-change-comment
(vc-git-command standard-output 1 nil
"log" "--max-count=1" "--pretty=format:%B" rev)))
+(defun vc-git--assert-allowed-rewrite (rev)
+ (when (and (not (eq vc-git-allow-rewriting-history 'no-ask))
+ ;; Check there is an upstream.
+ (with-temp-buffer
+ (vc-git--out-ok "config" "--get"
+ (format "branch.%s.merge"
+ (vc-git--current-branch)))))
+ (let ((outgoing (split-string
+ (with-output-to-string
+ (vc-git-command standard-output 0 nil "log"
+ "--pretty=format:%H"
+ "@{upstream}..HEAD")))))
+ (unless (or (cl-member rev outgoing :test #'string-prefix-p)
+ (and vc-git-allow-rewriting-history
+ (yes-or-no-p
+ (format
+"Commit %s looks to be published; are you sure you want to rewrite history?"
+ rev))))
+ (user-error "Will not rewrite likely-public Git history")))))
+
+(defun vc-git-modify-change-comment (files rev comment)
+ (vc-git--assert-allowed-rewrite rev)
+ (let* ((args (vc-git--log-edit-extract-headers comment))
+ (message (format "amend! %s\n\n%s" rev (pop args)))
+ (msg-file
+ ;; On MS-Windows, pass the message through a file, to work
+ ;; around how command line arguments must be in the system
+ ;; codepage, and therefore might not support non-ASCII.
+ ;;
+ ;; As our other arguments are static, we need not be concerned
+ ;; about the encoding of command line arguments in general.
+ ;; See `vc-git-checkin' for the more complex case.
+ (and (eq system-type 'windows-nt)
+ (let ((default-directory
+ (or (file-name-directory (or (car files)
+ default-directory))
+ default-directory)))
+ (make-nearby-temp-file "git-msg")))))
+ (unwind-protect
+ (progn
+ (when (cl-intersection '("--author" "--date") args
+ :test #'string=)
+ ;; 'git rebase --autosquash' cannot alter authorship.
+ ;; See the description of --fixup in git-commit(1).
+ (error
+"Author: and Date: not supported when modifying existing commits"))
+ (when msg-file
+ (let ((coding-system-for-write
+ (or coding-system-for-write
+ vc-git-commits-coding-system)))
+ (write-region message nil msg-file)))
+ ;; Regardless of the state of the index and working tree, this
+ ;; will always create an empty commit, thanks to --only.
+ (apply #'vc-git-command nil 0 nil
+ "commit" "--only" "--allow-empty"
+ (nconc (if msg-file
+ (list "-F" (file-local-name msg-file))
+ (list "-m" message))
+ args)))
+ (when (and msg-file (file-exists-p msg-file))
+ (delete-file msg-file))))
+ (with-environment-variables (("GIT_SEQUENCE_EDITOR" "true"))
+ (vc-git-command nil 0 nil "rebase" "--autostash" "--autosquash" "-i"
+ (format "%s~1" rev))))
+
(defvar vc-git-extra-menu-map
(let ((map (make-sparse-keymap)))
(define-key map [git-grep]
--
2.45.2
prev parent reply other threads:[~2024-10-18 9:26 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-13 22:59 bug#64055: [WIP Patch] Enable editing commit messages - vc-git-modify-change-comment Morgan Smith
2023-06-14 8:00 ` Robert Pluim
2023-06-14 11:41 ` Morgan Smith
2023-06-14 13:13 ` Robert Pluim
2023-06-14 13:54 ` Morgan Smith
2023-06-14 15:30 ` Robert Pluim
2024-10-01 2:38 ` Sean Whitton
2024-10-01 19:32 ` Dmitry Gutov
2024-10-02 0:01 ` Sean Whitton
2024-10-02 23:20 ` Dmitry Gutov
2024-10-10 2:39 ` Sean Whitton
2024-10-10 2:48 ` Sean Whitton
2024-10-17 13:27 ` Sean Whitton
2024-10-18 5:26 ` Eli Zaretskii
2024-10-18 6:20 ` Sean Whitton
2024-10-18 9:14 ` Eli Zaretskii
2024-10-18 9:30 ` Sean Whitton
2024-10-18 12:18 ` Eli Zaretskii
2024-10-18 0:46 ` Dmitry Gutov
2024-10-18 4:50 ` Sean Whitton
2023-06-17 2:40 ` Dmitry Gutov
2024-10-01 2:37 ` Sean Whitton
2024-10-01 13:35 ` Dmitry Gutov
2024-10-10 2:45 ` Sean Whitton
2024-10-10 6:12 ` Eli Zaretskii
2024-10-10 6:23 ` Sean Whitton
2024-10-10 7:36 ` Eli Zaretskii
2024-10-10 7:46 ` Sean Whitton
2024-10-18 9:26 ` Sean Whitton [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=874j59wym3.fsf@melete.silentflame.com \
--to=spwhitton@spwhitton.name \
--cc=64055@debbugs.gnu.org \
--cc=Morgan.J.Smith@outlook.com \
--cc=dgutov@yandex.ru \
--cc=eliz@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).