aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Whitton2025-09-27 21:36:51 +0100
committerSean Whitton2025-09-27 21:36:51 +0100
commit4e7cb37b8440bf63ce5ef715282bfbf9b263128a (patch)
treeea2621586b321e908175f58d8fcc0b8a38c9b9bf
parent1d03eb590ca8bbc7d4a0d9432a8eb17d968614a3 (diff)
downloademacs-4e7cb37b8440bf63ce5ef715282bfbf9b263128a.tar.gz
emacs-4e7cb37b8440bf63ce5ef715282bfbf9b263128a.zip
VC prepare-patch: New :patch-start & :patch-end plist entries
* lisp/vc/vc.el (prepare-patch): Specify :patch-start and :patch-end plist entries. * lisp/vc/vc-git.el (vc-git-prepare-patch): Use -n1 to avoid passing a revision range to git-format-patch, which is a bit simpler. Catch search-failed errors and signal an error with a more helpful message. Properly handle Subject: header by looking for continuation lines. Return :patch-start and :patch-end entries in the plist. * lisp/vc/vc-hg.el (vc-hg-prepare-patch): Always pass --git to 'hg export' for consistency. Catch search-failed errors and signal an error with a more helpful message. Return a :patch-start entry in the plist.
-rw-r--r--lisp/vc/vc-git.el53
-rw-r--r--lisp/vc/vc-hg.el20
-rw-r--r--lisp/vc/vc.el22
3 files changed, 57 insertions, 38 deletions
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 5002c21747f..54475542ac4 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -2311,26 +2311,39 @@ Rebase may --autosquash your other squash!/fixup!/amend!; proceed?")))
2311 2311
2312(defun vc-git-prepare-patch (rev) 2312(defun vc-git-prepare-patch (rev)
2313 (with-current-buffer (generate-new-buffer " *vc-git-prepare-patch*") 2313 (with-current-buffer (generate-new-buffer " *vc-git-prepare-patch*")
2314 (vc-git-command 2314 (vc-git-command t 0 nil "format-patch"
2315 t 0 '() "format-patch" 2315 "--no-numbered" "--stdout" "-n1" rev)
2316 "--no-numbered" "--stdout" 2316 (condition-case _
2317 ;; From gitrevisions(7): ^<n> means the <n>th parent 2317 (let (subject body-start patch-start patch-end)
2318 ;; (i.e. <rev>^ is equivalent to <rev>^1). As a 2318 (goto-char (point-min))
2319 ;; special rule, <rev>^0 means the commit itself and 2319 (re-search-forward "^Subject: \\(.*\\)")
2320 ;; is used when <rev> is the object name of a tag 2320 (setq subject (match-string 1))
2321 ;; object that refers to a commit object. 2321 (while (progn (forward-line 1)
2322 (concat rev "^.." rev)) 2322 (looking-at "[\s\t]\\(.*\\)"))
2323 (let (subject) 2323 (setq subject (format "%s %s" subject (match-string 1))))
2324 ;; Extract the subject line 2324 (goto-char (point-min))
2325 (goto-char (point-min)) 2325 (re-search-forward "\n\n")
2326 (search-forward-regexp "^Subject: \\(.+\\)") 2326 (setq body-start (point))
2327 (setq subject (match-string 1)) 2327 (if ;; If the user has added any of these to
2328 ;; Jump to the beginning for the patch 2328 ;; `vc-git-diff-switches' then they expect to see the
2329 (search-forward-regexp "\n\n") 2329 ;; diffstat in *vc-diff* buffers.
2330 ;; Return the extracted data 2330 (cl-intersection '("--stat"
2331 (list :subject subject 2331 "--patch-with-stat"
2332 :buffer (current-buffer) 2332 "--compact-summary")
2333 :body-start (point))))) 2333 (vc-switches 'git 'diff)
2334 :test #'equal)
2335 (progn (re-search-forward "^---$")
2336 (setq patch-start (pos-bol 2)))
2337 (re-search-forward "^diff --git a/")
2338 (setq patch-start (pos-bol)))
2339 (re-search-forward "^-- $")
2340 (setq patch-end (pos-bol))
2341 (list :subject subject
2342 :body-start body-start
2343 :patch-start patch-start
2344 :patch-end patch-end
2345 :buffer (current-buffer)))
2346 (search-failed (error "git-format-patch output parse failure")))))
2334 2347
2335;; grep-compute-defaults autoloads grep. 2348;; grep-compute-defaults autoloads grep.
2336(declare-function grep-read-regexp "grep" ()) 2349(declare-function grep-read-regexp "grep" ())
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index a646ba079dd..0d1f1703081 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -1673,14 +1673,18 @@ This runs the command \"hg merge\"."
1673 1673
1674(defun vc-hg-prepare-patch (rev) 1674(defun vc-hg-prepare-patch (rev)
1675 (with-current-buffer (generate-new-buffer " *vc-hg-prepare-patch*") 1675 (with-current-buffer (generate-new-buffer " *vc-hg-prepare-patch*")
1676 (vc-hg-command t 0 '() "export" "--rev" rev) 1676 (vc-hg-command t 0 nil "export" "--git" "--rev" rev)
1677 (let (subject) 1677 (condition-case _
1678 ;; Extract the subject line 1678 (let (subject patch-start)
1679 (goto-char (point-min)) 1679 (goto-char (point-min))
1680 (search-forward-regexp "^[^#].*") 1680 (re-search-forward "^[^#].*")
1681 (setq subject (match-string 0)) 1681 (setq subject (match-string 0))
1682 ;; Return the extracted data 1682 (re-search-forward "\n\ndiff --git a/")
1683 (list :subject subject :buffer (current-buffer))))) 1683 (setq patch-start (pos-bol))
1684 (list :subject subject
1685 :patch-start patch-start
1686 :buffer (current-buffer)))
1687 (search-failed (error "'hg export' output parse failure")))))
1684 1688
1685;;; Internal functions 1689;;; Internal functions
1686 1690
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 782f9ae12a2..006d2098c2f 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -670,15 +670,17 @@
670;; 670;;
671;; - prepare-patch (rev) 671;; - prepare-patch (rev)
672;; 672;;
673;; Prepare a patch and return a property list with the keys 673;; Prepare a patch and return a property list with the keys `:subject'
674;; `:subject' indicating the patch message as a string, `:buffer' 674;; with the summary line (first line) of the patch message as a
675;; with a buffer object that contains the entire patch message and 675;; string; `:buffer' with a buffer object that contains the entire
676;; `:body-start' and `:body-end' demarcating what part of said 676;; patch message; `:body-start' and `:body-end' demarcating the part
677;; buffer should be inserted into an inline patch. If the two last 677;; of that buffer which should be inserted inline into a mail message
678;; properties are omitted, `point-min' and `point-max' will 678;; body; and `:patch-start' and `:patch-end' demarcating the part of
679;; respectively be used instead. If supported by the backend, the 679;; the buffer that is purely the patch, excluding any log message.
680;; patch should contain authorship identity and date information, and 680;; If any of these *-start and *-end properties are omitted, they
681;; REV's log message. 681;; default to (point-min) and (point-max), respectively.
682;; If supported by the backend, the patch should contain authorship
683;; identity and date information, and REV's log message.
682;; 684;;
683;; - clone (remote directory rev) 685;; - clone (remote directory rev)
684;; 686;;
@@ -4210,7 +4212,7 @@ If nil, no default will be used. This option may be set locally."
4210 :buffer (current-buffer))))) 4212 :buffer (current-buffer)))))
4211 4213
4212(defun vc-prepare-patch-prompt-revisions () 4214(defun vc-prepare-patch-prompt-revisions ()
4213 "Prompt the user for a list revisions. 4215 "Prompt the user for a list of revisions.
4214Prepare a default value, depending on the current context. With 4216Prepare a default value, depending on the current context. With
4215a numerical prefix argument, use the last N revisions as the 4217a numerical prefix argument, use the last N revisions as the
4216default value. If the current buffer is a log-view buffer, use 4218default value. If the current buffer is a log-view buffer, use