aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2010-04-20 22:05:24 -0400
committerStefan Monnier2010-04-20 22:05:24 -0400
commite97a42c15bfc9ed00a1def8381f235642947931a (patch)
tree2c37bdd17ea3cea0615de066ceaebff877a8061f
parent50426a043dc30200e093237101b8d0125861c127 (diff)
downloademacs-e97a42c15bfc9ed00a1def8381f235642947931a.tar.gz
emacs-e97a42c15bfc9ed00a1def8381f235642947931a.zip
Make the log-edit comments use RFC822 format throughout.
* vc.el (vc-checkin, vc-modify-change-comment): Adjust to new vc-start/finish-logentry. (vc-find-conflicted-file): New command. (vc-transfer-file): Adjust to new vc-checkin. (vc-next-action): Improve scoping. * vc-hg.el (vc-hg-log-edit-mode): Remove. (vc-hg-checkin): Remove extra arg. Use log-edit-extract-headers. * vc-git.el (vc-git-log-edit-mode): Remove. (vc-git-checkin): Remove extra arg. Use log-edit-extract-headers. (vc-git-commits-coding-system): Rename from git-commits-coding-system. * vc-dispatcher.el (vc-log-edit): Shorten names for log-edit-show-files. (vc-start-logentry): Remove argument `extra'. (vc-finish-logentry): Remove extra args. * vc-bzr.el (vc-bzr-log-edit-mode): Remove. (vc-bzr-checkin): Remove extra arg. Use log-edit-extract-headers. (vc-bzr-conflicted-files): New function. * log-edit.el (log-edit-extra-flags) (log-edit-before-checkin-process): Remove. (log-edit-summary, log-edit-header, log-edit-unknown-header): New faces. (log-edit-headers-alist): New var. (log-edit-header-contents-regexp): New const. (log-edit-match-to-eoh): New function. (log-edit-font-lock-keywords): Use them. (log-edit): Insert a "Summary:" header as default. (log-edit-mode): Mark font-lock rules as case-insensitive. (log-edit-done): Cleanup headers. (log-view-process-buffer): Remove. (log-edit-extract-headers): New function to replace it.
-rw-r--r--etc/NEWS23
-rw-r--r--lisp/ChangeLog36
-rw-r--r--lisp/emacs-lisp/cl-loaddefs.el3
-rw-r--r--lisp/log-edit.el134
-rw-r--r--lisp/vc-bzr.el39
-rw-r--r--lisp/vc-dispatcher.el31
-rw-r--r--lisp/vc-git.el29
-rw-r--r--lisp/vc-hg.el23
-rw-r--r--lisp/vc.el108
9 files changed, 268 insertions, 158 deletions
diff --git a/etc/NEWS b/etc/NEWS
index b47fcd09536..fcd293781b6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -88,6 +88,8 @@ define it as a scroll command affected by `scroll-preserve-screen-position.
88** Archive Mode has basic support to browse 7z archives. 88** Archive Mode has basic support to browse 7z archives.
89 89
90** partial-completion-mode is now obsolete. 90** partial-completion-mode is now obsolete.
91You can get the same behavior with
92(setq completion-styles '(partial-completion initials)).
91 93
92** mpc.el: Can use pseudo tags of the form tag1|tag2 as a union of two tags. 94** mpc.el: Can use pseudo tags of the form tag1|tag2 as a union of two tags.
93** Customize 95** Customize
@@ -106,23 +108,18 @@ choose a color via list-colors-display.
106 108
107** VC and related modes 109** VC and related modes
108 110
109*** New VC commands: vc-log-incoming and vc-log-outgoing. 111*** New VC commands: vc-log-incoming, vc-log-outgoing, vc-find-conflicted-file.
110 112
111*** vc-dir for Bzr supports viewing shelve contents and shelving snapshots. 113*** vc-dir for Bzr supports viewing shelve contents and shelving snapshots.
112 114
113*** Special markup can be added to log-edit buffers. 115*** Special markup can be added to log-edit buffers.
114 116The log-edit buffers are expected to have a format similar to email messages
115**** For Bzr, adding an 117with headers of the form:
116Author: NAME 118 Author: <author of this change>
117line will add "--author NAME" to the "bzr commit" command. 119 Summary: <one line summary of this change>
118 120 Fixes: <reference to the bug fixed by this change>
119**** For Git, adding an 121Some backends handle some of those headers specially, but any unknown header
120Author: NAME 122is just left as is in the message, so it is not lost.
121line will add "--author NAME" to the "git commit" command.
122
123**** For Hg, adding an
124Author: NAME
125line will add "--user NAME" to the "hg commit" command.
126 123
127** Directory local variables can apply to file-less buffers. 124** Directory local variables can apply to file-less buffers.
128For example, adding "(diff-mode . ((mode . whitespace)))" to your 125For example, adding "(diff-mode . ((mode . whitespace)))" to your
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 29188d53f0b..0a834ceeb38 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,39 @@
12010-04-21 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * vc.el (vc-checkin, vc-modify-change-comment):
4 Adjust to new vc-start/finish-logentry.
5 (vc-find-conflicted-file): New command.
6 (vc-transfer-file): Adjust to new vc-checkin.
7 (vc-next-action): Improve scoping.
8
9 * vc-hg.el (vc-hg-log-edit-mode): Remove.
10 (vc-hg-checkin): Remove extra arg. Use log-edit-extract-headers.
11
12 * vc-git.el (vc-git-log-edit-mode): Remove.
13 (vc-git-checkin): Remove extra arg. Use log-edit-extract-headers.
14 (vc-git-commits-coding-system): Rename from git-commits-coding-system.
15
16 * vc-dispatcher.el (vc-log-edit): Shorten names for log-edit-show-files.
17 (vc-start-logentry): Remove argument `extra'.
18 (vc-finish-logentry): Remove extra args.
19
20 * vc-bzr.el (vc-bzr-log-edit-mode): Remove.
21 (vc-bzr-checkin): Remove extra arg. Use log-edit-extract-headers.
22 (vc-bzr-conflicted-files): New function.
23
24 * log-edit.el (log-edit-extra-flags)
25 (log-edit-before-checkin-process): Remove.
26 (log-edit-summary, log-edit-header, log-edit-unknown-header): New faces.
27 (log-edit-headers-alist): New var.
28 (log-edit-header-contents-regexp): New const.
29 (log-edit-match-to-eoh): New function.
30 (log-edit-font-lock-keywords): Use them.
31 (log-edit): Insert a "Summary:" header as default.
32 (log-edit-mode): Mark font-lock rules as case-insensitive.
33 (log-edit-done): Cleanup headers.
34 (log-view-process-buffer): Remove.
35 (log-edit-extract-headers): New function to replace it.
36
12010-04-20 Juanma Barranquero <lekktu@gmail.com> 372010-04-20 Juanma Barranquero <lekktu@gmail.com>
2 38
3 * subr.el (default-direction-reversed): Remove obsolescence info. 39 * subr.el (default-direction-reversed): Remove obsolescence info.
diff --git a/lisp/emacs-lisp/cl-loaddefs.el b/lisp/emacs-lisp/cl-loaddefs.el
index 83247b62135..bb5fd5037a1 100644
--- a/lisp/emacs-lisp/cl-loaddefs.el
+++ b/lisp/emacs-lisp/cl-loaddefs.el
@@ -1242,7 +1242,6 @@ Keywords supported: :test :test-not :key
1242;; version-control: never 1242;; version-control: never
1243;; no-byte-compile: t 1243;; no-byte-compile: t
1244;; no-update-autoloads: t 1244;; no-update-autoloads: t
1245;; coding: utf-8
1245;; End: 1246;; End:
1246
1247;; arch-tag: 08cc5aab-e992-47f6-992e-12a7428c1a0e
1248;;; cl-loaddefs.el ends here 1247;;; cl-loaddefs.el ends here
diff --git a/lisp/log-edit.el b/lisp/log-edit.el
index 09dce0eb859..efcb8ba1299 100644
--- a/lisp/log-edit.el
+++ b/lisp/log-edit.el
@@ -125,6 +125,7 @@ If SETUP is 'force, this variable has no effect."
125 :type 'boolean) 125 :type 'boolean)
126 126
127(defcustom log-edit-hook '(log-edit-insert-cvs-template 127(defcustom log-edit-hook '(log-edit-insert-cvs-template
128 log-edit-show-files
128 log-edit-insert-changelog) 129 log-edit-insert-changelog)
129 "Hook run at the end of `log-edit'." 130 "Hook run at the end of `log-edit'."
130 :group 'log-edit 131 :group 'log-edit
@@ -188,22 +189,6 @@ when this variable is set to nil.")
188(defvar log-edit-callback nil) 189(defvar log-edit-callback nil)
189(defvar log-edit-diff-function nil) 190(defvar log-edit-diff-function nil)
190(defvar log-edit-listfun nil) 191(defvar log-edit-listfun nil)
191(defvar log-edit-extra-flags nil
192 "List of extra flags to pass to the check in command.")
193(defvar log-edit-before-checkin-process nil
194 "Alist with instructions for processing the commit message before check in.
195The format is: (REGEXP . INSTRUCTIONS).
196All lines matching REGEXP are removed. For example:
197
198\(\"^#.*\" . nil)
199
200means: just remove all lines starting with #. This can be used
201to insert lines in the commit buffer that contain, for example, the
202list of files to be committed.
203
204\(\"Author: \\\\(.*\\\\)\" . (list \"--author\" (match-string 1)))
205
206means: append (list \"--author\" (match-string 1)) to `log-edit-extra-flags'.")
207 192
208(defvar log-edit-parent-buffer nil) 193(defvar log-edit-parent-buffer nil)
209 194
@@ -329,10 +314,53 @@ automatically."
329;;; Actual code 314;;; Actual code
330;;; 315;;;
331 316
317(defface log-edit-summary '((t :inherit font-lock-function-name-face))
318 "Face for the summary in `log-edit-mode' buffers.")
319
320(defface log-edit-header '((t :inherit font-lock-keyword-face))
321 "Face for the headers in `log-edit-mode' buffers.")
322
323(defface log-edit-unknown-header '((t :inherit font-lock-comment-face))
324 "Face for unknown headers in `log-edit-mode' buffers.")
325
326(defvar log-edit-headers-alist '(("Summary" . log-edit-summary)
327 ("Fixes") ("Author"))
328 "AList of known headers and the face to use to highlight them.")
329
330(defconst log-edit-header-contents-regexp
331 "[ \t]*\\(.*\\(\n[ \t].*\\)*\\)\n?")
332
333(defun log-edit-match-to-eoh (limit)
334 ;; FIXME: copied from message-match-to-eoh.
335 (let ((start (point)))
336 (rfc822-goto-eoh)
337 ;; Typical situation: some temporary change causes the header to be
338 ;; incorrect, so EOH comes earlier than intended: the last lines of the
339 ;; intended headers are now not considered part of the header any more,
340 ;; so they don't have the multiline property set. When the change is
341 ;; completed and the header has its correct shape again, the lack of the
342 ;; multiline property means we won't rehighlight the last lines of
343 ;; the header.
344 (if (< (point) start)
345 nil ;No header within start..limit.
346 ;; Here we disregard LIMIT so that we may extend the area again.
347 (set-match-data (list start (point)))
348 (point))))
349
332(defvar log-edit-font-lock-keywords 350(defvar log-edit-font-lock-keywords
333 '(("\\`\\(Summary:\\)\\(.*\\)" 351 ;; Copied/inspired by message-font-lock-keywords.
334 (1 font-lock-keyword-face) 352 `((log-edit-match-to-eoh
335 (2 font-lock-function-name-face)))) 353 (,(concat "^\\(\\([a-z]+\\):\\)" log-edit-header-contents-regexp
354 "\\|\\(.*\\)")
355 (progn (goto-char (match-beginning 0)) (match-end 0)) nil
356 (1 (if (assoc (match-string 2) log-edit-headers-alist)
357 'log-edit-header
358 'log-edit-unknown-header)
359 nil lax)
360 (3 (or (cdr (assoc (match-string 2) log-edit-headers-alist))
361 'log-edit-header)
362 nil lax)
363 (4 font-lock-warning-face)))))
336 364
337;;;###autoload 365;;;###autoload
338(defun log-edit (callback &optional setup params buffer mode &rest ignore) 366(defun log-edit (callback &optional setup params buffer mode &rest ignore)
@@ -358,7 +386,10 @@ uses the current buffer."
358 (if buffer (pop-to-buffer buffer)) 386 (if buffer (pop-to-buffer buffer))
359 (when (and log-edit-setup-invert (not (eq setup 'force))) 387 (when (and log-edit-setup-invert (not (eq setup 'force)))
360 (setq setup (not setup))) 388 (setq setup (not setup)))
361 (when setup (erase-buffer)) 389 (when setup
390 (erase-buffer)
391 (insert "Summary: ")
392 (save-excursion (insert "\n\n")))
362 (if mode 393 (if mode
363 (funcall mode) 394 (funcall mode)
364 (log-edit-mode)) 395 (log-edit-mode))
@@ -387,7 +418,7 @@ commands (under C-x v for VC, for example).
387 418
388\\{log-edit-mode-map}" 419\\{log-edit-mode-map}"
389 (set (make-local-variable 'font-lock-defaults) 420 (set (make-local-variable 'font-lock-defaults)
390 '(log-edit-font-lock-keywords t)) 421 '(log-edit-font-lock-keywords t t))
391 (make-local-variable 'log-edit-comment-ring-index) 422 (make-local-variable 'log-edit-comment-ring-index)
392 (hack-dir-local-variables-non-file-buffer)) 423 (hack-dir-local-variables-non-file-buffer))
393 424
@@ -401,6 +432,17 @@ commands (under C-x v for VC, for example).
401 "Finish editing the log message and commit the files. 432 "Finish editing the log message and commit the files.
402If you want to abort the commit, simply delete the buffer." 433If you want to abort the commit, simply delete the buffer."
403 (interactive) 434 (interactive)
435 ;; Clean up empty headers.
436 (goto-char (point-min))
437 (while (looking-at (concat "^[a-z]*:" log-edit-header-contents-regexp))
438 (let ((beg (match-beginning 0)))
439 (goto-char (match-end 0))
440 (if (string-match "\\`[ \n\t]*\\'" (match-string 1))
441 (delete-region beg (point)))))
442 ;; Get rid of leading empty lines.
443 (goto-char (point-min))
444 (when (looking-at "\\([ \t]*\n\\)+")
445 (delete-region (match-beginning 0) (match-end 0)))
404 ;; Get rid of trailing empty lines 446 ;; Get rid of trailing empty lines
405 (goto-char (point-max)) 447 (goto-char (point-max))
406 (skip-syntax-backward " ") 448 (skip-syntax-backward " ")
@@ -458,12 +500,13 @@ If you want to abort the commit, simply delete the buffer."
458 "(Un)Indent the current buffer rigidly to `log-edit-common-indent'." 500 "(Un)Indent the current buffer rigidly to `log-edit-common-indent'."
459 (save-excursion 501 (save-excursion
460 (let ((common (point-max))) 502 (let ((common (point-max)))
461 (goto-char (point-min)) 503 (rfc822-goto-eoh)
462 (while (< (point) (point-max)) 504 (while (< (point) (point-max))
463 (if (not (looking-at "^[ \t]*$")) 505 (if (not (looking-at "^[ \t]*$"))
464 (setq common (min common (current-indentation)))) 506 (setq common (min common (current-indentation))))
465 (forward-line 1)) 507 (forward-line 1))
466 (indent-rigidly (point-min) (point-max) 508 (rfc822-goto-eoh)
509 (indent-rigidly (point) (point-max)
467 (- log-edit-common-indent common))))) 510 (- log-edit-common-indent common)))))
468 511
469(defun log-edit-show-diff () 512(defun log-edit-show-diff ()
@@ -546,6 +589,10 @@ If the optional prefix arg USE-FIRST is given (via \\[universal-argument]),
546or if the command is repeated a second time in a row, use the first log entry 589or if the command is repeated a second time in a row, use the first log entry
547regardless of user name or time." 590regardless of user name or time."
548 (interactive "P") 591 (interactive "P")
592 (let ((eoh (save-excursion (rfc822-goto-eoh) (point))))
593 (when (<= (point) eoh)
594 (goto-char eoh)
595 (if (looking-at "\n") (forward-char 1))))
549 (let ((log-edit-changelog-use-first 596 (let ((log-edit-changelog-use-first
550 (or use-first (eq last-command 'log-edit-insert-changelog)))) 597 (or use-first (eq last-command 'log-edit-insert-changelog))))
551 (log-edit-insert-changelog-entries (log-edit-files))) 598 (log-edit-insert-changelog-entries (log-edit-files)))
@@ -731,16 +778,39 @@ Sort REGIONS front-to-back first."
731 (log-edit-changelog-insert-entries (car buffer-entry) (cdr buffer-entry)) 778 (log-edit-changelog-insert-entries (car buffer-entry) (cdr buffer-entry))
732 (when (cdr buffer-entry) (newline))))) 779 (when (cdr buffer-entry) (newline)))))
733 780
734(defun log-view-process-buffer () 781(defun log-edit-extract-headers (headers comment)
735 (when log-edit-before-checkin-process 782 "Extract headers from COMMENT to form command line arguments.
736 (dolist (crt log-edit-before-checkin-process) 783HEADERS should be an alist with elements of the form (HEADER . CMDARG)
737 ;; Remove all lines matching (car crt) 784associating header names to the corresponding cmdline option name and the
738 ;; Append to `log-edit-extra-flags' the results of (cdr crt). 785result is then a list of the form (MSG CMDARG1 HDRTEXT1 CMDARG2 HDRTEXT2...).
786where MSG is the remaining text from STRING.
787If \"Summary\" is not in HEADERS, then the \"Summary\" header is extracted
788anyway and put back as the first line of MSG."
789 (with-temp-buffer
790 (insert comment)
791 (rfc822-goto-eoh)
792 (narrow-to-region (point-min) (point))
793 (let ((case-fold-search t)
794 (summary ())
795 (res ()))
796 (dolist (header (if (assoc "Summary" headers) headers
797 (cons '("Summary" . t) headers)))
798 (goto-char (point-min))
799 (while (re-search-forward (concat "^" (car header)
800 ":" log-edit-header-contents-regexp)
801 nil t)
802 (if (eq t (cdr header))
803 (setq summary (match-string 1))
804 (push (match-string 1) res)
805 (push (or (cdr header) (car header)) res))
806 (replace-match "" t t)))
807 ;; Remove header separator if the header is empty.
808 (widen)
739 (goto-char (point-min)) 809 (goto-char (point-min))
740 (while (re-search-forward (car crt) nil t) 810 (when (looking-at "\\([ \t]*\n\\)+")
741 (when (cdr crt) 811 (delete-region (match-beginning 0) (match-end 0)))
742 (setq log-edit-extra-flags (append log-edit-extra-flags (eval (cdr crt))))) 812 (if summary (insert summary "\n"))
743 (replace-match "" nil t))))) 813 (cons (buffer-string) res))))
744 814
745(provide 'log-edit) 815(provide 'log-edit)
746 816
diff --git a/lisp/vc-bzr.el b/lisp/vc-bzr.el
index 64935f16dbd..4bdf9acc956 100644
--- a/lisp/vc-bzr.el
+++ b/lisp/vc-bzr.el
@@ -451,11 +451,16 @@ or a superior directory.")
451 "Unregister FILE from bzr." 451 "Unregister FILE from bzr."
452 (vc-bzr-command "remove" nil 0 file "--keep")) 452 (vc-bzr-command "remove" nil 0 file "--keep"))
453 453
454(defun vc-bzr-checkin (files rev comment &optional extra-args) 454(declare-function log-edit-extract-headers "log-edit" (headers string))
455
456(defun vc-bzr-checkin (files rev comment)
455 "Check FILE in to bzr with log message COMMENT. 457 "Check FILE in to bzr with log message COMMENT.
456REV non-nil gets an error." 458REV non-nil gets an error."
457 (if rev (error "Can't check in a specific revision with bzr")) 459 (if rev (error "Can't check in a specific revision with bzr"))
458 (apply 'vc-bzr-command "commit" nil 0 files (append (list "-m" comment) extra-args))) 460 (apply 'vc-bzr-command "commit" nil 'async
461 files (cons "-m" (log-edit-extract-headers '(("Author" . "--author")
462 ("Fixes" . "--fixes"))
463 comment))))
459 464
460(defun vc-bzr-find-revision (file rev buffer) 465(defun vc-bzr-find-revision (file rev buffer)
461 "Fetch revision REV of file FILE and put it into BUFFER." 466 "Fetch revision REV of file FILE and put it into BUFFER."
@@ -552,23 +557,6 @@ REV non-nil gets an error."
552 (goto-char (point-min))) 557 (goto-char (point-min)))
553 found))) 558 found)))
554 559
555(declare-function log-edit-mode "log-edit" ())
556(defvar log-edit-extra-flags)
557(defvar log-edit-before-checkin-process)
558
559(define-derived-mode vc-bzr-log-edit-mode log-edit-mode "Bzr-Log-Edit"
560 "Mode for editing Bzr commit logs.
561If a line like:
562Author: NAME
563is present in the log, it is removed, and
564--author NAME
565is passed to the bzr commit command. Similarly with Fixes: and --fixes."
566 (set (make-local-variable 'log-edit-extra-flags) nil)
567 (set (make-local-variable 'log-edit-before-checkin-process)
568 '(("^\\(Author\\|Fixes\\):[ \t]+\\(.*\\)[ \t]*$" .
569 (list (format "--%s" (downcase (match-string 1)))
570 (match-string 2))))))
571
572(defun vc-bzr-diff (files &optional rev1 rev2 buffer) 560(defun vc-bzr-diff (files &optional rev1 rev2 buffer)
573 "VC bzr backend for diff." 561 "VC bzr backend for diff."
574 ;; `bzr diff' exits with code 1 if diff is non-empty. 562 ;; `bzr diff' exits with code 1 if diff is non-empty.
@@ -983,6 +971,19 @@ stream. Standard error output is discarded."
983 (setq loglines (buffer-substring-no-properties start (point-max)))))) 971 (setq loglines (buffer-substring-no-properties start (point-max))))))
984 vc-bzr-revisions)) 972 vc-bzr-revisions))
985 973
974(defun vc-bzr-conflicted-files (dir)
975 (let ((default-directory (vc-bzr-root dir))
976 (files ()))
977 (with-temp-buffer
978 (vc-bzr-command "status" t 0 default-directory)
979 (goto-char (point-min))
980 (when (re-search-forward "^conflicts:\n" nil t)
981 (while (looking-at " \\(?:Text conflict in \\(.*\\)\\|.*\\)\n")
982 (if (match-end 1)
983 (push (expand-file-name (match-string 1)) files))
984 (goto-char (match-end 0)))))
985 files))
986
986;;; Revision completion 987;;; Revision completion
987 988
988(eval-and-compile 989(eval-and-compile
diff --git a/lisp/vc-dispatcher.el b/lisp/vc-dispatcher.el
index f061af46b8c..7892fed158f 100644
--- a/lisp/vc-dispatcher.el
+++ b/lisp/vc-dispatcher.el
@@ -141,7 +141,6 @@ preserve the setting."
141(defvar vc-log-operation nil) 141(defvar vc-log-operation nil)
142(defvar vc-log-after-operation-hook nil) 142(defvar vc-log-after-operation-hook nil)
143(defvar vc-log-fileset) 143(defvar vc-log-fileset)
144(defvar vc-log-extra)
145 144
146;; In a log entry buffer, this is a local variable 145;; In a log entry buffer, this is a local variable
147;; that points to the buffer for which it was made 146;; that points to the buffer for which it was made
@@ -521,17 +520,20 @@ NOT-URGENT means it is ok to continue if the user says not to save."
521 (with-current-buffer vc-parent-buffer default-directory)) 520 (with-current-buffer vc-parent-buffer default-directory))
522 (log-edit 'vc-finish-logentry 521 (log-edit 'vc-finish-logentry
523 nil 522 nil
524 `((log-edit-listfun . (lambda () ',fileset)) 523 `((log-edit-listfun . (lambda ()
524 ;; FIXME: Should expand the list
525 ;; for directories.
526 (mapcar 'file-relative-name
527 ',fileset)))
525 (log-edit-diff-function . (lambda () (vc-diff nil)))) 528 (log-edit-diff-function . (lambda () (vc-diff nil))))
526 nil 529 nil
527 mode) 530 mode)
528 (set (make-local-variable 'vc-log-fileset) fileset) 531 (set (make-local-variable 'vc-log-fileset) fileset)
529 (make-local-variable 'vc-log-extra)
530 (set-buffer-modified-p nil) 532 (set-buffer-modified-p nil)
531 (setq buffer-file-name nil)) 533 (setq buffer-file-name nil))
532 534
533(defun vc-start-logentry (files extra comment initial-contents msg logbuf mode action &optional after-hook) 535(defun vc-start-logentry (files comment initial-contents msg logbuf mode action &optional after-hook)
534 "Accept a comment for an operation on FILES with extra data EXTRA. 536 "Accept a comment for an operation on FILES.
535If COMMENT is nil, pop up a LOGBUF buffer, emit MSG, and set the 537If COMMENT is nil, pop up a LOGBUF buffer, emit MSG, and set the
536action on close to ACTION. If COMMENT is a string and 538action on close to ACTION. If COMMENT is a string and
537INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial 539INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial
@@ -561,7 +563,6 @@ AFTER-HOOK specifies the local value for `vc-log-after-operation-hook'."
561 (when after-hook 563 (when after-hook
562 (setq vc-log-after-operation-hook after-hook)) 564 (setq vc-log-after-operation-hook after-hook))
563 (setq vc-log-operation action) 565 (setq vc-log-operation action)
564 (setq vc-log-extra extra)
565 (when comment 566 (when comment
566 (erase-buffer) 567 (erase-buffer)
567 (when (stringp comment) (insert comment))) 568 (when (stringp comment) (insert comment)))
@@ -570,10 +571,8 @@ AFTER-HOOK specifies the local value for `vc-log-after-operation-hook'."
570 (vc-finish-logentry (eq comment t))))) 571 (vc-finish-logentry (eq comment t)))))
571 572
572(declare-function vc-dir-move-to-goal-column "vc-dir" ()) 573(declare-function vc-dir-move-to-goal-column "vc-dir" ())
573;; vc-finish-logentry is called from a log-edit buffer (see above). 574;; vc-finish-logentry is typically called from a log-edit buffer (see
574(declare-function log-view-process-buffer "log-edit" ()) 575;; vc-start-logentry).
575(defvar log-edit-extra-flags)
576
577(defun vc-finish-logentry (&optional nocomment) 576(defun vc-finish-logentry (&optional nocomment)
578 "Complete the operation implied by the current log entry. 577 "Complete the operation implied by the current log entry.
579Use the contents of the current buffer as a check-in or registration 578Use the contents of the current buffer as a check-in or registration
@@ -590,25 +589,21 @@ the buffer contents as a comment."
590 (unless vc-log-operation 589 (unless vc-log-operation
591 (error "No log operation is pending")) 590 (error "No log operation is pending"))
592 591
593 (log-view-process-buffer)
594
595 ;; save the parameters held in buffer-local variables 592 ;; save the parameters held in buffer-local variables
596 (let ((logbuf (current-buffer)) 593 (let ((logbuf (current-buffer))
597 (log-operation vc-log-operation) 594 (log-operation vc-log-operation)
595 ;; FIXME: When coming from VC-Dir, we should check that the
596 ;; set of selected files is still equal to vc-log-fileset,
597 ;; to avoid surprises.
598 (log-fileset vc-log-fileset) 598 (log-fileset vc-log-fileset)
599 (log-extra vc-log-extra)
600 (log-entry (buffer-string)) 599 (log-entry (buffer-string))
601 (extra-flags log-edit-extra-flags)
602 (after-hook vc-log-after-operation-hook)) 600 (after-hook vc-log-after-operation-hook))
603 (pop-to-buffer vc-parent-buffer) 601 (pop-to-buffer vc-parent-buffer)
604 ;; OK, do it to it 602 ;; OK, do it to it
605 (save-excursion 603 (save-excursion
606 (funcall log-operation 604 (funcall log-operation
607 log-fileset 605 log-fileset
608 log-extra 606 log-entry))
609 log-entry
610 extra-flags
611 ))
612 ;; Remove checkin window (after the checkin so that if that fails 607 ;; Remove checkin window (after the checkin so that if that fails
613 ;; we don't zap the log buffer and the typing therein). 608 ;; we don't zap the log buffer and the typing therein).
614 ;; -- IMO this should be replaced with quit-window 609 ;; -- IMO this should be replaced with quit-window
diff --git a/lisp/vc-git.el b/lisp/vc-git.el
index 14cdb4a1e38..7b740734892 100644
--- a/lisp/vc-git.el
+++ b/lisp/vc-git.el
@@ -118,7 +118,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
118 :version "23.1" 118 :version "23.1"
119 :group 'vc) 119 :group 'vc)
120 120
121(defvar git-commits-coding-system 'utf-8 121(defvar vc-git-commits-coding-system 'utf-8
122 "Default coding system for git commits.") 122 "Default coding system for git commits.")
123 123
124;;; BACKEND PROPERTIES 124;;; BACKEND PROPERTIES
@@ -548,11 +548,15 @@ or an empty string if none."
548(defun vc-git-unregister (file) 548(defun vc-git-unregister (file)
549 (vc-git-command nil 0 file "rm" "-f" "--cached" "--")) 549 (vc-git-command nil 0 file "rm" "-f" "--cached" "--"))
550 550
551(declare-function log-edit-extract-headers "log-edit" (headers string))
551 552
552(defun vc-git-checkin (files rev comment &optional extra-args) 553(defun vc-git-checkin (files rev comment)
553 (let ((coding-system-for-write git-commits-coding-system)) 554 (let ((coding-system-for-write vc-git-commits-coding-system))
554 (apply 'vc-git-command nil 0 files 555 (apply 'vc-git-command nil 0 files
555 (nconc (list "commit" "-m" comment) extra-args (list "--only" "--"))))) 556 (nconc (list "commit" "-m")
557 (log-edit-extract-headers '(("Author" . "--author"))
558 comment)
559 (list "--only" "--")))))
556 560
557(defun vc-git-find-revision (file rev buffer) 561(defun vc-git-find-revision (file rev buffer)
558 (let* (process-file-side-effects 562 (let* (process-file-side-effects
@@ -582,7 +586,7 @@ or an empty string if none."
582 "Get change log associated with FILES. 586 "Get change log associated with FILES.
583Note that using SHORTLOG requires at least Git version 1.5.6, 587Note that using SHORTLOG requires at least Git version 1.5.6,
584for the --graph option." 588for the --graph option."
585 (let ((coding-system-for-read git-commits-coding-system)) 589 (let ((coding-system-for-read vc-git-commits-coding-system))
586 ;; `vc-do-command' creates the buffer, but we need it before running 590 ;; `vc-do-command' creates the buffer, but we need it before running
587 ;; the command. 591 ;; the command.
588 (vc-setup-buffer buffer) 592 (vc-setup-buffer buffer)
@@ -793,21 +797,6 @@ or BRANCH^ (where \"^\" can be repeated)."
793 (progn (forward-line 1) (1- (point))))))))) 797 (progn (forward-line 1) (1- (point)))))))))
794 (or (vc-git-symbolic-commit next-rev) next-rev))) 798 (or (vc-git-symbolic-commit next-rev) next-rev)))
795 799
796(declare-function log-edit-mode "log-edit" ())
797(defvar log-edit-extra-flags)
798(defvar log-edit-before-checkin-process)
799
800(define-derived-mode vc-git-log-edit-mode log-edit-mode "Git-log-edit"
801 "Mode for editing Git commit logs.
802If a line like:
803Author: NAME
804is present in the log, it is removed, and
805--author=NAME
806is passed to the git commit command."
807 (set (make-local-variable 'log-edit-extra-flags) nil)
808 (set (make-local-variable 'log-edit-before-checkin-process)
809 '(("^Author:[ \t]+\\(.*\\)[ \t]*$" . (list "--author" (match-string 1))))))
810
811(defun vc-git-delete-file (file) 800(defun vc-git-delete-file (file)
812 (vc-git-command nil 0 file "rm" "-f" "--")) 801 (vc-git-command nil 0 file "rm" "-f" "--"))
813 802
diff --git a/lisp/vc-hg.el b/lisp/vc-hg.el
index e67342d707a..6ccfd038ff4 100644
--- a/lisp/vc-hg.el
+++ b/lisp/vc-hg.el
@@ -296,20 +296,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
296 ("^tag: +\\([^ ]+\\)$" (1 'highlight)) 296 ("^tag: +\\([^ ]+\\)$" (1 'highlight))
297 ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))) 297 ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message)))))))
298 298
299(declare-function log-edit-mode "log-edit" ()) 299(declare-function log-edit-extract-headers "log-edit" (headers string))
300(defvar log-edit-extra-flags)
301(defvar log-edit-before-checkin-process)
302
303(define-derived-mode vc-hg-log-edit-mode log-edit-mode "Hg-log-edit"
304 "Mode for editing Hg commit logs.
305If a line like:
306Author: NAME
307is present in the log, it is removed, and
308--author NAME
309is passed to the hg commit command."
310 (set (make-local-variable 'log-edit-extra-flags) nil)
311 (set (make-local-variable 'log-edit-before-checkin-process)
312 '(("^Author:[ \t]+\\(.*\\)[ \t]*$" . (list "--user" (match-string 1))))))
313 300
314(defun vc-hg-diff (files &optional oldvers newvers buffer) 301(defun vc-hg-diff (files &optional oldvers newvers buffer)
315 "Get a difference report using hg between two revisions of FILES." 302 "Get a difference report using hg between two revisions of FILES."
@@ -434,11 +421,15 @@ COMMENT is ignored."
434;; "Unregister FILE from hg." 421;; "Unregister FILE from hg."
435;; (vc-hg-command nil nil file "remove")) 422;; (vc-hg-command nil nil file "remove"))
436 423
437(defun vc-hg-checkin (files rev comment &optional extra-args) 424(declare-function log-edit-extract-headers "log-edit" (headers string))
425
426(defun vc-hg-checkin (files rev comment)
438 "Hg-specific version of `vc-backend-checkin'. 427 "Hg-specific version of `vc-backend-checkin'.
439REV is ignored." 428REV is ignored."
440 (apply 'vc-hg-command nil 0 files 429 (apply 'vc-hg-command nil 0 files
441 (nconc (list "commit" "-m" comment) extra-args))) 430 (nconc (list "commit" "-m")
431 (log-edit-extract-headers '(("Author" . "--user"))
432 comment))))
442 433
443(defun vc-hg-find-revision (file rev buffer) 434(defun vc-hg-find-revision (file rev buffer)
444 (let ((coding-system-for-read 'binary) 435 (let ((coding-system-for-read 'binary)
diff --git a/lisp/vc.el b/lisp/vc.el
index 4bf5a92da1b..01952de2025 100644
--- a/lisp/vc.el
+++ b/lisp/vc.el
@@ -268,15 +268,12 @@
268;; Unregister FILE from this backend. This is only needed if this 268;; Unregister FILE from this backend. This is only needed if this
269;; backend may be used as a "more local" backend for temporary editing. 269;; backend may be used as a "more local" backend for temporary editing.
270;; 270;;
271;; * checkin (files rev comment &optional extra-args) 271;; * checkin (files rev comment)
272;; 272;;
273;; Commit changes in FILES to this backend. If REV is non-nil, that 273;; Commit changes in FILES to this backend. REV is a historical artifact
274;; should become the new revision number (not all backends do 274;; and should be ignored. COMMENT is used as a check-in comment.
275;; anything with it). COMMENT is used as a check-in comment. The 275;; The implementation should pass the value of vc-checkin-switches to
276;; implementation should pass the value of vc-checkin-switches to 276;; the backend command.
277;; the backend command. (Note: in older versions of VC, this
278;; command took a single file argument and not a list.)
279;; EXTRA-ARGS should be passed to the backend command.
280;; 277;;
281;; * find-revision (file rev buffer) 278;; * find-revision (file rev buffer)
282;; 279;;
@@ -548,6 +545,12 @@
548;; makes it possible to provide menu entries for functionality that 545;; makes it possible to provide menu entries for functionality that
549;; is specific to a backend and which does not map to any of the VC 546;; is specific to a backend and which does not map to any of the VC
550;; generic concepts. 547;; generic concepts.
548;;
549;; - conflicted-files (dir)
550;;
551;; Return the list of files where conflict resolution is needed in
552;; the project that contains DIR.
553;; FIXME: what should it do with non-text conflicts?
551 554
552;;; Todo: 555;;; Todo:
553 556
@@ -1054,8 +1057,7 @@ merge in the changes into your working copy."
1054 (state (nth 3 vc-fileset)) 1057 (state (nth 3 vc-fileset))
1055 ;; The backend should check that the checkout-model is consistent 1058 ;; The backend should check that the checkout-model is consistent
1056 ;; among all the `files'. 1059 ;; among all the `files'.
1057 (model (nth 4 vc-fileset)) 1060 (model (nth 4 vc-fileset)))
1058 revision)
1059 1061
1060 ;; Do the right thing 1062 ;; Do the right thing
1061 (cond 1063 (cond
@@ -1070,11 +1072,13 @@ merge in the changes into your working copy."
1070 (cond 1072 (cond
1071 (verbose 1073 (verbose
1072 ;; go to a different revision 1074 ;; go to a different revision
1073 (setq revision (read-string "Branch, revision, or backend to move to: ")) 1075 (let* ((revision
1074 (let ((revision-downcase (downcase revision))) 1076 (read-string "Branch, revision, or backend to move to: "))
1077 (revision-downcase (downcase revision)))
1075 (if (member 1078 (if (member
1076 revision-downcase 1079 revision-downcase
1077 (mapcar (lambda (arg) (downcase (symbol-name arg))) vc-handled-backends)) 1080 (mapcar (lambda (arg) (downcase (symbol-name arg)))
1081 vc-handled-backends))
1078 (let ((vsym (intern-soft revision-downcase))) 1082 (let ((vsym (intern-soft revision-downcase)))
1079 (dolist (file files) (vc-transfer-file file vsym))) 1083 (dolist (file files) (vc-transfer-file file vsym)))
1080 (dolist (file files) 1084 (dolist (file files)
@@ -1119,8 +1123,8 @@ merge in the changes into your working copy."
1119 (message "No files remain to be committed") 1123 (message "No files remain to be committed")
1120 (if (not verbose) 1124 (if (not verbose)
1121 (vc-checkin ready-for-commit backend) 1125 (vc-checkin ready-for-commit backend)
1122 (setq revision (read-string "New revision or backend: ")) 1126 (let* ((revision (read-string "New revision or backend: "))
1123 (let ((revision-downcase (downcase revision))) 1127 (revision-downcase (downcase revision)))
1124 (if (member 1128 (if (member
1125 revision-downcase 1129 revision-downcase
1126 (mapcar (lambda (arg) (downcase (symbol-name arg))) 1130 (mapcar (lambda (arg) (downcase (symbol-name arg)))
@@ -1365,7 +1369,7 @@ Type \\[vc-next-action] to check in changes.")
1365(defun vc-checkin (files backend &optional rev comment initial-contents) 1369(defun vc-checkin (files backend &optional rev comment initial-contents)
1366 "Check in FILES. 1370 "Check in FILES.
1367The optional argument REV may be a string specifying the new revision 1371The optional argument REV may be a string specifying the new revision
1368level (if nil increment the current level). COMMENT is a comment 1372level (strongly deprecated). COMMENT is a comment
1369string; if omitted, a buffer is popped up to accept a comment. If 1373string; if omitted, a buffer is popped up to accept a comment. If
1370INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents 1374INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents
1371of the log entry buffer. 1375of the log entry buffer.
@@ -1379,28 +1383,30 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
1379 (lexical-let 1383 (lexical-let
1380 ((backend backend)) 1384 ((backend backend))
1381 (vc-start-logentry 1385 (vc-start-logentry
1382 files rev comment initial-contents 1386 files comment initial-contents
1383 "Enter a change comment." 1387 "Enter a change comment."
1384 "*VC-log*" 1388 "*VC-log*"
1385 (lambda () 1389 (lambda ()
1386 (vc-call-backend backend 'log-edit-mode)) 1390 (vc-call-backend backend 'log-edit-mode))
1387 (lambda (files rev comment extra-flags) 1391 (lexical-let ((rev rev))
1388 (message "Checking in %s..." (vc-delistify files)) 1392 (lambda (files comment)
1389 ;; "This log message intentionally left almost blank". 1393 (message "Checking in %s..." (vc-delistify files))
1390 ;; RCS 5.7 gripes about white-space-only comments too. 1394 ;; "This log message intentionally left almost blank".
1391 (or (and comment (string-match "[^\t\n ]" comment)) 1395 ;; RCS 5.7 gripes about white-space-only comments too.
1392 (setq comment "*** empty log message ***")) 1396 (or (and comment (string-match "[^\t\n ]" comment))
1393 (with-vc-properties 1397 (setq comment "*** empty log message ***"))
1394 files 1398 (with-vc-properties
1395 ;; We used to change buffers to get local value of vc-checkin-switches, 1399 files
1396 ;; but 'the' local buffer is not a well-defined concept for filesets. 1400 ;; We used to change buffers to get local value of
1397 (progn 1401 ;; vc-checkin-switches, but 'the' local buffer is
1398 (vc-call-backend backend 'checkin files rev comment extra-flags) 1402 ;; not a well-defined concept for filesets.
1399 (mapc 'vc-delete-automatic-version-backups files)) 1403 (progn
1400 `((vc-state . up-to-date) 1404 (vc-call-backend backend 'checkin files rev comment)
1401 (vc-checkout-time . ,(nth 5 (file-attributes file))) 1405 (mapc 'vc-delete-automatic-version-backups files))
1402 (vc-working-revision . nil))) 1406 `((vc-state . up-to-date)
1403 (message "Checking in %s...done" (vc-delistify files))) 1407 (vc-checkout-time . ,(nth 5 (file-attributes file)))
1408 (vc-working-revision . nil)))
1409 (message "Checking in %s...done" (vc-delistify files))))
1404 'vc-checkin-hook))) 1410 'vc-checkin-hook)))
1405 1411
1406;;; Additional entry points for examining version histories 1412;;; Additional entry points for examining version histories
@@ -1772,13 +1778,14 @@ The headers are reset to their non-expanded form."
1772 ;; case the more general operation ever becomes meaningful. 1778 ;; case the more general operation ever becomes meaningful.
1773 (let ((backend (vc-responsible-backend (car files)))) 1779 (let ((backend (vc-responsible-backend (car files))))
1774 (vc-start-logentry 1780 (vc-start-logentry
1775 files rev oldcomment t 1781 files oldcomment t
1776 "Enter a replacement change comment." 1782 "Enter a replacement change comment."
1777 "*VC-log*" 1783 "*VC-log*"
1778 (lambda () (vc-call-backend backend 'log-edit-mode)) 1784 (lambda () (vc-call-backend backend 'log-edit-mode))
1779 (lambda (files rev comment ignored) 1785 (lexical-let ((rev rev))
1780 (vc-call-backend backend 1786 (lambda (files comment)
1781 'modify-change-comment files rev comment))))) 1787 (vc-call-backend backend
1788 'modify-change-comment files rev comment))))))
1782 1789
1783;;;###autoload 1790;;;###autoload
1784(defun vc-merge () 1791(defun vc-merge ()
@@ -1839,6 +1846,31 @@ See Info node `Merging'."
1839;;;###autoload 1846;;;###autoload
1840(defalias 'vc-resolve-conflicts 'smerge-ediff) 1847(defalias 'vc-resolve-conflicts 'smerge-ediff)
1841 1848
1849;; TODO: This is OK but maybe we could integrate it better.
1850;; E.g. it could be run semi-automatically (via a prompt?) when saving a file
1851;; that was conflicted (i.e. upon mark-resolved).
1852;; FIXME: should we add an "other-window" version? Or maybe we should
1853;; hook it inside find-file so it automatically works for
1854;; find-file-other-window as well. E.g. find-file could use a new
1855;; `default-next-file' variable for its default file (M-n), and
1856;; we could then set it upon mark-resolve, so C-x C-s C-x C-f M-n would
1857;; automatically offer the next conflicted file.
1858(defun vc-find-conflicted-file ()
1859 "Visit the next conflicted file in the current project."
1860 (interactive)
1861 (let* ((backend (or (if buffer-file-name (vc-backend buffer-file-name))
1862 (vc-responsible-backend default-directory)
1863 (error "No VC backend")))
1864 (files (vc-call-backend backend
1865 'conflicted-files default-directory)))
1866 ;; Don't try and visit the current file.
1867 (if (equal (car files) buffer-file-name) (pop files))
1868 (if (null files)
1869 (message "No more conflicted files")
1870 (find-file (pop files))
1871 (message "%s more conflicted files after this one"
1872 (if files (length files) "No")))))
1873
1842;; Named-configuration entry points 1874;; Named-configuration entry points
1843 1875
1844(defun vc-tag-precondition (dir) 1876(defun vc-tag-precondition (dir)