##// END OF EJS Templates
mq.el: add mq-signoff, to sign off on a patch
Bryan O'Sullivan -
r4429:3b0f73ed default
parent child Browse files
Show More
@@ -1,375 +1,410 b''
1 ;;; mq.el --- Emacs support for Mercurial Queues
1 ;;; mq.el --- Emacs support for Mercurial Queues
2
2
3 ;; Copyright (C) 2006 Bryan O'Sullivan
3 ;; Copyright (C) 2006 Bryan O'Sullivan
4
4
5 ;; Author: Bryan O'Sullivan <bos@serpentine.com>
5 ;; Author: Bryan O'Sullivan <bos@serpentine.com>
6
6
7 ;; mq.el is free software; you can redistribute it and/or modify it
7 ;; mq.el is free software; you can redistribute it and/or modify it
8 ;; under the terms of version 2 of the GNU General Public License as
8 ;; under the terms of version 2 of the GNU General Public License as
9 ;; published by the Free Software Foundation.
9 ;; published by the Free Software Foundation.
10
10
11 ;; mq.el is distributed in the hope that it will be useful, but
11 ;; mq.el is distributed in the hope that it will be useful, but
12 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ;; General Public License for more details.
14 ;; General Public License for more details.
15
15
16 ;; You should have received a copy of the GNU General Public License
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with mq.el, GNU Emacs, or XEmacs; see the file COPYING (`C-h
17 ;; along with mq.el, GNU Emacs, or XEmacs; see the file COPYING (`C-h
18 ;; C-l'). If not, write to the Free Software Foundation, Inc., 59
18 ;; C-l'). If not, write to the Free Software Foundation, Inc., 59
19 ;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 ;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
20
21 (require 'mercurial)
21 (require 'mercurial)
22
22
23
23
24 (defcustom mq-mode-hook nil
24 (defcustom mq-mode-hook nil
25 "Hook run when a buffer enters mq-mode."
25 "Hook run when a buffer enters mq-mode."
26 :type 'sexp
26 :type 'sexp
27 :group 'mercurial)
27 :group 'mercurial)
28
28
29 (defcustom mq-global-prefix "\C-cq"
29 (defcustom mq-global-prefix "\C-cq"
30 "The global prefix for Mercurial Queues keymap bindings."
30 "The global prefix for Mercurial Queues keymap bindings."
31 :type 'sexp
31 :type 'sexp
32 :group 'mercurial)
32 :group 'mercurial)
33
33
34 (defcustom mq-edit-mode-hook nil
34 (defcustom mq-edit-mode-hook nil
35 "Hook run after a buffer is populated to edit a patch description."
35 "Hook run after a buffer is populated to edit a patch description."
36 :type 'sexp
36 :type 'sexp
37 :group 'mercurial)
37 :group 'mercurial)
38
38
39 (defcustom mq-edit-finish-hook nil
39 (defcustom mq-edit-finish-hook nil
40 "Hook run before a patch description is finished up with."
40 "Hook run before a patch description is finished up with."
41 :type 'sexp
41 :type 'sexp
42 :group 'mercurial)
42 :group 'mercurial)
43
43
44 (defcustom mq-signoff-address nil
45 "Address with which to sign off on a patch."
46 :type 'string
47 :group 'mercurial)
48
44
49
45 ;;; Internal variables.
50 ;;; Internal variables.
46
51
47 (defvar mq-mode nil
52 (defvar mq-mode nil
48 "Is this file managed by MQ?")
53 "Is this file managed by MQ?")
49 (make-variable-buffer-local 'mq-mode)
54 (make-variable-buffer-local 'mq-mode)
50 (put 'mq-mode 'permanent-local t)
55 (put 'mq-mode 'permanent-local t)
51
56
52 (defvar mq-patch-history nil)
57 (defvar mq-patch-history nil)
53
58
54 (defvar mq-top-patch '(nil))
59 (defvar mq-top-patch '(nil))
55
60
56 (defvar mq-prev-buffer nil)
61 (defvar mq-prev-buffer nil)
57 (make-variable-buffer-local 'mq-prev-buffer)
62 (make-variable-buffer-local 'mq-prev-buffer)
58 (put 'mq-prev-buffer 'permanent-local t)
63 (put 'mq-prev-buffer 'permanent-local t)
59
64
60
65
61 ;;; Global keymap.
66 ;;; Global keymap.
62
67
63 (defvar mq-global-map (make-sparse-keymap))
68 (defvar mq-global-map (make-sparse-keymap))
64 (fset 'mq-global-map mq-global-map)
69 (fset 'mq-global-map mq-global-map)
65 (global-set-key mq-global-prefix 'mq-global-map)
70 (global-set-key mq-global-prefix 'mq-global-map)
66 (define-key mq-global-map "." 'mq-push)
71 (define-key mq-global-map "." 'mq-push)
67 (define-key mq-global-map ">" 'mq-push-all)
72 (define-key mq-global-map ">" 'mq-push-all)
68 (define-key mq-global-map "," 'mq-pop)
73 (define-key mq-global-map "," 'mq-pop)
69 (define-key mq-global-map "<" 'mq-pop-all)
74 (define-key mq-global-map "<" 'mq-pop-all)
70 (define-key mq-global-map "=" 'mq-diff)
75 (define-key mq-global-map "=" 'mq-diff)
71 (define-key mq-global-map "r" 'mq-refresh)
76 (define-key mq-global-map "r" 'mq-refresh)
72 (define-key mq-global-map "e" 'mq-refresh-edit)
77 (define-key mq-global-map "e" 'mq-refresh-edit)
73 (define-key mq-global-map "i" 'mq-new)
78 (define-key mq-global-map "i" 'mq-new)
74 (define-key mq-global-map "n" 'mq-next)
79 (define-key mq-global-map "n" 'mq-next)
80 (define-key mq-global-map "o" 'mq-signoff)
75 (define-key mq-global-map "p" 'mq-previous)
81 (define-key mq-global-map "p" 'mq-previous)
76 (define-key mq-global-map "s" 'mq-edit-series)
82 (define-key mq-global-map "s" 'mq-edit-series)
77 (define-key mq-global-map "t" 'mq-top)
83 (define-key mq-global-map "t" 'mq-top)
78
84
79 (add-minor-mode 'mq-mode 'mq-mode)
85 (add-minor-mode 'mq-mode 'mq-mode)
80
86
81
87
82 ;;; Refresh edit mode keymap.
88 ;;; Refresh edit mode keymap.
83
89
84 (defvar mq-edit-mode-map (make-sparse-keymap))
90 (defvar mq-edit-mode-map (make-sparse-keymap))
85 (define-key mq-edit-mode-map "\C-c\C-c" 'mq-edit-finish)
91 (define-key mq-edit-mode-map "\C-c\C-c" 'mq-edit-finish)
86 (define-key mq-edit-mode-map "\C-c\C-k" 'mq-edit-kill)
92 (define-key mq-edit-mode-map "\C-c\C-k" 'mq-edit-kill)
93 (define-key mq-edit-mode-map "\C-c\C-s" 'mq-signoff)
87
94
88
95
89 ;;; Helper functions.
96 ;;; Helper functions.
90
97
91 (defun mq-read-patch-name (&optional source prompt force)
98 (defun mq-read-patch-name (&optional source prompt force)
92 "Read a patch name to use with a command.
99 "Read a patch name to use with a command.
93 May return nil, meaning \"use the default\"."
100 May return nil, meaning \"use the default\"."
94 (let ((patches (split-string
101 (let ((patches (split-string
95 (hg-chomp (hg-run0 (or source "qseries"))) "\n")))
102 (hg-chomp (hg-run0 (or source "qseries"))) "\n")))
96 (when force
103 (when force
97 (completing-read (format "Patch%s: " (or prompt ""))
104 (completing-read (format "Patch%s: " (or prompt ""))
98 (map 'list 'cons patches patches)
105 (map 'list 'cons patches patches)
99 nil
106 nil
100 nil
107 nil
101 nil
108 nil
102 'mq-patch-history))))
109 'mq-patch-history))))
103
110
104 (defun mq-refresh-buffers (root)
111 (defun mq-refresh-buffers (root)
105 (save-excursion
112 (save-excursion
106 (dolist (buf (hg-buffers-visiting-repo root))
113 (dolist (buf (hg-buffers-visiting-repo root))
107 (when (not (verify-visited-file-modtime buf))
114 (when (not (verify-visited-file-modtime buf))
108 (set-buffer buf)
115 (set-buffer buf)
109 (let ((ctx (hg-buffer-context)))
116 (let ((ctx (hg-buffer-context)))
110 (message "Refreshing %s..." (buffer-name))
117 (message "Refreshing %s..." (buffer-name))
111 (revert-buffer t t t)
118 (revert-buffer t t t)
112 (hg-restore-context ctx)
119 (hg-restore-context ctx)
113 (message "Refreshing %s...done" (buffer-name))))))
120 (message "Refreshing %s...done" (buffer-name))))))
114 (hg-update-mode-lines root)
121 (hg-update-mode-lines root)
115 (mq-update-mode-lines root))
122 (mq-update-mode-lines root))
116
123
117 (defun mq-last-line ()
124 (defun mq-last-line ()
118 (goto-char (point-max))
125 (goto-char (point-max))
119 (beginning-of-line)
126 (beginning-of-line)
120 (when (looking-at "^$")
127 (when (looking-at "^$")
121 (forward-line -1))
128 (forward-line -1))
122 (let ((bol (point)))
129 (let ((bol (point)))
123 (end-of-line)
130 (end-of-line)
124 (let ((line (buffer-substring bol (point))))
131 (let ((line (buffer-substring bol (point))))
125 (when (> (length line) 0)
132 (when (> (length line) 0)
126 line))))
133 line))))
127
134
128 (defun mq-push (&optional patch)
135 (defun mq-push (&optional patch)
129 "Push patches until PATCH is reached.
136 "Push patches until PATCH is reached.
130 If PATCH is nil, push at most one patch."
137 If PATCH is nil, push at most one patch."
131 (interactive (list (mq-read-patch-name "qunapplied" " to push"
138 (interactive (list (mq-read-patch-name "qunapplied" " to push"
132 current-prefix-arg)))
139 current-prefix-arg)))
133 (let ((root (hg-root))
140 (let ((root (hg-root))
134 (prev-buf (current-buffer))
141 (prev-buf (current-buffer))
135 last-line ok)
142 last-line ok)
136 (unless root
143 (unless root
137 (error "Cannot push outside a repository!"))
144 (error "Cannot push outside a repository!"))
138 (hg-sync-buffers root)
145 (hg-sync-buffers root)
139 (let ((buf-name (format "MQ: Push %s" (or patch "next patch"))))
146 (let ((buf-name (format "MQ: Push %s" (or patch "next patch"))))
140 (kill-buffer (get-buffer-create buf-name))
147 (kill-buffer (get-buffer-create buf-name))
141 (split-window-vertically)
148 (split-window-vertically)
142 (other-window 1)
149 (other-window 1)
143 (switch-to-buffer (get-buffer-create buf-name))
150 (switch-to-buffer (get-buffer-create buf-name))
144 (cd root)
151 (cd root)
145 (message "Pushing...")
152 (message "Pushing...")
146 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpush"
153 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpush"
147 (if patch (list patch))))
154 (if patch (list patch))))
148 last-line (mq-last-line))
155 last-line (mq-last-line))
149 (let ((lines (count-lines (point-min) (point-max))))
156 (let ((lines (count-lines (point-min) (point-max))))
150 (if (or (<= lines 1)
157 (if (or (<= lines 1)
151 (and (equal lines 2) (string-match "Now at:" last-line)))
158 (and (equal lines 2) (string-match "Now at:" last-line)))
152 (progn
159 (progn
153 (kill-buffer (current-buffer))
160 (kill-buffer (current-buffer))
154 (delete-window))
161 (delete-window))
155 (hg-view-mode prev-buf))))
162 (hg-view-mode prev-buf))))
156 (mq-refresh-buffers root)
163 (mq-refresh-buffers root)
157 (sit-for 0)
164 (sit-for 0)
158 (when last-line
165 (when last-line
159 (if ok
166 (if ok
160 (message "Pushing... %s" last-line)
167 (message "Pushing... %s" last-line)
161 (error "Pushing... %s" last-line)))))
168 (error "Pushing... %s" last-line)))))
162
169
163 (defun mq-push-all ()
170 (defun mq-push-all ()
164 "Push patches until all are applied."
171 "Push patches until all are applied."
165 (interactive)
172 (interactive)
166 (mq-push "-a"))
173 (mq-push "-a"))
167
174
168 (defun mq-pop (&optional patch)
175 (defun mq-pop (&optional patch)
169 "Pop patches until PATCH is reached.
176 "Pop patches until PATCH is reached.
170 If PATCH is nil, pop at most one patch."
177 If PATCH is nil, pop at most one patch."
171 (interactive (list (mq-read-patch-name "qapplied" " to pop to"
178 (interactive (list (mq-read-patch-name "qapplied" " to pop to"
172 current-prefix-arg)))
179 current-prefix-arg)))
173 (let ((root (hg-root))
180 (let ((root (hg-root))
174 last-line ok)
181 last-line ok)
175 (unless root
182 (unless root
176 (error "Cannot pop outside a repository!"))
183 (error "Cannot pop outside a repository!"))
177 (hg-sync-buffers root)
184 (hg-sync-buffers root)
178 (set-buffer (generate-new-buffer "qpop"))
185 (set-buffer (generate-new-buffer "qpop"))
179 (cd root)
186 (cd root)
180 (message "Popping...")
187 (message "Popping...")
181 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpop"
188 (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpop"
182 (if patch (list patch))))
189 (if patch (list patch))))
183 last-line (mq-last-line))
190 last-line (mq-last-line))
184 (kill-buffer (current-buffer))
191 (kill-buffer (current-buffer))
185 (mq-refresh-buffers root)
192 (mq-refresh-buffers root)
186 (sit-for 0)
193 (sit-for 0)
187 (when last-line
194 (when last-line
188 (if ok
195 (if ok
189 (message "Popping... %s" last-line)
196 (message "Popping... %s" last-line)
190 (error "Popping... %s" last-line)))))
197 (error "Popping... %s" last-line)))))
191
198
192 (defun mq-pop-all ()
199 (defun mq-pop-all ()
193 "Push patches until none are applied."
200 "Push patches until none are applied."
194 (interactive)
201 (interactive)
195 (mq-pop "-a"))
202 (mq-pop "-a"))
196
203
197 (defun mq-refresh-internal (root &rest args)
204 (defun mq-refresh-internal (root &rest args)
198 (hg-sync-buffers root)
205 (hg-sync-buffers root)
199 (let ((patch (mq-patch-info "qtop")))
206 (let ((patch (mq-patch-info "qtop")))
200 (message "Refreshing %s..." patch)
207 (message "Refreshing %s..." patch)
201 (let ((ret (apply 'hg-run "qrefresh" args)))
208 (let ((ret (apply 'hg-run "qrefresh" args)))
202 (if (equal (car ret) 0)
209 (if (equal (car ret) 0)
203 (message "Refreshing %s... done." patch)
210 (message "Refreshing %s... done." patch)
204 (error "Refreshing %s... %s" patch (hg-chomp (cdr ret)))))))
211 (error "Refreshing %s... %s" patch (hg-chomp (cdr ret)))))))
205
212
206 (defun mq-refresh (&optional git)
213 (defun mq-refresh (&optional git)
207 "Refresh the topmost applied patch.
214 "Refresh the topmost applied patch.
208 With a prefix argument, generate a git-compatible patch."
215 With a prefix argument, generate a git-compatible patch."
209 (interactive "P")
216 (interactive "P")
210 (let ((root (hg-root)))
217 (let ((root (hg-root)))
211 (unless root
218 (unless root
212 (error "Cannot refresh outside of a repository!"))
219 (error "Cannot refresh outside of a repository!"))
213 (apply 'mq-refresh-internal root (if git '("--git")))))
220 (apply 'mq-refresh-internal root (if git '("--git")))))
214
221
215 (defun mq-patch-info (cmd &optional msg)
222 (defun mq-patch-info (cmd &optional msg)
216 (let* ((ret (hg-run cmd))
223 (let* ((ret (hg-run cmd))
217 (info (hg-chomp (cdr ret))))
224 (info (hg-chomp (cdr ret))))
218 (if (equal (car ret) 0)
225 (if (equal (car ret) 0)
219 (if msg
226 (if msg
220 (message "%s patch: %s" msg info)
227 (message "%s patch: %s" msg info)
221 info)
228 info)
222 (error "%s" info))))
229 (error "%s" info))))
223
230
224 (defun mq-top ()
231 (defun mq-top ()
225 "Print the name of the topmost applied patch."
232 "Print the name of the topmost applied patch."
226 (interactive)
233 (interactive)
227 (mq-patch-info "qtop" "Top"))
234 (mq-patch-info "qtop" "Top"))
228
235
229 (defun mq-next ()
236 (defun mq-next ()
230 "Print the name of the next patch to be pushed."
237 "Print the name of the next patch to be pushed."
231 (interactive)
238 (interactive)
232 (mq-patch-info "qnext" "Next"))
239 (mq-patch-info "qnext" "Next"))
233
240
234 (defun mq-previous ()
241 (defun mq-previous ()
235 "Print the name of the first patch below the topmost applied patch.
242 "Print the name of the first patch below the topmost applied patch.
236 This would become the active patch if popped to."
243 This would become the active patch if popped to."
237 (interactive)
244 (interactive)
238 (mq-patch-info "qprev" "Previous"))
245 (mq-patch-info "qprev" "Previous"))
239
246
240 (defun mq-edit-finish ()
247 (defun mq-edit-finish ()
241 "Finish editing the description of this patch, and refresh the patch."
248 "Finish editing the description of this patch, and refresh the patch."
242 (interactive)
249 (interactive)
243 (unless (equal (mq-patch-info "qtop") mq-top)
250 (unless (equal (mq-patch-info "qtop") mq-top)
244 (error "Topmost patch has changed!"))
251 (error "Topmost patch has changed!"))
245 (hg-sync-buffers hg-root)
252 (hg-sync-buffers hg-root)
246 (run-hooks 'mq-edit-finish-hook)
253 (run-hooks 'mq-edit-finish-hook)
247 (mq-refresh-internal hg-root "-m" (buffer-substring (point-min) (point-max)))
254 (mq-refresh-internal hg-root "-m" (buffer-substring (point-min) (point-max)))
248 (let ((buf mq-prev-buffer))
255 (let ((buf mq-prev-buffer))
249 (kill-buffer nil)
256 (kill-buffer nil)
250 (switch-to-buffer buf)))
257 (switch-to-buffer buf)))
251
258
252 (defun mq-edit-kill ()
259 (defun mq-edit-kill ()
253 "Kill the edit currently being prepared."
260 "Kill the edit currently being prepared."
254 (interactive)
261 (interactive)
255 (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this edit? "))
262 (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this edit? "))
256 (let ((buf mq-prev-buffer))
263 (let ((buf mq-prev-buffer))
257 (kill-buffer nil)
264 (kill-buffer nil)
258 (switch-to-buffer buf))))
265 (switch-to-buffer buf))))
259
266
260 (defun mq-get-top (root)
267 (defun mq-get-top (root)
261 (let ((entry (assoc root mq-top-patch)))
268 (let ((entry (assoc root mq-top-patch)))
262 (if entry
269 (if entry
263 (cdr entry))))
270 (cdr entry))))
264
271
265 (defun mq-set-top (root patch)
272 (defun mq-set-top (root patch)
266 (let ((entry (assoc root mq-top-patch)))
273 (let ((entry (assoc root mq-top-patch)))
267 (if entry
274 (if entry
268 (if patch
275 (if patch
269 (setcdr entry patch)
276 (setcdr entry patch)
270 (setq mq-top-patch (delq entry mq-top-patch)))
277 (setq mq-top-patch (delq entry mq-top-patch)))
271 (setq mq-top-patch (cons (cons root patch) mq-top-patch)))))
278 (setq mq-top-patch (cons (cons root patch) mq-top-patch)))))
272
279
273 (defun mq-update-mode-lines (root)
280 (defun mq-update-mode-lines (root)
274 (let ((cwd default-directory))
281 (let ((cwd default-directory))
275 (cd root)
282 (cd root)
276 (condition-case nil
283 (condition-case nil
277 (mq-set-top root (mq-patch-info "qtop"))
284 (mq-set-top root (mq-patch-info "qtop"))
278 (error (mq-set-top root nil)))
285 (error (mq-set-top root nil)))
279 (cd cwd))
286 (cd cwd))
280 (let ((patch (mq-get-top root)))
287 (let ((patch (mq-get-top root)))
281 (save-excursion
288 (save-excursion
282 (dolist (buf (hg-buffers-visiting-repo root))
289 (dolist (buf (hg-buffers-visiting-repo root))
283 (set-buffer buf)
290 (set-buffer buf)
284 (if mq-mode
291 (if mq-mode
285 (setq mq-mode (or (and patch (concat " MQ:" patch)) " MQ")))))))
292 (setq mq-mode (or (and patch (concat " MQ:" patch)) " MQ")))))))
286
293
287 (defun mq-mode (&optional arg)
294 (defun mq-mode (&optional arg)
288 "Minor mode for Mercurial repositories with an MQ patch queue"
295 "Minor mode for Mercurial repositories with an MQ patch queue"
289 (interactive "i")
296 (interactive "i")
290 (cond ((hg-root)
297 (cond ((hg-root)
291 (setq mq-mode (if (null arg) (not mq-mode)
298 (setq mq-mode (if (null arg) (not mq-mode)
292 arg))
299 arg))
293 (mq-update-mode-lines (hg-root))))
300 (mq-update-mode-lines (hg-root))))
294 (run-hooks 'mq-mode-hook))
301 (run-hooks 'mq-mode-hook))
295
302
296 (defun mq-edit-mode ()
303 (defun mq-edit-mode ()
297 "Mode for editing the description of a patch.
304 "Mode for editing the description of a patch.
298
305
299 Key bindings
306 Key bindings
300 ------------
307 ------------
301 \\[mq-edit-finish] use this description
308 \\[mq-edit-finish] use this description
302 \\[mq-edit-kill] abandon this description"
309 \\[mq-edit-kill] abandon this description"
303 (interactive)
310 (interactive)
304 (use-local-map mq-edit-mode-map)
311 (use-local-map mq-edit-mode-map)
305 (set-syntax-table text-mode-syntax-table)
312 (set-syntax-table text-mode-syntax-table)
306 (setq local-abbrev-table text-mode-abbrev-table
313 (setq local-abbrev-table text-mode-abbrev-table
307 major-mode 'mq-edit-mode
314 major-mode 'mq-edit-mode
308 mode-name "MQ-Edit")
315 mode-name "MQ-Edit")
309 (set-buffer-modified-p nil)
316 (set-buffer-modified-p nil)
310 (setq buffer-undo-list nil)
317 (setq buffer-undo-list nil)
311 (run-hooks 'text-mode-hook 'mq-edit-mode-hook))
318 (run-hooks 'text-mode-hook 'mq-edit-mode-hook))
312
319
313 (defun mq-refresh-edit ()
320 (defun mq-refresh-edit ()
314 "Refresh the topmost applied patch, editing the patch description."
321 "Refresh the topmost applied patch, editing the patch description."
315 (interactive)
322 (interactive)
316 (while mq-prev-buffer
323 (while mq-prev-buffer
317 (set-buffer mq-prev-buffer))
324 (set-buffer mq-prev-buffer))
318 (let ((root (hg-root))
325 (let ((root (hg-root))
319 (prev-buffer (current-buffer))
326 (prev-buffer (current-buffer))
320 (patch (mq-patch-info "qtop")))
327 (patch (mq-patch-info "qtop")))
321 (hg-sync-buffers root)
328 (hg-sync-buffers root)
322 (let ((buf-name (format "*MQ: Edit description of %s*" patch)))
329 (let ((buf-name (format "*MQ: Edit description of %s*" patch)))
323 (switch-to-buffer (get-buffer-create buf-name))
330 (switch-to-buffer (get-buffer-create buf-name))
324 (when (= (point-min) (point-max))
331 (when (= (point-min) (point-max))
325 (set (make-local-variable 'hg-root) root)
332 (set (make-local-variable 'hg-root) root)
326 (set (make-local-variable 'mq-top) patch)
333 (set (make-local-variable 'mq-top) patch)
327 (setq mq-prev-buffer prev-buffer)
334 (setq mq-prev-buffer prev-buffer)
328 (insert (hg-run0 "qheader"))
335 (insert (hg-run0 "qheader"))
329 (goto-char (point-min)))
336 (goto-char (point-min)))
330 (mq-edit-mode)
337 (mq-edit-mode)
331 (cd root)))
338 (cd root)))
332 (message "Type `C-c C-c' to finish editing and refresh the patch."))
339 (message "Type `C-c C-c' to finish editing and refresh the patch."))
333
340
334 (defun mq-new (name)
341 (defun mq-new (name)
335 "Create a new empty patch named NAME.
342 "Create a new empty patch named NAME.
336 The patch is applied on top of the current topmost patch.
343 The patch is applied on top of the current topmost patch.
337 With a prefix argument, forcibly create the patch even if the working
344 With a prefix argument, forcibly create the patch even if the working
338 directory is modified."
345 directory is modified."
339 (interactive (list (mq-read-patch-name "qseries" " to create" t)))
346 (interactive (list (mq-read-patch-name "qseries" " to create" t)))
340 (message "Creating patch...")
347 (message "Creating patch...")
341 (let ((ret (if current-prefix-arg
348 (let ((ret (if current-prefix-arg
342 (hg-run "qnew" "-f" name)
349 (hg-run "qnew" "-f" name)
343 (hg-run "qnew" name))))
350 (hg-run "qnew" name))))
344 (if (equal (car ret) 0)
351 (if (equal (car ret) 0)
345 (progn
352 (progn
346 (hg-update-mode-lines (buffer-file-name))
353 (hg-update-mode-lines (buffer-file-name))
347 (message "Creating patch... done."))
354 (message "Creating patch... done."))
348 (error "Creating patch... %s" (hg-chomp (cdr ret))))))
355 (error "Creating patch... %s" (hg-chomp (cdr ret))))))
349
356
350 (defun mq-edit-series ()
357 (defun mq-edit-series ()
351 "Edit the MQ series file directly."
358 "Edit the MQ series file directly."
352 (interactive)
359 (interactive)
353 (let ((root (hg-root)))
360 (let ((root (hg-root)))
354 (unless root
361 (unless root
355 (error "Not in an MQ repository!"))
362 (error "Not in an MQ repository!"))
356 (find-file (concat root ".hg/patches/series"))))
363 (find-file (concat root ".hg/patches/series"))))
357
364
358 (defun mq-diff (&optional git)
365 (defun mq-diff (&optional git)
359 "Display a diff of the topmost applied patch.
366 "Display a diff of the topmost applied patch.
360 With a prefix argument, display a git-compatible diff."
367 With a prefix argument, display a git-compatible diff."
361 (interactive "P")
368 (interactive "P")
362 (hg-view-output ((format "MQ: Diff of %s" (mq-patch-info "qtop")))
369 (hg-view-output ((format "MQ: Diff of %s" (mq-patch-info "qtop")))
363 (if git
370 (if git
364 (call-process (hg-binary) nil t nil "qdiff" "--git")
371 (call-process (hg-binary) nil t nil "qdiff" "--git")
365 (call-process (hg-binary) nil t nil "qdiff"))
372 (call-process (hg-binary) nil t nil "qdiff"))
366 (diff-mode)
373 (diff-mode)
367 (font-lock-fontify-buffer)))
374 (font-lock-fontify-buffer)))
368
375
376 (defun mq-signoff ()
377 "Sign off on the current patch, in the style used by the Linux kernel.
378 If the variable mq-signoff-address is non-nil, it will be used, otherwise
379 the value of the ui.username item from your hgrc will be used."
380 (interactive)
381 (let ((was-editing (eq major-mode 'mq-edit-mode))
382 signed)
383 (unless was-editing
384 (mq-refresh-edit))
385 (save-excursion
386 (let* ((user (or mq-signoff-address
387 (hg-run0 "debugconfig" "ui.username")))
388 (signoff (concat "Signed-off-by: " user)))
389 (if (search-forward signoff nil t)
390 (message "You have already signed off on this patch.")
391 (goto-char (point-max))
392 (let ((case-fold-search t))
393 (if (re-search-backward "^Signed-off-by: " nil t)
394 (forward-line 1)
395 (insert "\n")))
396 (insert signoff)
397 (message "%s" signoff)
398 (setq signed t))))
399 (unless was-editing
400 (if signed
401 (mq-edit-finish)
402 (mq-edit-kill)))))
403
369
404
370 (provide 'mq)
405 (provide 'mq)
371
406
372
407
373 ;;; Local Variables:
408 ;;; Local Variables:
374 ;;; prompt-to-byte-compile: nil
409 ;;; prompt-to-byte-compile: nil
375 ;;; end:
410 ;;; end:
General Comments 0
You need to be logged in to leave comments. Login now