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.
This commit is contained in:
Stefan Monnier 2010-04-20 22:05:24 -04:00
parent 50426a043d
commit e97a42c15b
9 changed files with 268 additions and 158 deletions

View file

@ -88,6 +88,8 @@ define it as a scroll command affected by `scroll-preserve-screen-position.
** Archive Mode has basic support to browse 7z archives.
** partial-completion-mode is now obsolete.
You can get the same behavior with
(setq completion-styles '(partial-completion initials)).
** mpc.el: Can use pseudo tags of the form tag1|tag2 as a union of two tags.
** Customize
@ -106,23 +108,18 @@ choose a color via list-colors-display.
** VC and related modes
*** New VC commands: vc-log-incoming and vc-log-outgoing.
*** New VC commands: vc-log-incoming, vc-log-outgoing, vc-find-conflicted-file.
*** vc-dir for Bzr supports viewing shelve contents and shelving snapshots.
*** Special markup can be added to log-edit buffers.
**** For Bzr, adding an
Author: NAME
line will add "--author NAME" to the "bzr commit" command.
**** For Git, adding an
Author: NAME
line will add "--author NAME" to the "git commit" command.
**** For Hg, adding an
Author: NAME
line will add "--user NAME" to the "hg commit" command.
The log-edit buffers are expected to have a format similar to email messages
with headers of the form:
Author: <author of this change>
Summary: <one line summary of this change>
Fixes: <reference to the bug fixed by this change>
Some backends handle some of those headers specially, but any unknown header
is just left as is in the message, so it is not lost.
** Directory local variables can apply to file-less buffers.
For example, adding "(diff-mode . ((mode . whitespace)))" to your

View file

@ -1,3 +1,39 @@
2010-04-21 Stefan Monnier <monnier@iro.umontreal.ca>
* 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.
2010-04-20 Juanma Barranquero <lekktu@gmail.com>
* subr.el (default-direction-reversed): Remove obsolescence info.

View file

@ -1242,7 +1242,6 @@ Keywords supported: :test :test-not :key
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; coding: utf-8
;; End:
;; arch-tag: 08cc5aab-e992-47f6-992e-12a7428c1a0e
;;; cl-loaddefs.el ends here

View file

@ -125,6 +125,7 @@ If SETUP is 'force, this variable has no effect."
:type 'boolean)
(defcustom log-edit-hook '(log-edit-insert-cvs-template
log-edit-show-files
log-edit-insert-changelog)
"Hook run at the end of `log-edit'."
:group 'log-edit
@ -188,22 +189,6 @@ when this variable is set to nil.")
(defvar log-edit-callback nil)
(defvar log-edit-diff-function nil)
(defvar log-edit-listfun nil)
(defvar log-edit-extra-flags nil
"List of extra flags to pass to the check in command.")
(defvar log-edit-before-checkin-process nil
"Alist with instructions for processing the commit message before check in.
The format is: (REGEXP . INSTRUCTIONS).
All lines matching REGEXP are removed. For example:
\(\"^#.*\" . nil)
means: just remove all lines starting with #. This can be used
to insert lines in the commit buffer that contain, for example, the
list of files to be committed.
\(\"Author: \\\\(.*\\\\)\" . (list \"--author\" (match-string 1)))
means: append (list \"--author\" (match-string 1)) to `log-edit-extra-flags'.")
(defvar log-edit-parent-buffer nil)
@ -329,10 +314,53 @@ automatically."
;;; Actual code
;;;
(defface log-edit-summary '((t :inherit font-lock-function-name-face))
"Face for the summary in `log-edit-mode' buffers.")
(defface log-edit-header '((t :inherit font-lock-keyword-face))
"Face for the headers in `log-edit-mode' buffers.")
(defface log-edit-unknown-header '((t :inherit font-lock-comment-face))
"Face for unknown headers in `log-edit-mode' buffers.")
(defvar log-edit-headers-alist '(("Summary" . log-edit-summary)
("Fixes") ("Author"))
"AList of known headers and the face to use to highlight them.")
(defconst log-edit-header-contents-regexp
"[ \t]*\\(.*\\(\n[ \t].*\\)*\\)\n?")
(defun log-edit-match-to-eoh (limit)
;; FIXME: copied from message-match-to-eoh.
(let ((start (point)))
(rfc822-goto-eoh)
;; Typical situation: some temporary change causes the header to be
;; incorrect, so EOH comes earlier than intended: the last lines of the
;; intended headers are now not considered part of the header any more,
;; so they don't have the multiline property set. When the change is
;; completed and the header has its correct shape again, the lack of the
;; multiline property means we won't rehighlight the last lines of
;; the header.
(if (< (point) start)
nil ;No header within start..limit.
;; Here we disregard LIMIT so that we may extend the area again.
(set-match-data (list start (point)))
(point))))
(defvar log-edit-font-lock-keywords
'(("\\`\\(Summary:\\)\\(.*\\)"
(1 font-lock-keyword-face)
(2 font-lock-function-name-face))))
;; Copied/inspired by message-font-lock-keywords.
`((log-edit-match-to-eoh
(,(concat "^\\(\\([a-z]+\\):\\)" log-edit-header-contents-regexp
"\\|\\(.*\\)")
(progn (goto-char (match-beginning 0)) (match-end 0)) nil
(1 (if (assoc (match-string 2) log-edit-headers-alist)
'log-edit-header
'log-edit-unknown-header)
nil lax)
(3 (or (cdr (assoc (match-string 2) log-edit-headers-alist))
'log-edit-header)
nil lax)
(4 font-lock-warning-face)))))
;;;###autoload
(defun log-edit (callback &optional setup params buffer mode &rest ignore)
@ -358,7 +386,10 @@ uses the current buffer."
(if buffer (pop-to-buffer buffer))
(when (and log-edit-setup-invert (not (eq setup 'force)))
(setq setup (not setup)))
(when setup (erase-buffer))
(when setup
(erase-buffer)
(insert "Summary: ")
(save-excursion (insert "\n\n")))
(if mode
(funcall mode)
(log-edit-mode))
@ -387,7 +418,7 @@ commands (under C-x v for VC, for example).
\\{log-edit-mode-map}"
(set (make-local-variable 'font-lock-defaults)
'(log-edit-font-lock-keywords t))
'(log-edit-font-lock-keywords t t))
(make-local-variable 'log-edit-comment-ring-index)
(hack-dir-local-variables-non-file-buffer))
@ -401,6 +432,17 @@ commands (under C-x v for VC, for example).
"Finish editing the log message and commit the files.
If you want to abort the commit, simply delete the buffer."
(interactive)
;; Clean up empty headers.
(goto-char (point-min))
(while (looking-at (concat "^[a-z]*:" log-edit-header-contents-regexp))
(let ((beg (match-beginning 0)))
(goto-char (match-end 0))
(if (string-match "\\`[ \n\t]*\\'" (match-string 1))
(delete-region beg (point)))))
;; Get rid of leading empty lines.
(goto-char (point-min))
(when (looking-at "\\([ \t]*\n\\)+")
(delete-region (match-beginning 0) (match-end 0)))
;; Get rid of trailing empty lines
(goto-char (point-max))
(skip-syntax-backward " ")
@ -458,12 +500,13 @@ If you want to abort the commit, simply delete the buffer."
"(Un)Indent the current buffer rigidly to `log-edit-common-indent'."
(save-excursion
(let ((common (point-max)))
(goto-char (point-min))
(rfc822-goto-eoh)
(while (< (point) (point-max))
(if (not (looking-at "^[ \t]*$"))
(setq common (min common (current-indentation))))
(forward-line 1))
(indent-rigidly (point-min) (point-max)
(rfc822-goto-eoh)
(indent-rigidly (point) (point-max)
(- log-edit-common-indent common)))))
(defun log-edit-show-diff ()
@ -546,6 +589,10 @@ If the optional prefix arg USE-FIRST is given (via \\[universal-argument]),
or if the command is repeated a second time in a row, use the first log entry
regardless of user name or time."
(interactive "P")
(let ((eoh (save-excursion (rfc822-goto-eoh) (point))))
(when (<= (point) eoh)
(goto-char eoh)
(if (looking-at "\n") (forward-char 1))))
(let ((log-edit-changelog-use-first
(or use-first (eq last-command 'log-edit-insert-changelog))))
(log-edit-insert-changelog-entries (log-edit-files)))
@ -731,16 +778,39 @@ Sort REGIONS front-to-back first."
(log-edit-changelog-insert-entries (car buffer-entry) (cdr buffer-entry))
(when (cdr buffer-entry) (newline)))))
(defun log-view-process-buffer ()
(when log-edit-before-checkin-process
(dolist (crt log-edit-before-checkin-process)
;; Remove all lines matching (car crt)
;; Append to `log-edit-extra-flags' the results of (cdr crt).
(defun log-edit-extract-headers (headers comment)
"Extract headers from COMMENT to form command line arguments.
HEADERS should be an alist with elements of the form (HEADER . CMDARG)
associating header names to the corresponding cmdline option name and the
result is then a list of the form (MSG CMDARG1 HDRTEXT1 CMDARG2 HDRTEXT2...).
where MSG is the remaining text from STRING.
If \"Summary\" is not in HEADERS, then the \"Summary\" header is extracted
anyway and put back as the first line of MSG."
(with-temp-buffer
(insert comment)
(rfc822-goto-eoh)
(narrow-to-region (point-min) (point))
(let ((case-fold-search t)
(summary ())
(res ()))
(dolist (header (if (assoc "Summary" headers) headers
(cons '("Summary" . t) headers)))
(goto-char (point-min))
(while (re-search-forward (concat "^" (car header)
":" log-edit-header-contents-regexp)
nil t)
(if (eq t (cdr header))
(setq summary (match-string 1))
(push (match-string 1) res)
(push (or (cdr header) (car header)) res))
(replace-match "" t t)))
;; Remove header separator if the header is empty.
(widen)
(goto-char (point-min))
(while (re-search-forward (car crt) nil t)
(when (cdr crt)
(setq log-edit-extra-flags (append log-edit-extra-flags (eval (cdr crt)))))
(replace-match "" nil t)))))
(when (looking-at "\\([ \t]*\n\\)+")
(delete-region (match-beginning 0) (match-end 0)))
(if summary (insert summary "\n"))
(cons (buffer-string) res))))
(provide 'log-edit)

View file

@ -451,11 +451,16 @@ or a superior directory.")
"Unregister FILE from bzr."
(vc-bzr-command "remove" nil 0 file "--keep"))
(defun vc-bzr-checkin (files rev comment &optional extra-args)
(declare-function log-edit-extract-headers "log-edit" (headers string))
(defun vc-bzr-checkin (files rev comment)
"Check FILE in to bzr with log message COMMENT.
REV non-nil gets an error."
(if rev (error "Can't check in a specific revision with bzr"))
(apply 'vc-bzr-command "commit" nil 0 files (append (list "-m" comment) extra-args)))
(apply 'vc-bzr-command "commit" nil 'async
files (cons "-m" (log-edit-extract-headers '(("Author" . "--author")
("Fixes" . "--fixes"))
comment))))
(defun vc-bzr-find-revision (file rev buffer)
"Fetch revision REV of file FILE and put it into BUFFER."
@ -552,23 +557,6 @@ REV non-nil gets an error."
(goto-char (point-min)))
found)))
(declare-function log-edit-mode "log-edit" ())
(defvar log-edit-extra-flags)
(defvar log-edit-before-checkin-process)
(define-derived-mode vc-bzr-log-edit-mode log-edit-mode "Bzr-Log-Edit"
"Mode for editing Bzr commit logs.
If a line like:
Author: NAME
is present in the log, it is removed, and
--author NAME
is passed to the bzr commit command. Similarly with Fixes: and --fixes."
(set (make-local-variable 'log-edit-extra-flags) nil)
(set (make-local-variable 'log-edit-before-checkin-process)
'(("^\\(Author\\|Fixes\\):[ \t]+\\(.*\\)[ \t]*$" .
(list (format "--%s" (downcase (match-string 1)))
(match-string 2))))))
(defun vc-bzr-diff (files &optional rev1 rev2 buffer)
"VC bzr backend for diff."
;; `bzr diff' exits with code 1 if diff is non-empty.
@ -983,6 +971,19 @@ stream. Standard error output is discarded."
(setq loglines (buffer-substring-no-properties start (point-max))))))
vc-bzr-revisions))
(defun vc-bzr-conflicted-files (dir)
(let ((default-directory (vc-bzr-root dir))
(files ()))
(with-temp-buffer
(vc-bzr-command "status" t 0 default-directory)
(goto-char (point-min))
(when (re-search-forward "^conflicts:\n" nil t)
(while (looking-at " \\(?:Text conflict in \\(.*\\)\\|.*\\)\n")
(if (match-end 1)
(push (expand-file-name (match-string 1)) files))
(goto-char (match-end 0)))))
files))
;;; Revision completion
(eval-and-compile

View file

@ -141,7 +141,6 @@ preserve the setting."
(defvar vc-log-operation nil)
(defvar vc-log-after-operation-hook nil)
(defvar vc-log-fileset)
(defvar vc-log-extra)
;; In a log entry buffer, this is a local variable
;; 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."
(with-current-buffer vc-parent-buffer default-directory))
(log-edit 'vc-finish-logentry
nil
`((log-edit-listfun . (lambda () ',fileset))
`((log-edit-listfun . (lambda ()
;; FIXME: Should expand the list
;; for directories.
(mapcar 'file-relative-name
',fileset)))
(log-edit-diff-function . (lambda () (vc-diff nil))))
nil
mode)
(set (make-local-variable 'vc-log-fileset) fileset)
(make-local-variable 'vc-log-extra)
(set-buffer-modified-p nil)
(setq buffer-file-name nil))
(defun vc-start-logentry (files extra comment initial-contents msg logbuf mode action &optional after-hook)
"Accept a comment for an operation on FILES with extra data EXTRA.
(defun vc-start-logentry (files comment initial-contents msg logbuf mode action &optional after-hook)
"Accept a comment for an operation on FILES.
If COMMENT is nil, pop up a LOGBUF buffer, emit MSG, and set the
action on close to ACTION. If COMMENT is a string and
INITIAL-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'."
(when after-hook
(setq vc-log-after-operation-hook after-hook))
(setq vc-log-operation action)
(setq vc-log-extra extra)
(when comment
(erase-buffer)
(when (stringp comment) (insert comment)))
@ -570,10 +571,8 @@ AFTER-HOOK specifies the local value for `vc-log-after-operation-hook'."
(vc-finish-logentry (eq comment t)))))
(declare-function vc-dir-move-to-goal-column "vc-dir" ())
;; vc-finish-logentry is called from a log-edit buffer (see above).
(declare-function log-view-process-buffer "log-edit" ())
(defvar log-edit-extra-flags)
;; vc-finish-logentry is typically called from a log-edit buffer (see
;; vc-start-logentry).
(defun vc-finish-logentry (&optional nocomment)
"Complete the operation implied by the current log entry.
Use the contents of the current buffer as a check-in or registration
@ -590,25 +589,21 @@ the buffer contents as a comment."
(unless vc-log-operation
(error "No log operation is pending"))
(log-view-process-buffer)
;; save the parameters held in buffer-local variables
(let ((logbuf (current-buffer))
(log-operation vc-log-operation)
;; FIXME: When coming from VC-Dir, we should check that the
;; set of selected files is still equal to vc-log-fileset,
;; to avoid surprises.
(log-fileset vc-log-fileset)
(log-extra vc-log-extra)
(log-entry (buffer-string))
(extra-flags log-edit-extra-flags)
(after-hook vc-log-after-operation-hook))
(pop-to-buffer vc-parent-buffer)
;; OK, do it to it
(save-excursion
(funcall log-operation
log-fileset
log-extra
log-entry
extra-flags
))
log-entry))
;; Remove checkin window (after the checkin so that if that fails
;; we don't zap the log buffer and the typing therein).
;; -- IMO this should be replaced with quit-window

View file

@ -118,7 +118,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
:version "23.1"
:group 'vc)
(defvar git-commits-coding-system 'utf-8
(defvar vc-git-commits-coding-system 'utf-8
"Default coding system for git commits.")
;;; BACKEND PROPERTIES
@ -548,11 +548,15 @@ or an empty string if none."
(defun vc-git-unregister (file)
(vc-git-command nil 0 file "rm" "-f" "--cached" "--"))
(declare-function log-edit-extract-headers "log-edit" (headers string))
(defun vc-git-checkin (files rev comment &optional extra-args)
(let ((coding-system-for-write git-commits-coding-system))
(defun vc-git-checkin (files rev comment)
(let ((coding-system-for-write vc-git-commits-coding-system))
(apply 'vc-git-command nil 0 files
(nconc (list "commit" "-m" comment) extra-args (list "--only" "--")))))
(nconc (list "commit" "-m")
(log-edit-extract-headers '(("Author" . "--author"))
comment)
(list "--only" "--")))))
(defun vc-git-find-revision (file rev buffer)
(let* (process-file-side-effects
@ -582,7 +586,7 @@ or an empty string if none."
"Get change log associated with FILES.
Note that using SHORTLOG requires at least Git version 1.5.6,
for the --graph option."
(let ((coding-system-for-read git-commits-coding-system))
(let ((coding-system-for-read vc-git-commits-coding-system))
;; `vc-do-command' creates the buffer, but we need it before running
;; the command.
(vc-setup-buffer buffer)
@ -793,21 +797,6 @@ or BRANCH^ (where \"^\" can be repeated)."
(progn (forward-line 1) (1- (point)))))))))
(or (vc-git-symbolic-commit next-rev) next-rev)))
(declare-function log-edit-mode "log-edit" ())
(defvar log-edit-extra-flags)
(defvar log-edit-before-checkin-process)
(define-derived-mode vc-git-log-edit-mode log-edit-mode "Git-log-edit"
"Mode for editing Git commit logs.
If a line like:
Author: NAME
is present in the log, it is removed, and
--author=NAME
is passed to the git commit command."
(set (make-local-variable 'log-edit-extra-flags) nil)
(set (make-local-variable 'log-edit-before-checkin-process)
'(("^Author:[ \t]+\\(.*\\)[ \t]*$" . (list "--author" (match-string 1))))))
(defun vc-git-delete-file (file)
(vc-git-command nil 0 file "rm" "-f" "--"))

View file

@ -296,20 +296,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
("^tag: +\\([^ ]+\\)$" (1 'highlight))
("^summary:[ \t]+\\(.+\\)" (1 'log-view-message)))))))
(declare-function log-edit-mode "log-edit" ())
(defvar log-edit-extra-flags)
(defvar log-edit-before-checkin-process)
(define-derived-mode vc-hg-log-edit-mode log-edit-mode "Hg-log-edit"
"Mode for editing Hg commit logs.
If a line like:
Author: NAME
is present in the log, it is removed, and
--author NAME
is passed to the hg commit command."
(set (make-local-variable 'log-edit-extra-flags) nil)
(set (make-local-variable 'log-edit-before-checkin-process)
'(("^Author:[ \t]+\\(.*\\)[ \t]*$" . (list "--user" (match-string 1))))))
(declare-function log-edit-extract-headers "log-edit" (headers string))
(defun vc-hg-diff (files &optional oldvers newvers buffer)
"Get a difference report using hg between two revisions of FILES."
@ -434,11 +421,15 @@ COMMENT is ignored."
;; "Unregister FILE from hg."
;; (vc-hg-command nil nil file "remove"))
(defun vc-hg-checkin (files rev comment &optional extra-args)
(declare-function log-edit-extract-headers "log-edit" (headers string))
(defun vc-hg-checkin (files rev comment)
"Hg-specific version of `vc-backend-checkin'.
REV is ignored."
(apply 'vc-hg-command nil 0 files
(nconc (list "commit" "-m" comment) extra-args)))
(nconc (list "commit" "-m")
(log-edit-extract-headers '(("Author" . "--user"))
comment))))
(defun vc-hg-find-revision (file rev buffer)
(let ((coding-system-for-read 'binary)

View file

@ -268,15 +268,12 @@
;; Unregister FILE from this backend. This is only needed if this
;; backend may be used as a "more local" backend for temporary editing.
;;
;; * checkin (files rev comment &optional extra-args)
;; * checkin (files rev comment)
;;
;; Commit changes in FILES to this backend. If REV is non-nil, that
;; should become the new revision number (not all backends do
;; anything with it). COMMENT is used as a check-in comment. The
;; implementation should pass the value of vc-checkin-switches to
;; the backend command. (Note: in older versions of VC, this
;; command took a single file argument and not a list.)
;; EXTRA-ARGS should be passed to the backend command.
;; Commit changes in FILES to this backend. REV is a historical artifact
;; and should be ignored. COMMENT is used as a check-in comment.
;; The implementation should pass the value of vc-checkin-switches to
;; the backend command.
;;
;; * find-revision (file rev buffer)
;;
@ -548,6 +545,12 @@
;; makes it possible to provide menu entries for functionality that
;; is specific to a backend and which does not map to any of the VC
;; generic concepts.
;;
;; - conflicted-files (dir)
;;
;; Return the list of files where conflict resolution is needed in
;; the project that contains DIR.
;; FIXME: what should it do with non-text conflicts?
;;; Todo:
@ -1054,8 +1057,7 @@ merge in the changes into your working copy."
(state (nth 3 vc-fileset))
;; The backend should check that the checkout-model is consistent
;; among all the `files'.
(model (nth 4 vc-fileset))
revision)
(model (nth 4 vc-fileset)))
;; Do the right thing
(cond
@ -1070,11 +1072,13 @@ merge in the changes into your working copy."
(cond
(verbose
;; go to a different revision
(setq revision (read-string "Branch, revision, or backend to move to: "))
(let ((revision-downcase (downcase revision)))
(let* ((revision
(read-string "Branch, revision, or backend to move to: "))
(revision-downcase (downcase revision)))
(if (member
revision-downcase
(mapcar (lambda (arg) (downcase (symbol-name arg))) vc-handled-backends))
(mapcar (lambda (arg) (downcase (symbol-name arg)))
vc-handled-backends))
(let ((vsym (intern-soft revision-downcase)))
(dolist (file files) (vc-transfer-file file vsym)))
(dolist (file files)
@ -1119,8 +1123,8 @@ merge in the changes into your working copy."
(message "No files remain to be committed")
(if (not verbose)
(vc-checkin ready-for-commit backend)
(setq revision (read-string "New revision or backend: "))
(let ((revision-downcase (downcase revision)))
(let* ((revision (read-string "New revision or backend: "))
(revision-downcase (downcase revision)))
(if (member
revision-downcase
(mapcar (lambda (arg) (downcase (symbol-name arg)))
@ -1365,7 +1369,7 @@ Type \\[vc-next-action] to check in changes.")
(defun vc-checkin (files backend &optional rev comment initial-contents)
"Check in FILES.
The optional argument REV may be a string specifying the new revision
level (if nil increment the current level). COMMENT is a comment
level (strongly deprecated). COMMENT is a comment
string; if omitted, a buffer is popped up to accept a comment. If
INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents
of the log entry buffer.
@ -1379,28 +1383,30 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
(lexical-let
((backend backend))
(vc-start-logentry
files rev comment initial-contents
files comment initial-contents
"Enter a change comment."
"*VC-log*"
(lambda ()
(vc-call-backend backend 'log-edit-mode))
(lambda (files rev comment extra-flags)
(message "Checking in %s..." (vc-delistify files))
;; "This log message intentionally left almost blank".
;; RCS 5.7 gripes about white-space-only comments too.
(or (and comment (string-match "[^\t\n ]" comment))
(setq comment "*** empty log message ***"))
(with-vc-properties
files
;; We used to change buffers to get local value of vc-checkin-switches,
;; but 'the' local buffer is not a well-defined concept for filesets.
(progn
(vc-call-backend backend 'checkin files rev comment extra-flags)
(mapc 'vc-delete-automatic-version-backups files))
`((vc-state . up-to-date)
(vc-checkout-time . ,(nth 5 (file-attributes file)))
(vc-working-revision . nil)))
(message "Checking in %s...done" (vc-delistify files)))
(lexical-let ((rev rev))
(lambda (files comment)
(message "Checking in %s..." (vc-delistify files))
;; "This log message intentionally left almost blank".
;; RCS 5.7 gripes about white-space-only comments too.
(or (and comment (string-match "[^\t\n ]" comment))
(setq comment "*** empty log message ***"))
(with-vc-properties
files
;; We used to change buffers to get local value of
;; vc-checkin-switches, but 'the' local buffer is
;; not a well-defined concept for filesets.
(progn
(vc-call-backend backend 'checkin files rev comment)
(mapc 'vc-delete-automatic-version-backups files))
`((vc-state . up-to-date)
(vc-checkout-time . ,(nth 5 (file-attributes file)))
(vc-working-revision . nil)))
(message "Checking in %s...done" (vc-delistify files))))
'vc-checkin-hook)))
;;; Additional entry points for examining version histories
@ -1772,13 +1778,14 @@ The headers are reset to their non-expanded form."
;; case the more general operation ever becomes meaningful.
(let ((backend (vc-responsible-backend (car files))))
(vc-start-logentry
files rev oldcomment t
files oldcomment t
"Enter a replacement change comment."
"*VC-log*"
(lambda () (vc-call-backend backend 'log-edit-mode))
(lambda (files rev comment ignored)
(vc-call-backend backend
'modify-change-comment files rev comment)))))
(lexical-let ((rev rev))
(lambda (files comment)
(vc-call-backend backend
'modify-change-comment files rev comment))))))
;;;###autoload
(defun vc-merge ()
@ -1839,6 +1846,31 @@ See Info node `Merging'."
;;;###autoload
(defalias 'vc-resolve-conflicts 'smerge-ediff)
;; TODO: This is OK but maybe we could integrate it better.
;; E.g. it could be run semi-automatically (via a prompt?) when saving a file
;; that was conflicted (i.e. upon mark-resolved).
;; FIXME: should we add an "other-window" version? Or maybe we should
;; hook it inside find-file so it automatically works for
;; find-file-other-window as well. E.g. find-file could use a new
;; `default-next-file' variable for its default file (M-n), and
;; we could then set it upon mark-resolve, so C-x C-s C-x C-f M-n would
;; automatically offer the next conflicted file.
(defun vc-find-conflicted-file ()
"Visit the next conflicted file in the current project."
(interactive)
(let* ((backend (or (if buffer-file-name (vc-backend buffer-file-name))
(vc-responsible-backend default-directory)
(error "No VC backend")))
(files (vc-call-backend backend
'conflicted-files default-directory)))
;; Don't try and visit the current file.
(if (equal (car files) buffer-file-name) (pop files))
(if (null files)
(message "No more conflicted files")
(find-file (pop files))
(message "%s more conflicted files after this one"
(if files (length files) "No")))))
;; Named-configuration entry points
(defun vc-tag-precondition (dir)