diff options
-rw-r--r-- | init.el | 9 | ||||
-rw-r--r-- | lisp/km-magit.el | 78 |
2 files changed, 86 insertions, 1 deletions
@@ -1190,7 +1190,14 @@ '("V" "Back up current branch, v" km/magit-branch-version)) (transient-append-suffix 'magit-branch "c" - '("m" "Checkout master" km/magit-checkout-master))) + '("m" "Checkout master" km/magit-checkout-master)) + + (after 'magit-patch + (transient-append-suffix 'magit-patch-create "c" + '("u" "@{upstream}.." km/magit-patch-create-from-upstream)) + + (transient-append-suffix 'magit-patch-create "u" + '("s" "series" km/magit-patch-create-series)))) (use-package magit-annex :load-path "~/src/emacs/magit-annex/" diff --git a/lisp/km-magit.el b/lisp/km-magit.el index f0819de..8f2179a 100644 --- a/lisp/km-magit.el +++ b/lisp/km-magit.el @@ -26,6 +26,7 @@ (require 'km-util) (require 'magit) (require 'projectile) +(require 'seq) ;;;###autoload (defun km/magit-status (&optional default-display) @@ -832,6 +833,83 @@ category." (magit-run-git-async "for-each-ref" (format "--contains=%s" rev) "--sort=v:refname" "refs/tags"))) +(defun km/magit-patch-create-from-upstream (&optional args) + (interactive (list (transient-args 'magit-patch-create))) + (if-let ((upstream (magit-get-upstream-branch))) + (apply #'magit-run-git "format-patch" upstream args) + (user-error "No upstream branch"))) + +(defun km/magit-tweak-patch-series-summary () + "Restyle \"My Name (N):\" heading. +Drop author for single author series by `user-full-name', +appending [M/N] to each entry." + (interactive) + (save-excursion + (goto-char (point-min)) + (search-forward "*** BLURB HERE ***") + (let ((author-regexp (rx line-start word (zero-or-more not-newline) + "(" (one-or-more digit) "):" line-end))) + ;; Don't proceed if there looks to be more than one author. + (unless (and (re-search-forward author-regexp nil t) + (re-search-forward author-regexp nil t)) + (let ((buffer-read-only nil)) + (save-excursion + (goto-char (point-min)) + (when-let ((total (and (re-search-forward + (rx line-start (eval user-full-name) " (" + (group (one-or-more digit)) + "):" line-end) + nil t) + (match-string 1))) + (prefix (format "[%%%dd/%s] " (length total) total)) + (idx 1)) + (delete-region (line-beginning-position) (1+ (line-end-position))) + (while (and (not (eobp)) + (not (looking-at-p "^$"))) + (goto-char (line-beginning-position)) + (skip-chars-forward " ") + (insert (format prefix idx)) + (cl-incf idx) + (forward-line))))))))) + +(defun km/magit-patch-create-series (&optional args) + (interactive (list (transient-args 'magit-patch-create))) + (when (magit-anything-modified-p t) + (user-error "There are uncommitted changes")) + (setq args (seq-remove + (lambda (a) (string-match-p "\\`--base=" a)) + args)) + (if-let ((current (magit-get-current-branch)) + (upstream (magit-get-upstream-branch current))) + (let ((patch-branch (concat "patches/" current))) + (if (not (magit-local-branch-p patch-branch)) + (magit-branch-and-checkout patch-branch current) + (magit-update-ref (concat "refs/heads/" patch-branch) + (concat "reset: moving back to " current) + current) + (magit-branch-checkout patch-branch)) + (apply #'magit-run-git "format-patch" + upstream (concat "--base=" upstream) args) + (let* ((patches (or (seq-filter + (lambda (f) (string-match-p "\\.patch\\'" f)) + (magit-untracked-files)) + (error "There should be patches"))) + (cover (seq-find (lambda (f) (string-match-p "\\`0+-" f)) + patches))) + (magit-call-git "add" patches) + (magit-run-git "commit" "-mpatches") + (when cover + (with-temp-buffer + (insert-file-contents cover) + (km/magit-tweak-patch-series-summary) + (write-region nil nil cover)) + (magit-call-git "commit" "-mtweak cover" "--" cover)) + (when cover + (find-file-other-window cover) + (re-search-forward (rx "Subject: [PATCH" (zero-or-more not-newline) "] ")) + (setq buffer-read-only nil)))) + (user-error "No upstream branch"))) + ;;; Copy functions |