aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2010-10-31 23:13:42 -0400
committerChong Yidong2010-10-31 23:13:42 -0400
commit98cfec0d6935f25a54852caaa33112ea1ca4634b (patch)
tree95822bce29eaee01ee15f79a24405489e2eaf8d5
parent6aad7ea061dac5966904f6a6b4f36816d9c87d10 (diff)
downloademacs-98cfec0d6935f25a54852caaa33112ea1ca4634b.tar.gz
emacs-98cfec0d6935f25a54852caaa33112ea1ca4634b.zip
Backport VC improvements from trunk.
* vc/log-edit.el (log-edit-rewrite-fixes): New var. (log-edit-author): New dynamic var. (log-edit-changelog-ours-p, log-edit-insert-changelog-entries): Use it to return the author if different from committer. (log-edit-insert-changelog): Use them to add Author: and Fixes headers. * vc/vc-hooks.el (vc-default-mode-line-string): Doc fix. * vc/vc.el (vc-deduce-backend): New fun. Handle diff buffers. (vc-root-diff, vc-print-root-log, vc-log-incoming) (vc-log-outgoing): Use it. (vc-diff-internal): Set diff-vc-backend. * vc/diff-mode.el (diff-vc-backend): New var. * vc/vc.el (vc-diff-internal): Set `revert-buffer-function' buffer-locally to lambda that re-runs the vc diff command. (Bug#6447) * vc/log-view.el (log-view-mode-map): Bind revert-buffer. Make 'g' (AKA revert-buffer) rerun VC log, log-incoming and log-outgoing commands. * vc/vc.el (vc-log-internal-common): Add a new argument and use it to create a buffer local revert-buffer-function variable. (vc-print-log-internal, vc-log-incoming, vc-log-outgoing): Pass a revert-buffer-function lambda. Improve VC create/retrieve tag/branch. * vc.el (vc-create-tag): Do not read the directory name for VCs with repository revision granularity. Adjust the tag/branch prompt. Reset VC properties. (vc-retrieve-tag): Do not read the directory name for VCs with repository revision granularity. Reset VC properties. Add optional support for resetting VC properties. * vc-dispatcher.el (vc-resynch-window): Add new optional argument, call vc-file-clearprops when true. (vc-resynch-buffer): Add new optional argument, pass it down. (vc-resynch-buffers-in-directory): Likewise. Improve support for special markup in the VC commit message. * vc-mtn.el (vc-mtn-checkin): Support Author: and Date: markup. * vc-hg.el (vc-hg-checkin): Add support for Date:. * vc-git.el (vc-git-checkin): * vc-bzr.el (vc-bzr-checkin): Likewise. Add support for vc-log-incoming, improve vc-log-outgoing for Git. * vc-git.el (vc-git-log-view-mode): Fix font lock for incoming/outgoing logs. (vc-git-log-outgoing, vc-git-log-incoming): New functions. * vc-git.el (vc-git-log-outgoing): Use the same format as the short log. (vc-git-log-incoming): Likewise. Run "git fetch" before the log command Add bindings for vc-log-incoming and vc-log-outgoing. * vc-hooks.el (vc-prefix-map): Add bindings for vc-log-incoming and vc-log-outgoing. * vc-dir.el (vc-dir-menu-map): Add menu bindings for vc-log-incoming and vc-log-outgoing. Improve state updating for VC tag commands. * vc.el (vc-create-tag, vc-retrieve-tag): Call vc-resynch-buffer to update the state of all buffers in the directory. * vc-dir.el (vc-dir): Don't pop-up-windows. (Bug#6204) * 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-git.el (vc-git-checkin): 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-bzr.el (vc-bzr-checkin): Use log-edit-extract-headers. (vc-bzr-conflicted-files): New function. * log-edit.el (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-edit-extract-headers): New function to replace it. * vc-dispatcher.el (vc-finish-logentry): Don't mess so badly with the windows/frames. * vc-bzr.el (vc-bzr-shelve-apply): Don't use *vc-bzr-shelve*. * vc-dir.el (vc-dir-kill-line): New command. (vc-dir-mode-map): Bind it to C-k. (vc-dir-headers): Abbreviate the working dir. * vc-git.el (vc-git-revision-table): Include remote branches. New VC methods: vc-log-incoming and vc-log-outgoing. * vc.el (vc-print-log-setup-buttons, vc-log-internal-common) (vc-incoming-outgoing-internal, vc-log-incoming, vc-log-outgoing): New functions. (vc-print-log-internal): Just call vc-log-internal-common. (vc-log-view-type): New permanent local variable. * vc-hooks.el (vc-menu-map): Bind vc-log-incoming and vc-log-outgoing. * vc-bzr.el (vc-bzr-log-view-mode): Use vc-log-view-type instead of the dynamic bound vc-short-log. (vc-bzr-log-incoming, vc-bzr-log-outgoing): New functions. * vc-git.el (vc-git-log-outgoing): New function. (vc-git-log-view-mode): Use vc-log-view-type instead of the dynamic bound vc-short-log. * vc-hg.el (vc-hg-log-view-mode): Use vc-log-view-type instead of the dynamic bound vc-short-log. Highlight the tag. (vc-hg-log-incoming, vc-hg-log-outgoing): New functions. (vc-hg-outgoing, vc-hg-incoming, vc-hg-outgoing-mode): (vc-hg-incoming-mode): Remove. (vc-hg-extra-menu-map): Do not bind vc-hg-incoming and vc-hg-outgoing. Fix default-directory for vc-root-diff. * vc.el (vc-root-diff): Bind default-directory to the root directory for the diff command. * vc-hg.el (vc-hg-push, vc-hg-pull): Use `apply' when calling `vc-hg-command' with a list of flags. * vc-bzr.el (vc-bzr-log-edit-mode): Add --fixes support to log-edit-before-checkin-process. * vc.el (vc-modify-change-comment): Pass MODE to vc-start-logentry. * vc-bzr.el, vc-hg.el (log-edit-mode): Declare. * vc-dispatcher.el (vc-start-logentry): Doc fix. (log-view-process-buffer, log-edit-extra-flags): Declare. Add special markup processing for commit logs. * log-edit.el (log-edit): Add new argument MODE. Use that mode when non-nil instead of the log-view-mode. * vc.el (vc-default-log-edit-mode): New function. * vc-dispatcher.el (vc-log-edit): Add a mode argument, pass it to log-edit. Support for shelving snapshots and for showing shelves. * vc-bzr.el (vc-bzr-shelve-show, vc-bzr-shelve-show-at-point) (vc-bzr-shelve-apply-and-keep-at-point, vc-bzr-shelve-snapshot): New functions. (vc-bzr-shelve-map, vc-bzr-shelve-menu-map) (vc-bzr-extra-menu-map): Map them.
-rw-r--r--etc/NEWS36
-rw-r--r--lisp/ChangeLog185
-rw-r--r--lisp/diff-mode.el4
-rw-r--r--lisp/log-edit.el261
-rw-r--r--lisp/log-view.el1
-rw-r--r--lisp/vc-arch.el3
-rw-r--r--lisp/vc-bzr.el101
-rw-r--r--lisp/vc-dir.el27
-rw-r--r--lisp/vc-dispatcher.el62
-rw-r--r--lisp/vc-git.el58
-rw-r--r--lisp/vc-hg.el89
-rw-r--r--lisp/vc-hooks.el21
-rw-r--r--lisp/vc-mtn.el8
-rw-r--r--lisp/vc.el382
14 files changed, 957 insertions, 281 deletions
diff --git a/etc/NEWS b/etc/NEWS
index e1e7ba79d41..fd6d1b5a954 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -34,6 +34,42 @@ alt/option key by customizing the value for ns-right-alternate-modifier.
34** The appt-add command takes an optional argument for the warning time. 34** The appt-add command takes an optional argument for the warning time.
35This can be used in place of the default appt-message-warning-time. 35This can be used in place of the default appt-message-warning-time.
36 36
37** VC and related modes
38
39*** New VC commands: vc-log-incoming, vc-log-outgoing, vc-find-conflicted-file.
40
41**** vc-log-incoming for Git runs "git fetch" so that the necessary
42data is available locally.
43
44**** vc-log-incoming and vc-log-outgoing for Git require version 1.7 (or newer).
45
46*** New key bindings: C-x v I and C-x v O bound to vc-log-incoming and
47vc-log-outgoing, respectively.
48
49*** The 'g' key in VC diff, log, log-incoming and log-outgoing buffers
50reruns the corresponding VC command to compute an up to date version
51of the buffer.
52
53*** vc-dir for Bzr supports viewing shelve contents and shelving snapshots.
54
55*** Special markup can be added to log-edit buffers.
56The log-edit buffers are expected to have a format similar to email messages
57with headers of the form:
58 Author: <author of this change>
59 Summary: <one line summary of this change>
60 Fixes: <reference to the bug fixed by this change>
61Some backends handle some of those headers specially, but any unknown header
62is just left as is in the message, so it is not lost.
63
64**** vc-git handles Author: and Date:
65**** vc-hg handles Author: and Date:
66**** vc-bzr handles Author:, Date: and Fixes:
67**** vc-mtn handles Author: and Date:
68
69*** Pressing g in a *vc-diff* buffer reruns vc-diff, so it will
70produce an up to date diff.
71
72
37** Obsolete packages 73** Obsolete packages
38 74
39+++ 75+++
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 3944fdebc69..d2a1713ed27 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,188 @@
12010-10-31 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * vc/log-edit.el (log-edit-rewrite-fixes): New var.
4 (log-edit-author): New dynamic var.
5 (log-edit-changelog-ours-p, log-edit-insert-changelog-entries):
6 Use it to return the author if different from committer.
7 (log-edit-insert-changelog): Use them to add Author: and Fixes headers.
8
92010-10-31 Eli Zaretskii <eliz@gnu.org>
10
11 * vc/vc-hooks.el (vc-default-mode-line-string): Doc fix.
12
132010-10-31 Chong Yidong <cyd@stupidchicken.com>
14
15 * vc/vc.el (vc-deduce-backend): New fun. Handle diff buffers.
16 (vc-root-diff, vc-print-root-log, vc-log-incoming)
17 (vc-log-outgoing): Use it.
18 (vc-diff-internal): Set diff-vc-backend.
19
20 * vc/diff-mode.el (diff-vc-backend): New var.
21
222010-10-31 Juri Linkov <juri@jurta.org>
23
24 * vc/vc.el (vc-diff-internal): Set `revert-buffer-function'
25 buffer-locally to lambda that re-runs the vc diff command.
26 (Bug#6447)
27
282010-10-31 Dan Nicolaescu <dann@ics.uci.edu>
29
30 * vc/log-view.el (log-view-mode-map): Bind revert-buffer.
31
32 Make 'g' (AKA revert-buffer) rerun VC log, log-incoming and
33 log-outgoing commands.
34 * vc/vc.el (vc-log-internal-common): Add a new argument and use it
35 to create a buffer local revert-buffer-function variable.
36 (vc-print-log-internal, vc-log-incoming, vc-log-outgoing): Pass a
37 revert-buffer-function lambda.
38
39 Improve VC create/retrieve tag/branch.
40 * vc.el (vc-create-tag): Do not read the directory name for VCs
41 with repository revision granularity. Adjust the tag/branch
42 prompt. Reset VC properties.
43 (vc-retrieve-tag): Do not read the directory name for VCs
44 with repository revision granularity. Reset VC properties.
45
46 Add optional support for resetting VC properties.
47 * vc-dispatcher.el (vc-resynch-window): Add new optional argument,
48 call vc-file-clearprops when true.
49 (vc-resynch-buffer): Add new optional argument, pass it down.
50 (vc-resynch-buffers-in-directory): Likewise.
51
52 Improve support for special markup in the VC commit message.
53 * vc-mtn.el (vc-mtn-checkin): Support Author: and Date: markup.
54 * vc-hg.el (vc-hg-checkin): Add support for Date:.
55 * vc-git.el (vc-git-checkin):
56 * vc-bzr.el (vc-bzr-checkin): Likewise.
57
58 Add support for vc-log-incoming, improve vc-log-outgoing for Git.
59 * vc-git.el (vc-git-log-view-mode): Fix font lock for
60 incoming/outgoing logs.
61 (vc-git-log-outgoing, vc-git-log-incoming): New functions.
62
63 * vc-git.el (vc-git-log-outgoing): Use the same format as the
64 short log.
65 (vc-git-log-incoming): Likewise. Run "git fetch" before the log
66 command
67
68 Add bindings for vc-log-incoming and vc-log-outgoing.
69 * vc-hooks.el (vc-prefix-map): Add bindings for vc-log-incoming
70 and vc-log-outgoing.
71 * vc-dir.el (vc-dir-menu-map): Add menu bindings for vc-log-incoming
72 and vc-log-outgoing.
73
74 Improve state updating for VC tag commands.
75 * vc.el (vc-create-tag, vc-retrieve-tag): Call vc-resynch-buffer
76 to update the state of all buffers in the directory.
77
782010-05-19 Glenn Morris <rgm@gnu.org>
79
80 * vc-dir.el (vc-dir): Don't pop-up-windows. (Bug#6204)
81
822010-10-31 Stefan Monnier <monnier@iro.umontreal.ca>
83
84 * vc.el (vc-checkin, vc-modify-change-comment):
85 Adjust to new vc-start/finish-logentry.
86 (vc-find-conflicted-file): New command.
87 (vc-transfer-file): Adjust to new vc-checkin.
88 (vc-next-action): Improve scoping.
89
90 * vc-git.el (vc-git-checkin): Use log-edit-extract-headers.
91 (vc-git-commits-coding-system): Rename from git-commits-coding-system.
92
93 * vc-dispatcher.el (vc-log-edit): Shorten names for
94 log-edit-show-files.
95
96 * vc-bzr.el (vc-bzr-checkin): Use log-edit-extract-headers.
97 (vc-bzr-conflicted-files): New function.
98
99 * log-edit.el (log-edit-summary, log-edit-header)
100 (log-edit-unknown-header): New faces.
101 (log-edit-headers-alist): New var.
102 (log-edit-header-contents-regexp): New const.
103 (log-edit-match-to-eoh): New function.
104 (log-edit-font-lock-keywords): Use them.
105 (log-edit): Insert a "Summary:" header as default.
106 (log-edit-mode): Mark font-lock rules as case-insensitive.
107 (log-edit-done): Cleanup headers.
108 (log-edit-extract-headers): New function to replace it.
109
110 * vc-dispatcher.el (vc-finish-logentry): Don't mess so badly with
111 the windows/frames.
112
113 * vc-bzr.el (vc-bzr-shelve-apply): Don't use *vc-bzr-shelve*.
114
115 * vc-dir.el (vc-dir-kill-line): New command.
116 (vc-dir-mode-map): Bind it to C-k.
117 (vc-dir-headers): Abbreviate the working dir.
118
119 * vc-git.el (vc-git-revision-table): Include remote branches.
120
1212010-10-31 Dan Nicolaescu <dann@ics.uci.edu>
122
123 New VC methods: vc-log-incoming and vc-log-outgoing.
124 * vc.el (vc-print-log-setup-buttons, vc-log-internal-common)
125 (vc-incoming-outgoing-internal, vc-log-incoming, vc-log-outgoing):
126 New functions.
127 (vc-print-log-internal): Just call vc-log-internal-common.
128 (vc-log-view-type): New permanent local variable.
129
130 * vc-hooks.el (vc-menu-map): Bind vc-log-incoming and vc-log-outgoing.
131
132 * vc-bzr.el (vc-bzr-log-view-mode): Use vc-log-view-type instead
133 of the dynamic bound vc-short-log.
134 (vc-bzr-log-incoming, vc-bzr-log-outgoing): New functions.
135
136 * vc-git.el (vc-git-log-outgoing): New function.
137 (vc-git-log-view-mode): Use vc-log-view-type instead
138 of the dynamic bound vc-short-log.
139
140 * vc-hg.el (vc-hg-log-view-mode): Use vc-log-view-type instead of
141 the dynamic bound vc-short-log. Highlight the tag.
142 (vc-hg-log-incoming, vc-hg-log-outgoing): New functions.
143 (vc-hg-outgoing, vc-hg-incoming, vc-hg-outgoing-mode):
144 (vc-hg-incoming-mode): Remove.
145 (vc-hg-extra-menu-map): Do not bind vc-hg-incoming and vc-hg-outgoing.
146
147 Fix default-directory for vc-root-diff.
148 * vc.el (vc-root-diff): Bind default-directory to the root
149 directory for the diff command.
150
1512010-10-31 Sam Steingold <sds@gnu.org>
152
153 * vc-hg.el (vc-hg-push, vc-hg-pull): Use `apply' when calling
154 `vc-hg-command' with a list of flags.
155
1562010-10-31 Glenn Morris <rgm@gnu.org>
157
158 * vc-bzr.el (vc-bzr-log-edit-mode): Add --fixes support to
159 log-edit-before-checkin-process.
160
161 * vc.el (vc-modify-change-comment): Pass MODE to vc-start-logentry.
162
163 * vc-bzr.el, vc-hg.el (log-edit-mode): Declare.
164
165 * vc-dispatcher.el (vc-start-logentry): Doc fix.
166 (log-view-process-buffer, log-edit-extra-flags): Declare.
167
1682010-10-31 Dan Nicolaescu <dann@ics.uci.edu>
169
170 Add special markup processing for commit logs.
171 * log-edit.el (log-edit): Add new argument MODE. Use that mode
172 when non-nil instead of the log-view-mode.
173
174 * vc.el (vc-default-log-edit-mode): New function.
175
176 * vc-dispatcher.el (vc-log-edit): Add a mode argument, pass it to
177 log-edit.
178
179 Support for shelving snapshots and for showing shelves.
180 * vc-bzr.el (vc-bzr-shelve-show, vc-bzr-shelve-show-at-point)
181 (vc-bzr-shelve-apply-and-keep-at-point, vc-bzr-shelve-snapshot):
182 New functions.
183 (vc-bzr-shelve-map, vc-bzr-shelve-menu-map)
184 (vc-bzr-extra-menu-map): Map them.
185
12010-10-30 Michael Albinus <michael.albinus@gmx.de> 1862010-10-30 Michael Albinus <michael.albinus@gmx.de>
2 187
3 * net/tramp.el (tramp-handle-insert-file-contents): For root, 188 * net/tramp.el (tramp-handle-insert-file-contents): For root,
diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el
index 27f8318f91c..907bf7d5b83 100644
--- a/lisp/diff-mode.el
+++ b/lisp/diff-mode.el
@@ -97,6 +97,9 @@ when editing big diffs)."
97 :options '(diff-delete-empty-files diff-make-unified) 97 :options '(diff-delete-empty-files diff-make-unified)
98 :group 'diff-mode) 98 :group 'diff-mode)
99 99
100(defvar diff-vc-backend nil
101 "The VC backend that created the current Diff buffer, if any.")
102
100(defvar diff-outline-regexp 103(defvar diff-outline-regexp
101 "\\([*+][*+][*+] [^0-9]\\|@@ ...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)") 104 "\\([*+][*+][*+] [^0-9]\\|@@ ...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)")
102 105
@@ -138,6 +141,7 @@ when editing big diffs)."
138 ;; Standard M-r is useful, so don't change M-r or M-R. 141 ;; Standard M-r is useful, so don't change M-r or M-R.
139 ;;("r" . diff-restrict-view) 142 ;;("r" . diff-restrict-view)
140 ;;("R" . diff-reverse-direction) 143 ;;("R" . diff-reverse-direction)
144 ("g" . revert-buffer)
141 ("q" . quit-window)) 145 ("q" . quit-window))
142 "Basic keymap for `diff-mode', bound to various prefix keys.") 146 "Basic keymap for `diff-mode', bound to various prefix keys.")
143 147
diff --git a/lisp/log-edit.el b/lisp/log-edit.el
index 10c6d480d23..0d3061ad2df 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,6 +189,7 @@ 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)
192
191(defvar log-edit-parent-buffer nil) 193(defvar log-edit-parent-buffer nil)
192 194
193;;; Originally taken from VC-Log mode 195;;; Originally taken from VC-Log mode
@@ -312,15 +314,59 @@ automatically."
312;;; Actual code 314;;; Actual code
313;;; 315;;;
314 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
315(defvar log-edit-font-lock-keywords 350(defvar log-edit-font-lock-keywords
316 '(("\\`\\(Summary:\\)\\(.*\\)" 351 ;; Copied/inspired by message-font-lock-keywords.
317 (1 font-lock-keyword-face) 352 `((log-edit-match-to-eoh
318 (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)))))
319 364
320;;;###autoload 365;;;###autoload
321(defun log-edit (callback &optional setup params buffer &rest ignore) 366(defun log-edit (callback &optional setup params buffer mode &rest ignore)
322 "Setup a buffer to enter a log message. 367 "Setup a buffer to enter a log message.
323\\<log-edit-mode-map>The buffer will be put in `log-edit-mode'. 368\\<log-edit-mode-map>The buffer will be put in mode MODE or `log-edit-mode'
369if MODE is nil.
324If SETUP is non-nil, the buffer is then erased and `log-edit-hook' is run. 370If SETUP is non-nil, the buffer is then erased and `log-edit-hook' is run.
325Mark and point will be set around the entire contents of the buffer so 371Mark and point will be set around the entire contents of the buffer so
326that it is easy to kill the contents of the buffer with \\[kill-region]. 372that it is easy to kill the contents of the buffer with \\[kill-region].
@@ -340,8 +386,13 @@ uses the current buffer."
340 (if buffer (pop-to-buffer buffer)) 386 (if buffer (pop-to-buffer buffer))
341 (when (and log-edit-setup-invert (not (eq setup 'force))) 387 (when (and log-edit-setup-invert (not (eq setup 'force)))
342 (setq setup (not setup))) 388 (setq setup (not setup)))
343 (when setup (erase-buffer)) 389 (when setup
344 (log-edit-mode) 390 (erase-buffer)
391 (insert "Summary: ")
392 (save-excursion (insert "\n\n")))
393 (if mode
394 (funcall mode)
395 (log-edit-mode))
345 (set (make-local-variable 'log-edit-callback) callback) 396 (set (make-local-variable 'log-edit-callback) callback)
346 (if (listp params) 397 (if (listp params)
347 (dolist (crt params) 398 (dolist (crt params)
@@ -367,7 +418,7 @@ commands (under C-x v for VC, for example).
367 418
368\\{log-edit-mode-map}" 419\\{log-edit-mode-map}"
369 (set (make-local-variable 'font-lock-defaults) 420 (set (make-local-variable 'font-lock-defaults)
370 '(log-edit-font-lock-keywords t)) 421 '(log-edit-font-lock-keywords t t))
371 (make-local-variable 'log-edit-comment-ring-index)) 422 (make-local-variable 'log-edit-comment-ring-index))
372 423
373(defun log-edit-hide-buf (&optional buf where) 424(defun log-edit-hide-buf (&optional buf where)
@@ -380,6 +431,17 @@ commands (under C-x v for VC, for example).
380 "Finish editing the log message and commit the files. 431 "Finish editing the log message and commit the files.
381If you want to abort the commit, simply delete the buffer." 432If you want to abort the commit, simply delete the buffer."
382 (interactive) 433 (interactive)
434 ;; Clean up empty headers.
435 (goto-char (point-min))
436 (while (looking-at (concat "^[a-z]*:" log-edit-header-contents-regexp))
437 (let ((beg (match-beginning 0)))
438 (goto-char (match-end 0))
439 (if (string-match "\\`[ \n\t]*\\'" (match-string 1))
440 (delete-region beg (point)))))
441 ;; Get rid of leading empty lines.
442 (goto-char (point-min))
443 (when (looking-at "\\([ \t]*\n\\)+")
444 (delete-region (match-beginning 0) (match-end 0)))
383 ;; Get rid of trailing empty lines 445 ;; Get rid of trailing empty lines
384 (goto-char (point-max)) 446 (goto-char (point-max))
385 (skip-syntax-backward " ") 447 (skip-syntax-backward " ")
@@ -437,12 +499,13 @@ If you want to abort the commit, simply delete the buffer."
437 "(Un)Indent the current buffer rigidly to `log-edit-common-indent'." 499 "(Un)Indent the current buffer rigidly to `log-edit-common-indent'."
438 (save-excursion 500 (save-excursion
439 (let ((common (point-max))) 501 (let ((common (point-max)))
440 (goto-char (point-min)) 502 (rfc822-goto-eoh)
441 (while (< (point) (point-max)) 503 (while (< (point) (point-max))
442 (if (not (looking-at "^[ \t]*$")) 504 (if (not (looking-at "^[ \t]*$"))
443 (setq common (min common (current-indentation)))) 505 (setq common (min common (current-indentation))))
444 (forward-line 1)) 506 (forward-line 1))
445 (indent-rigidly (point-min) (point-max) 507 (rfc822-goto-eoh)
508 (indent-rigidly (point) (point-max)
446 (- log-edit-common-indent common))))) 509 (- log-edit-common-indent common)))))
447 510
448(defun log-edit-show-diff () 511(defun log-edit-show-diff ()
@@ -508,6 +571,16 @@ can thus take some time."
508 (log-edit-comment-to-change-log))))) 571 (log-edit-comment-to-change-log)))))
509 572
510(defvar log-edit-changelog-use-first nil) 573(defvar log-edit-changelog-use-first nil)
574
575(defvar log-edit-rewrite-fixes nil
576 "Rule to rewrite bug numbers into Fixes: headers.
577The value should be of the form (REGEXP . REPLACEMENT)
578where REGEXP should match the expression referring to a bug number
579in the text, and REPLACEMENT is an expression to pass to `replace-match'
580to build the Fixes: header.")
581(put 'log-edit-rewrite-fixes 'safe-local-variable
582 (lambda (v) (and (stringp (car-safe v)) (stringp (cdr v)))))
583
511(defun log-edit-insert-changelog (&optional use-first) 584(defun log-edit-insert-changelog (&optional use-first)
512 "Insert a log message by looking at the ChangeLog. 585 "Insert a log message by looking at the ChangeLog.
513The idea is to write your ChangeLog entries first, and then use this 586The idea is to write your ChangeLog entries first, and then use this
@@ -525,18 +598,38 @@ If the optional prefix arg USE-FIRST is given (via \\[universal-argument]),
525or if the command is repeated a second time in a row, use the first log entry 598or if the command is repeated a second time in a row, use the first log entry
526regardless of user name or time." 599regardless of user name or time."
527 (interactive "P") 600 (interactive "P")
528 (let ((log-edit-changelog-use-first 601 (let ((eoh (save-excursion (rfc822-goto-eoh) (point))))
529 (or use-first (eq last-command 'log-edit-insert-changelog)))) 602 (when (<= (point) eoh)
530 (log-edit-insert-changelog-entries (log-edit-files))) 603 (goto-char eoh)
531 (log-edit-set-common-indentation) 604 (if (looking-at "\n") (forward-char 1))))
532 (goto-char (point-min)) 605 (let ((author
533 (when (and log-edit-strip-single-file-name (looking-at "\\*\\s-+")) 606 (let ((log-edit-changelog-use-first
534 (forward-line 1) 607 (or use-first (eq last-command 'log-edit-insert-changelog))))
535 (when (not (re-search-forward "^\\*\\s-+" nil t)) 608 (log-edit-insert-changelog-entries (log-edit-files)))))
536 (goto-char (point-min)) 609 (log-edit-set-common-indentation)
537 (skip-chars-forward "^():") 610 ;; Add an Author: field if appropriate.
538 (skip-chars-forward ": ") 611 (when author
539 (delete-region (point-min) (point))))) 612 (rfc822-goto-eoh)
613 (insert "Author: " author "\n" (if (looking-at "\n") "" "\n")))
614 ;; Add a Fixes: field if applicable.
615 (when (consp log-edit-rewrite-fixes)
616 (rfc822-goto-eoh)
617 (when (re-search-forward (car log-edit-rewrite-fixes) nil t)
618 (let ((start (match-beginning 0))
619 (end (match-end 0))
620 (fixes (match-substitute-replacement
621 (cdr log-edit-rewrite-fixes))))
622 (delete-region start end)
623 (rfc822-goto-eoh)
624 (insert "Fixes: " fixes "\n" (if (looking-at "\n") "" "\n")))))
625 (goto-char (point-min))
626 (when (and log-edit-strip-single-file-name (looking-at "\\*\\s-+"))
627 (forward-line 1)
628 (when (not (re-search-forward "^\\*\\s-+" nil t))
629 (goto-char (point-min))
630 (skip-chars-forward "^():")
631 (skip-chars-forward ": ")
632 (delete-region (point-min) (point))))))
540 633
541;;;; 634;;;;
542;;;; functions for getting commit message from ChangeLog a file... 635;;;; functions for getting commit message from ChangeLog a file...
@@ -602,6 +695,9 @@ for more details."
602 695
603(defvar user-full-name) 696(defvar user-full-name)
604(defvar user-mail-address) 697(defvar user-mail-address)
698
699(defvar log-edit-author) ;Dynamically scoped.
700
605(defun log-edit-changelog-ours-p () 701(defun log-edit-changelog-ours-p ()
606 "See if ChangeLog entry at point is for the current user, today. 702 "See if ChangeLog entry at point is for the current user, today.
607Return non-nil if it is." 703Return non-nil if it is."
@@ -616,14 +712,28 @@ Return non-nil if it is."
616 (functionp add-log-time-format) 712 (functionp add-log-time-format)
617 (funcall add-log-time-format)) 713 (funcall add-log-time-format))
618 (format-time-string "%Y-%m-%d")))) 714 (format-time-string "%Y-%m-%d"))))
619 (looking-at (if log-edit-changelog-use-first 715 (if (null log-edit-changelog-use-first)
620 "[^ \t]" 716 (looking-at (regexp-quote (format "%s %s <%s>" time name mail)))
621 (regexp-quote (format "%s %s <%s>" time name mail)))))) 717 ;; Check the author, to potentially add it as a "Author: " header.
718 (when (looking-at "[^ \t]")
719 (when (and (boundp 'log-edit-author)
720 (not (looking-at (format ".+ .+ <%s>"
721 (regexp-quote mail))))
722 (looking-at ".+ \\(.+ <.+>\\)"))
723 (let ((author (replace-regexp-in-string " " " "
724 (match-string 1))))
725 (unless (and log-edit-author
726 (string-match (regexp-quote author) log-edit-author))
727 (setq log-edit-author
728 (if log-edit-author
729 (concat log-edit-author ", " author)
730 author)))))
731 t))))
622 732
623(defun log-edit-changelog-entries (file) 733(defun log-edit-changelog-entries (file)
624 "Return the ChangeLog entries for FILE, and the ChangeLog they came from. 734 "Return the ChangeLog entries for FILE, and the ChangeLog they came from.
625The return value looks like this: 735The return value looks like this:
626 (LOGBUFFER (ENTRYSTART . ENTRYEND) ...) 736 (LOGBUFFER (ENTRYSTART ENTRYEND) ...)
627where LOGBUFFER is the name of the ChangeLog buffer, and each 737where LOGBUFFER is the name of the ChangeLog buffer, and each
628\(ENTRYSTART . ENTRYEND\) pair is a buffer region." 738\(ENTRYSTART . ENTRYEND\) pair is a buffer region."
629 (let ((changelog-file-name 739 (let ((changelog-file-name
@@ -681,34 +791,87 @@ where LOGBUFFER is the name of the ChangeLog buffer, and each
681 791
682 (cons (current-buffer) texts)))))))) 792 (cons (current-buffer) texts))))))))
683 793
684(defun log-edit-changelog-insert-entries (buffer regions) 794(defun log-edit-changelog-insert-entries (buffer beg end &rest files)
685 "Insert those regions in BUFFER specified in REGIONS. 795 "Insert the text from BUFFER between BEG and END.
686Sort REGIONS front-to-back first." 796Rename relative filenames in the ChangeLog entry as FILES."
687 (let ((regions (sort regions 'car-less-than-car)) 797 (let ((opoint (point))
688 (last)) 798 (log-name (buffer-file-name buffer))
689 (dolist (region regions) 799 (case-fold-search nil)
690 (when (and last (< last (car region))) (newline)) 800 bound)
691 (setq last (elt region 1)) 801 (insert-buffer-substring buffer beg end)
692 (apply 'insert-buffer-substring buffer region)))) 802 (setq bound (point-marker))
803 (when log-name
804 (dolist (f files)
805 (save-excursion
806 (goto-char opoint)
807 (when (re-search-forward
808 (concat "\\(^\\|[ \t]\\)\\("
809 (file-relative-name f (file-name-directory log-name))
810 "\\)[, :\n]")
811 bound t)
812 (replace-match f t t nil 2)))))
813 ;; Eliminate tabs at the beginning of the line.
814 (save-excursion
815 (goto-char opoint)
816 (while (re-search-forward "^\\(\t+\\)" bound t)
817 (replace-match "")))))
693 818
694(defun log-edit-insert-changelog-entries (files) 819(defun log-edit-insert-changelog-entries (files)
695 "Given a list of files FILES, insert the ChangeLog entries for them." 820 "Given a list of files FILES, insert the ChangeLog entries for them."
696 (let ((buffer-entries nil)) 821 (let ((log-entries nil)
697 822 (log-edit-author nil))
698 ;; Add each buffer to buffer-entries, and associate it with the list 823 ;; Note that any ChangeLog entry can apply to more than one file.
699 ;; of entries we want from that file. 824 ;; Here we construct a log-entries list with elements of the form
825 ;; ((LOGBUFFER ENTRYSTART ENTRYEND) FILE1 FILE2...)
700 (dolist (file files) 826 (dolist (file files)
701 (let* ((entries (log-edit-changelog-entries file)) 827 (let* ((entries (log-edit-changelog-entries file))
702 (pair (assq (car entries) buffer-entries))) 828 (buf (car entries))
703 (if pair 829 key entry)
704 (setcdr pair (cvs-union (cdr pair) (cdr entries))) 830 (dolist (region (cdr entries))
705 (push entries buffer-entries)))) 831 (setq key (cons buf region))
706 832 (if (setq entry (assoc key log-entries))
707 ;; Now map over each buffer in buffer-entries, sort the entries for 833 (setcdr entry (append (cdr entry) (list file)))
708 ;; each buffer, and extract them as strings. 834 (push (list key file) log-entries)))))
709 (dolist (buffer-entry buffer-entries) 835 ;; Now map over log-entries, and extract the strings.
710 (log-edit-changelog-insert-entries (car buffer-entry) (cdr buffer-entry)) 836 (dolist (log-entry (nreverse log-entries))
711 (when (cdr buffer-entry) (newline))))) 837 (apply 'log-edit-changelog-insert-entries
838 (append (car log-entry) (cdr log-entry)))
839 (insert "\n"))
840 log-edit-author))
841
842(defun log-edit-extract-headers (headers comment)
843 "Extract headers from COMMENT to form command line arguments.
844HEADERS should be an alist with elements of the form (HEADER . CMDARG)
845associating header names to the corresponding cmdline option name and the
846result is then a list of the form (MSG CMDARG1 HDRTEXT1 CMDARG2 HDRTEXT2...).
847where MSG is the remaining text from STRING.
848If \"Summary\" is not in HEADERS, then the \"Summary\" header is extracted
849anyway and put back as the first line of MSG."
850 (with-temp-buffer
851 (insert comment)
852 (rfc822-goto-eoh)
853 (narrow-to-region (point-min) (point))
854 (let ((case-fold-search t)
855 (summary ())
856 (res ()))
857 (dolist (header (if (assoc "Summary" headers) headers
858 (cons '("Summary" . t) headers)))
859 (goto-char (point-min))
860 (while (re-search-forward (concat "^" (car header)
861 ":" log-edit-header-contents-regexp)
862 nil t)
863 (if (eq t (cdr header))
864 (setq summary (match-string 1))
865 (push (match-string 1) res)
866 (push (or (cdr header) (car header)) res))
867 (replace-match "" t t)))
868 ;; Remove header separator if the header is empty.
869 (widen)
870 (goto-char (point-min))
871 (when (looking-at "\\([ \t]*\n\\)+")
872 (delete-region (match-beginning 0) (match-end 0)))
873 (if summary (insert summary "\n"))
874 (cons (buffer-string) res))))
712 875
713(provide 'log-edit) 876(provide 'log-edit)
714 877
diff --git a/lisp/log-view.el b/lisp/log-view.el
index 6fbe8429671..6d0e1332830 100644
--- a/lisp/log-view.el
+++ b/lisp/log-view.el
@@ -128,6 +128,7 @@
128(easy-mmode-defmap log-view-mode-map 128(easy-mmode-defmap log-view-mode-map
129 '(("z" . kill-this-buffer) 129 '(("z" . kill-this-buffer)
130 ("q" . quit-window) 130 ("q" . quit-window)
131 ("g" . revert-buffer)
131 ("m" . log-view-toggle-mark-entry) 132 ("m" . log-view-toggle-mark-entry)
132 ("e" . log-view-modify-change-comment) 133 ("e" . log-view-modify-change-comment)
133 ("d" . log-view-diff) 134 ("d" . log-view-diff)
diff --git a/lisp/vc-arch.el b/lisp/vc-arch.el
index b99c3de6875..d9002f9f7d5 100644
--- a/lisp/vc-arch.el
+++ b/lisp/vc-arch.el
@@ -254,8 +254,7 @@ Only the value `maybe' can be trusted :-(."
254 (buffer-substring (point-min) (1- (point-max))))))))) 254 (buffer-substring (point-min) (1- (point-max)))))))))
255 255
256(defun vc-arch-workfile-unchanged-p (file) 256(defun vc-arch-workfile-unchanged-p (file)
257 "Check if FILE is unchanged by diffing against the master version. 257 "Stub: arch workfiles are always considered to be in a changed state,"
258Return non-nil if FILE is unchanged."
259 nil) 258 nil)
260 259
261(defun vc-arch-state (file) 260(defun vc-arch-state (file)
diff --git a/lisp/vc-bzr.el b/lisp/vc-bzr.el
index 8396547bdcb..39736bb0377 100644
--- a/lisp/vc-bzr.el
+++ b/lisp/vc-bzr.el
@@ -451,11 +451,17 @@ 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(declare-function log-edit-extract-headers "log-edit" (headers string))
455
454(defun vc-bzr-checkin (files rev comment) 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 (vc-bzr-command "commit" nil 0 files "-m" comment)) 460 (apply 'vc-bzr-command "commit" nil 0
461 files (cons "-m" (log-edit-extract-headers '(("Author" . "--author")
462 ("Date" . "--commit-time")
463 ("Fixes" . "--fixes"))
464 comment))))
459 465
460(defun vc-bzr-find-revision (file rev buffer) 466(defun vc-bzr-find-revision (file rev buffer)
461 "Fetch revision REV of file FILE and put it into BUFFER." 467 "Fetch revision REV of file FILE and put it into BUFFER."
@@ -478,7 +484,6 @@ REV non-nil gets an error."
478(defvar log-view-font-lock-keywords) 484(defvar log-view-font-lock-keywords)
479(defvar log-view-current-tag-function) 485(defvar log-view-current-tag-function)
480(defvar log-view-per-file-logs) 486(defvar log-view-per-file-logs)
481(defvar vc-short-log)
482 487
483(define-derived-mode vc-bzr-log-view-mode log-view-mode "Bzr-Log-View" 488(define-derived-mode vc-bzr-log-view-mode log-view-mode "Bzr-Log-View"
484 (remove-hook 'log-view-mode-hook 'vc-bzr-log-view-mode) ;Deactivate the hack. 489 (remove-hook 'log-view-mode-hook 'vc-bzr-log-view-mode) ;Deactivate the hack.
@@ -486,13 +491,13 @@ REV non-nil gets an error."
486 (set (make-local-variable 'log-view-per-file-logs) nil) 491 (set (make-local-variable 'log-view-per-file-logs) nil)
487 (set (make-local-variable 'log-view-file-re) "\\`a\\`") 492 (set (make-local-variable 'log-view-file-re) "\\`a\\`")
488 (set (make-local-variable 'log-view-message-re) 493 (set (make-local-variable 'log-view-message-re)
489 (if vc-short-log 494 (if (eq vc-log-view-type 'short)
490 "^ *\\([0-9.]+\\): \\(.*?\\)[ \t]+\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)\\( \\[merge\\]\\)?" 495 "^ *\\([0-9.]+\\): \\(.*?\\)[ \t]+\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)\\( \\[merge\\]\\)?"
491 "^ *\\(?:revno: \\([0-9.]+\\)\\|merged: .+\\)")) 496 "^ *\\(?:revno: \\([0-9.]+\\)\\|merged: .+\\)"))
492 (set (make-local-variable 'log-view-font-lock-keywords) 497 (set (make-local-variable 'log-view-font-lock-keywords)
493 ;; log-view-font-lock-keywords is careful to use the buffer-local 498 ;; log-view-font-lock-keywords is careful to use the buffer-local
494 ;; value of log-view-message-re only since Emacs-23. 499 ;; value of log-view-message-re only since Emacs-23.
495 (if vc-short-log 500 (if (eq vc-log-view-type 'short)
496 (append `((,log-view-message-re 501 (append `((,log-view-message-re
497 (1 'log-view-message-face) 502 (1 'log-view-message-face)
498 (2 'change-log-name) 503 (2 'change-log-name)
@@ -526,6 +531,14 @@ REV non-nil gets an error."
526 (list vc-bzr-log-switches) 531 (list vc-bzr-log-switches)
527 vc-bzr-log-switches))))) 532 vc-bzr-log-switches)))))
528 533
534(defun vc-bzr-log-incoming (buffer remote-location)
535 (apply 'vc-bzr-command "missing" buffer 'async nil
536 (list "--theirs-only" (unless (string= remote-location "") remote-location))))
537
538(defun vc-bzr-log-outgoing (buffer remote-location)
539 (apply 'vc-bzr-command "missing" buffer 'async nil
540 (list "--mine-only" (unless (string= remote-location "") remote-location))))
541
529(defun vc-bzr-show-log-entry (revision) 542(defun vc-bzr-show-log-entry (revision)
530 "Find entry for patch name REVISION in bzr change log buffer." 543 "Find entry for patch name REVISION in bzr change log buffer."
531 (goto-char (point-min)) 544 (goto-char (point-min))
@@ -758,9 +771,11 @@ stream. Standard error output is discarded."
758 771
759 (define-key map [down-mouse-3] 'vc-bzr-shelve-menu) 772 (define-key map [down-mouse-3] 'vc-bzr-shelve-menu)
760 (define-key map "\C-k" 'vc-bzr-shelve-delete-at-point) 773 (define-key map "\C-k" 'vc-bzr-shelve-delete-at-point)
761 ;; (define-key map "=" 'vc-bzr-shelve-show-at-point) 774 (define-key map "=" 'vc-bzr-shelve-show-at-point)
762 ;; (define-key map "\C-m" 'vc-bzr-shelve-show-at-point) 775 (define-key map "\C-m" 'vc-bzr-shelve-show-at-point)
776 (define-key map "A" 'vc-bzr-shelve-apply-and-keep-at-point)
763 (define-key map "P" 'vc-bzr-shelve-apply-at-point) 777 (define-key map "P" 'vc-bzr-shelve-apply-at-point)
778 (define-key map "S" 'vc-bzr-shelve-snapshot)
764 map)) 779 map))
765 780
766(defvar vc-bzr-shelve-menu-map 781(defvar vc-bzr-shelve-menu-map
@@ -768,16 +783,22 @@ stream. Standard error output is discarded."
768 (define-key map [de] 783 (define-key map [de]
769 '(menu-item "Delete shelf" vc-bzr-shelve-delete-at-point 784 '(menu-item "Delete shelf" vc-bzr-shelve-delete-at-point
770 :help "Delete the current shelf")) 785 :help "Delete the current shelf"))
786 (define-key map [ap]
787 '(menu-item "Apply and keep shelf" vc-bzr-shelve-apply-and-keep-at-point
788 :help "Apply the current shelf and keep it"))
771 (define-key map [po] 789 (define-key map [po]
772 '(menu-item "Apply and remove shelf (pop)" vc-bzr-shelve-apply-at-point 790 '(menu-item "Apply and remove shelf (pop)" vc-bzr-shelve-apply-at-point
773 :help "Apply the current shelf and remove it")) 791 :help "Apply the current shelf and remove it"))
774 ;; (define-key map [sh] 792 (define-key map [sh]
775 ;; '(menu-item "Show shelve" vc-bzr-shelve-show-at-point 793 '(menu-item "Show shelve" vc-bzr-shelve-show-at-point
776 ;; :help "Show the contents of the current shelve")) 794 :help "Show the contents of the current shelve"))
777 map)) 795 map))
778 796
779(defvar vc-bzr-extra-menu-map 797(defvar vc-bzr-extra-menu-map
780 (let ((map (make-sparse-keymap))) 798 (let ((map (make-sparse-keymap)))
799 (define-key map [bzr-sn]
800 '(menu-item "Shelve a snapshot" vc-bzr-shelve-snapshot
801 :help "Shelve the current state of the tree and keep the current state"))
781 (define-key map [bzr-sh] 802 (define-key map [bzr-sh]
782 '(menu-item "Shelve..." vc-bzr-shelve 803 '(menu-item "Shelve..." vc-bzr-shelve
783 :help "Shelve changes")) 804 :help "Shelve changes"))
@@ -864,21 +885,38 @@ stream. Standard error output is discarded."
864 (vc-bzr-command "shelve" nil 0 nil "--all" "-m" name) 885 (vc-bzr-command "shelve" nil 0 nil "--all" "-m" name)
865 (vc-resynch-buffer root t t)))) 886 (vc-resynch-buffer root t t))))
866 887
867;; (defun vc-bzr-shelve-show (name) 888(defun vc-bzr-shelve-show (name)
868;; "Show the contents of shelve NAME." 889 "Show the contents of shelve NAME."
869;; (interactive "sShelve name: ") 890 (interactive "sShelve name: ")
870;; (vc-setup-buffer "*vc-bzr-shelve*") 891 (vc-setup-buffer "*vc-diff*")
871;; ;; FIXME: how can you show the contents of a shelf? 892 ;; FIXME: how can you show the contents of a shelf?
872;; (vc-bzr-command "shelve" "*vc-bzr-shelve*" 'async nil name) 893 (vc-bzr-command "unshelve" "*vc-diff*" 'async nil "--preview" name)
873;; (set-buffer "*vc-bzr-shelve*") 894 (set-buffer "*vc-diff*")
874;; (diff-mode) 895 (diff-mode)
875;; (setq buffer-read-only t) 896 (setq buffer-read-only t)
876;; (pop-to-buffer (current-buffer))) 897 (pop-to-buffer (current-buffer)))
877 898
878(defun vc-bzr-shelve-apply (name) 899(defun vc-bzr-shelve-apply (name)
879 "Apply shelve NAME and remove it afterwards." 900 "Apply shelve NAME and remove it afterwards."
880 (interactive "sApply (and remove) shelf: ") 901 (interactive "sApply (and remove) shelf: ")
881 (vc-bzr-command "unshelve" "*vc-bzr-shelve*" 0 nil "--apply" name) 902 (vc-bzr-command "unshelve" nil 0 nil "--apply" name)
903 (vc-resynch-buffer (vc-bzr-root default-directory) t t))
904
905(defun vc-bzr-shelve-apply-and-keep (name)
906 "Apply shelve NAME and keep it afterwards."
907 (interactive "sApply (and keep) shelf: ")
908 (vc-bzr-command "unshelve" nil 0 nil "--apply" "--keep" name)
909 (vc-resynch-buffer (vc-bzr-root default-directory) t t))
910
911(defun vc-bzr-shelve-snapshot ()
912 "Create a stash with the current tree state."
913 (interactive)
914 (vc-bzr-command "shelve" nil 0 nil "--all" "-m"
915 (let ((ct (current-time)))
916 (concat
917 (format-time-string "Snapshot on %Y-%m-%d" ct)
918 (format-time-string " at %H:%M" ct))))
919 (vc-bzr-command "unshelve" nil 0 nil "--apply" "--keep")
882 (vc-resynch-buffer (vc-bzr-root default-directory) t t)) 920 (vc-resynch-buffer (vc-bzr-root default-directory) t t))
883 921
884(defun vc-bzr-shelve-list () 922(defun vc-bzr-shelve-list ()
@@ -905,14 +943,18 @@ stream. Standard error output is discarded."
905 (vc-bzr-command "unshelve" nil 0 nil "--delete-only" shelve) 943 (vc-bzr-command "unshelve" nil 0 nil "--delete-only" shelve)
906 (vc-dir-refresh)))) 944 (vc-dir-refresh))))
907 945
908;; (defun vc-bzr-shelve-show-at-point () 946(defun vc-bzr-shelve-show-at-point ()
909;; (interactive) 947 (interactive)
910;; (vc-bzr-shelve-show (vc-bzr-shelve-get-at-point (point)))) 948 (vc-bzr-shelve-show (vc-bzr-shelve-get-at-point (point))))
911 949
912(defun vc-bzr-shelve-apply-at-point () 950(defun vc-bzr-shelve-apply-at-point ()
913 (interactive) 951 (interactive)
914 (vc-bzr-shelve-apply (vc-bzr-shelve-get-at-point (point)))) 952 (vc-bzr-shelve-apply (vc-bzr-shelve-get-at-point (point))))
915 953
954(defun vc-bzr-shelve-apply-and-keep-at-point ()
955 (interactive)
956 (vc-bzr-shelve-apply-and-keep (vc-bzr-shelve-get-at-point (point))))
957
916(defun vc-bzr-shelve-menu (e) 958(defun vc-bzr-shelve-menu (e)
917 (interactive "e") 959 (interactive "e")
918 (vc-dir-at-event e (popup-menu vc-bzr-shelve-menu-map e))) 960 (vc-dir-at-event e (popup-menu vc-bzr-shelve-menu-map e)))
@@ -930,6 +972,19 @@ stream. Standard error output is discarded."
930 (setq loglines (buffer-substring-no-properties start (point-max)))))) 972 (setq loglines (buffer-substring-no-properties start (point-max))))))
931 vc-bzr-revisions)) 973 vc-bzr-revisions))
932 974
975(defun vc-bzr-conflicted-files (dir)
976 (let ((default-directory (vc-bzr-root dir))
977 (files ()))
978 (with-temp-buffer
979 (vc-bzr-command "status" t 0 default-directory)
980 (goto-char (point-min))
981 (when (re-search-forward "^conflicts:\n" nil t)
982 (while (looking-at " \\(?:Text conflict in \\(.*\\)\\|.*\\)\n")
983 (if (match-end 1)
984 (push (expand-file-name (match-string 1)) files))
985 (goto-char (match-end 0)))))
986 files))
987
933;;; Revision completion 988;;; Revision completion
934 989
935(eval-and-compile 990(eval-and-compile
diff --git a/lisp/vc-dir.el b/lisp/vc-dir.el
index a32e5b35e08..96eb67085b6 100644
--- a/lisp/vc-dir.el
+++ b/lisp/vc-dir.el
@@ -188,9 +188,18 @@ See `run-hooks'."
188 (define-key map [diff] 188 (define-key map [diff]
189 '(menu-item "Compare with Base Version" vc-diff 189 '(menu-item "Compare with Base Version" vc-diff
190 :help "Compare file set with the base version")) 190 :help "Compare file set with the base version"))
191 (define-key map [logo]
192 '(menu-item "Show Outgoing Log" vc-log-outgoing
193 :help "Show a log of changes that will be sent with a push operation"))
194 (define-key map [logi]
195 '(menu-item "Show Incoming Log" vc-log-incoming
196 :help "Show a log of changes that will be received with a pull operation"))
191 (define-key map [log] 197 (define-key map [log]
192 '(menu-item "Show history" vc-print-log 198 '(menu-item "Show history" vc-print-log
193 :help "List the change log of the current file set in a window")) 199 :help "List the change log of the current file set in a window"))
200 (define-key map [rlog]
201 '(menu-item "Show Top of the Tree History " vc-print-root-log
202 :help "List the change log for the current tree in a window"))
194 ;; VC commands. 203 ;; VC commands.
195 (define-key map [sepvccmd] '("--")) 204 (define-key map [sepvccmd] '("--"))
196 (define-key map [update] 205 (define-key map [update]
@@ -263,6 +272,7 @@ See `run-hooks'."
263 (define-key map [mouse-2] 'vc-dir-toggle-mark) 272 (define-key map [mouse-2] 'vc-dir-toggle-mark)
264 (define-key map [follow-link] 'mouse-face) 273 (define-key map [follow-link] 'mouse-face)
265 (define-key map "x" 'vc-dir-hide-up-to-date) 274 (define-key map "x" 'vc-dir-hide-up-to-date)
275 (define-key map [?\C-k] 'vc-dir-kill-line)
266 (define-key map "S" 'vc-dir-search) ;; FIXME: Maybe use A like dired? 276 (define-key map "S" 'vc-dir-search) ;; FIXME: Maybe use A like dired?
267 (define-key map "Q" 'vc-dir-query-replace-regexp) 277 (define-key map "Q" 'vc-dir-query-replace-regexp)
268 (define-key map (kbd "M-s a C-s") 'vc-dir-isearch) 278 (define-key map (kbd "M-s a C-s") 'vc-dir-isearch)
@@ -963,7 +973,8 @@ specific headers."
963 (propertize "VC backend : " 'face 'font-lock-type-face) 973 (propertize "VC backend : " 'face 'font-lock-type-face)
964 (propertize (format "%s\n" backend) 'face 'font-lock-variable-name-face) 974 (propertize (format "%s\n" backend) 'face 'font-lock-variable-name-face)
965 (propertize "Working dir: " 'face 'font-lock-type-face) 975 (propertize "Working dir: " 'face 'font-lock-type-face)
966 (propertize (format "%s\n" dir) 'face 'font-lock-variable-name-face) 976 (propertize (format "%s\n" (abbreviate-file-name dir))
977 'face 'font-lock-variable-name-face)
967 ;; Then the backend specific ones. 978 ;; Then the backend specific ones.
968 (vc-call-backend backend 'dir-extra-headers dir) 979 (vc-call-backend backend 'dir-extra-headers dir)
969 "\n")) 980 "\n"))
@@ -1100,6 +1111,13 @@ outside of VC) and one wants to do some operation on it."
1100 (ewoc-delete vc-ewoc crt)) 1111 (ewoc-delete vc-ewoc crt))
1101 (setq crt prev))))) 1112 (setq crt prev)))))
1102 1113
1114(defun vc-dir-kill-line ()
1115 "Remove the current line from display."
1116 (interactive)
1117 (let ((crt (ewoc-locate vc-ewoc))
1118 (inhibit-read-only t))
1119 (ewoc-delete vc-ewoc crt)))
1120
1103(defun vc-dir-printer (fileentry) 1121(defun vc-dir-printer (fileentry)
1104 (vc-call-backend vc-dir-backend 'dir-printer fileentry)) 1122 (vc-call-backend vc-dir-backend 'dir-printer fileentry))
1105 1123
@@ -1169,7 +1187,8 @@ These are the commands available for use in the file status buffer:
1169 nil t nil nil))))) 1187 nil t nil nil)))))
1170 (unless backend 1188 (unless backend
1171 (setq backend (vc-responsible-backend dir))) 1189 (setq backend (vc-responsible-backend dir)))
1172 (pop-to-buffer (vc-dir-prepare-status-buffer "*vc-dir*" dir backend)) 1190 (let (pop-up-windows) ; based on cvs-examine; bug#6204
1191 (pop-to-buffer (vc-dir-prepare-status-buffer "*vc-dir*" dir backend)))
1173 (if (derived-mode-p 'vc-dir-mode) 1192 (if (derived-mode-p 'vc-dir-mode)
1174 (vc-dir-refresh) 1193 (vc-dir-refresh)
1175 ;; FIXME: find a better way to pass the backend to `vc-dir-mode'. 1194 ;; FIXME: find a better way to pass the backend to `vc-dir-mode'.
diff --git a/lisp/vc-dispatcher.el b/lisp/vc-dispatcher.el
index 0c3820bc529..d0648570bec 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
@@ -458,7 +457,7 @@ ARG and NO-CONFIRM are passed on to `revert-buffer'."
458(make-variable-buffer-local 'vc-mode-line-hook) 457(make-variable-buffer-local 'vc-mode-line-hook)
459(put 'vc-mode-line-hook 'permanent-local t) 458(put 'vc-mode-line-hook 'permanent-local t)
460 459
461(defun vc-resynch-window (file &optional keep noquery) 460(defun vc-resynch-window (file &optional keep noquery reset-vc-info)
462 "If FILE is in the current buffer, either revert or unvisit it. 461 "If FILE is in the current buffer, either revert or unvisit it.
463The choice between revert (to see expanded keywords) and unvisit 462The choice between revert (to see expanded keywords) and unvisit
464depends on KEEP. NOQUERY if non-nil inhibits confirmation for 463depends on KEEP. NOQUERY if non-nil inhibits confirmation for
@@ -469,6 +468,8 @@ editing!"
469 (and (string= buffer-file-name file) 468 (and (string= buffer-file-name file)
470 (if keep 469 (if keep
471 (when (file-exists-p file) 470 (when (file-exists-p file)
471 (when reset-vc-info
472 (vc-file-clearprops file))
472 (vc-revert-buffer-internal t noquery) 473 (vc-revert-buffer-internal t noquery)
473 474
474 ;; VC operations might toggle the read-only state. In 475 ;; VC operations might toggle the read-only state. In
@@ -490,24 +491,24 @@ editing!"
490(declare-function vc-dir-resynch-file "vc-dir" (&optional fname)) 491(declare-function vc-dir-resynch-file "vc-dir" (&optional fname))
491(declare-function vc-string-prefix-p "vc" (prefix string)) 492(declare-function vc-string-prefix-p "vc" (prefix string))
492 493
493(defun vc-resynch-buffers-in-directory (directory &optional keep noquery) 494(defun vc-resynch-buffers-in-directory (directory &optional keep noquery reset-vc-info)
494 "Resync all buffers that visit files in DIRECTORY." 495 "Resync all buffers that visit files in DIRECTORY."
495 (dolist (buffer (buffer-list)) 496 (dolist (buffer (buffer-list))
496 (let ((fname (buffer-file-name buffer))) 497 (let ((fname (buffer-file-name buffer)))
497 (when (and fname (vc-string-prefix-p directory fname)) 498 (when (and fname (vc-string-prefix-p directory fname))
498 (with-current-buffer buffer 499 (with-current-buffer buffer
499 (vc-resynch-buffer fname keep noquery)))))) 500 (vc-resynch-buffer fname keep noquery reset-vc-info))))))
500 501
501(defun vc-resynch-buffer (file &optional keep noquery) 502(defun vc-resynch-buffer (file &optional keep noquery reset-vc-info)
502 "If FILE is currently visited, resynch its buffer." 503 "If FILE is currently visited, resynch its buffer."
503 (if (string= buffer-file-name file) 504 (if (string= buffer-file-name file)
504 (vc-resynch-window file keep noquery) 505 (vc-resynch-window file keep noquery reset-vc-info)
505 (if (file-directory-p file) 506 (if (file-directory-p file)
506 (vc-resynch-buffers-in-directory file keep noquery) 507 (vc-resynch-buffers-in-directory file keep noquery reset-vc-info)
507 (let ((buffer (get-file-buffer file))) 508 (let ((buffer (get-file-buffer file)))
508 (when buffer 509 (when buffer
509 (with-current-buffer buffer 510 (with-current-buffer buffer
510 (vc-resynch-window file keep noquery)))))) 511 (vc-resynch-window file keep noquery reset-vc-info))))))
511 ;; Try to avoid unnecessary work, a *vc-dir* buffer is only present 512 ;; Try to avoid unnecessary work, a *vc-dir* buffer is only present
512 ;; if this is true. 513 ;; if this is true.
513 (when vc-dir-buffers 514 (when vc-dir-buffers
@@ -527,21 +528,26 @@ NOT-URGENT means it is ok to continue if the user says not to save."
527 528
528;; Set up key bindings for use while editing log messages 529;; Set up key bindings for use while editing log messages
529 530
530(defun vc-log-edit (fileset) 531(defun vc-log-edit (fileset mode)
531 "Set up `log-edit' for use on FILE." 532 "Set up `log-edit' for use on FILE."
532 (setq default-directory 533 (setq default-directory
533 (with-current-buffer vc-parent-buffer default-directory)) 534 (with-current-buffer vc-parent-buffer default-directory))
534 (log-edit 'vc-finish-logentry 535 (log-edit 'vc-finish-logentry
535 nil 536 nil
536 `((log-edit-listfun . (lambda () ',fileset)) 537 `((log-edit-listfun . (lambda ()
537 (log-edit-diff-function . (lambda () (vc-diff nil))))) 538 ;; FIXME: Should expand the list
539 ;; for directories.
540 (mapcar 'file-relative-name
541 ',fileset)))
542 (log-edit-diff-function . (lambda () (vc-diff nil))))
543 nil
544 mode)
538 (set (make-local-variable 'vc-log-fileset) fileset) 545 (set (make-local-variable 'vc-log-fileset) fileset)
539 (make-local-variable 'vc-log-extra)
540 (set-buffer-modified-p nil) 546 (set-buffer-modified-p nil)
541 (setq buffer-file-name nil)) 547 (setq buffer-file-name nil))
542 548
543(defun vc-start-logentry (files extra comment initial-contents msg logbuf action &optional after-hook) 549(defun vc-start-logentry (files comment initial-contents msg logbuf mode action &optional after-hook)
544 "Accept a comment for an operation on FILES with extra data EXTRA. 550 "Accept a comment for an operation on FILES.
545If COMMENT is nil, pop up a LOGBUF buffer, emit MSG, and set the 551If COMMENT is nil, pop up a LOGBUF buffer, emit MSG, and set the
546action on close to ACTION. If COMMENT is a string and 552action on close to ACTION. If COMMENT is a string and
547INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial 553INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial
@@ -549,8 +555,9 @@ contents of the log entry buffer. If COMMENT is a string and
549INITIAL-CONTENTS is nil, do action immediately as if the user had 555INITIAL-CONTENTS is nil, do action immediately as if the user had
550entered COMMENT. If COMMENT is t, also do action immediately with an 556entered COMMENT. If COMMENT is t, also do action immediately with an
551empty comment. Remember the file's buffer in `vc-parent-buffer' 557empty comment. Remember the file's buffer in `vc-parent-buffer'
552\(current one if no file). AFTER-HOOK specifies the local value 558\(current one if no file). Puts the log-entry buffer in major-mode
553for `vc-log-after-operation-hook'." 559MODE, defaulting to `log-edit-mode' if MODE is nil.
560AFTER-HOOK specifies the local value for `vc-log-after-operation-hook'."
554 (let ((parent 561 (let ((parent
555 (if (vc-dispatcher-browsing) 562 (if (vc-dispatcher-browsing)
556 ;; If we are called from a directory browser, the parent buffer is 563 ;; If we are called from a directory browser, the parent buffer is
@@ -565,12 +572,11 @@ for `vc-log-after-operation-hook'."
565 (set (make-local-variable 'vc-parent-buffer) parent) 572 (set (make-local-variable 'vc-parent-buffer) parent)
566 (set (make-local-variable 'vc-parent-buffer-name) 573 (set (make-local-variable 'vc-parent-buffer-name)
567 (concat " from " (buffer-name vc-parent-buffer))) 574 (concat " from " (buffer-name vc-parent-buffer)))
568 (vc-log-edit files) 575 (vc-log-edit files mode)
569 (make-local-variable 'vc-log-after-operation-hook) 576 (make-local-variable 'vc-log-after-operation-hook)
570 (when after-hook 577 (when after-hook
571 (setq vc-log-after-operation-hook after-hook)) 578 (setq vc-log-after-operation-hook after-hook))
572 (setq vc-log-operation action) 579 (setq vc-log-operation action)
573 (setq vc-log-extra extra)
574 (when comment 580 (when comment
575 (erase-buffer) 581 (erase-buffer)
576 (when (stringp comment) (insert comment))) 582 (when (stringp comment) (insert comment)))
@@ -579,7 +585,8 @@ for `vc-log-after-operation-hook'."
579 (vc-finish-logentry (eq comment t))))) 585 (vc-finish-logentry (eq comment t)))))
580 586
581(declare-function vc-dir-move-to-goal-column "vc-dir" ()) 587(declare-function vc-dir-move-to-goal-column "vc-dir" ())
582 588;; vc-finish-logentry is typically called from a log-edit buffer (see
589;; vc-start-logentry).
583(defun vc-finish-logentry (&optional nocomment) 590(defun vc-finish-logentry (&optional nocomment)
584 "Complete the operation implied by the current log entry. 591 "Complete the operation implied by the current log entry.
585Use the contents of the current buffer as a check-in or registration 592Use the contents of the current buffer as a check-in or registration
@@ -595,20 +602,21 @@ the buffer contents as a comment."
595 (or (vc-dispatcher-browsing) (vc-buffer-sync))) 602 (or (vc-dispatcher-browsing) (vc-buffer-sync)))
596 (unless vc-log-operation 603 (unless vc-log-operation
597 (error "No log operation is pending")) 604 (error "No log operation is pending"))
605
598 ;; save the parameters held in buffer-local variables 606 ;; save the parameters held in buffer-local variables
599 (let ((logbuf (current-buffer)) 607 (let ((logbuf (current-buffer))
600 (log-operation vc-log-operation) 608 (log-operation vc-log-operation)
609 ;; FIXME: When coming from VC-Dir, we should check that the
610 ;; set of selected files is still equal to vc-log-fileset,
611 ;; to avoid surprises.
601 (log-fileset vc-log-fileset) 612 (log-fileset vc-log-fileset)
602 (log-extra vc-log-extra)
603 (log-entry (buffer-string)) 613 (log-entry (buffer-string))
604 (after-hook vc-log-after-operation-hook) 614 (after-hook vc-log-after-operation-hook))
605 (tmp-vc-parent-buffer vc-parent-buffer))
606 (pop-to-buffer vc-parent-buffer) 615 (pop-to-buffer vc-parent-buffer)
607 ;; OK, do it to it 616 ;; OK, do it to it
608 (save-excursion 617 (save-excursion
609 (funcall log-operation 618 (funcall log-operation
610 log-fileset 619 log-fileset
611 log-extra
612 log-entry)) 620 log-entry))
613 ;; Remove checkin window (after the checkin so that if that fails 621 ;; Remove checkin window (after the checkin so that if that fails
614 ;; we don't zap the log buffer and the typing therein). 622 ;; we don't zap the log buffer and the typing therein).
@@ -617,9 +625,11 @@ the buffer contents as a comment."
617 (delete-windows-on logbuf (selected-frame)) 625 (delete-windows-on logbuf (selected-frame))
618 ;; Kill buffer and delete any other dedicated windows/frames. 626 ;; Kill buffer and delete any other dedicated windows/frames.
619 (kill-buffer logbuf)) 627 (kill-buffer logbuf))
620 (logbuf (pop-to-buffer logbuf) 628 (logbuf
621 (bury-buffer) 629 (with-selected-window (or (get-buffer-window logbuf 0)
622 (pop-to-buffer tmp-vc-parent-buffer))) 630 (selected-window))
631 (with-current-buffer logbuf
632 (bury-buffer)))))
623 ;; Now make sure we see the expanded headers 633 ;; Now make sure we see the expanded headers
624 (when log-fileset 634 (when log-fileset
625 (mapc 635 (mapc
diff --git a/lisp/vc-git.el b/lisp/vc-git.el
index 24062a0f4f6..4383e609adb 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
@@ -171,7 +171,14 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
171 171
172(defun vc-git-state (file) 172(defun vc-git-state (file)
173 "Git-specific version of `vc-state'." 173 "Git-specific version of `vc-state'."
174 ;; FIXME: This can't set 'ignored yet 174 ;; FIXME: This can't set 'ignored or 'conflict yet
175 ;; The 'ignored state could be detected with `git ls-files -i -o
176 ;; --exclude-standard` It also can't set 'needs-update or
177 ;; 'needs-merge. The rough equivalent would be that upstream branch
178 ;; for current branch is in fast-forward state i.e. current branch
179 ;; is direct ancestor of corresponding upstream branch, and the file
180 ;; was modified upstream. But we can't check that without a network
181 ;; operation.
175 (if (not (vc-git-registered file)) 182 (if (not (vc-git-registered file))
176 'unregistered 183 'unregistered
177 (vc-git--call nil "add" "--refresh" "--" (file-relative-name file)) 184 (vc-git--call nil "add" "--refresh" "--" (file-relative-name file))
@@ -541,11 +548,16 @@ or an empty string if none."
541(defun vc-git-unregister (file) 548(defun vc-git-unregister (file)
542 (vc-git-command nil 0 file "rm" "-f" "--cached" "--")) 549 (vc-git-command nil 0 file "rm" "-f" "--cached" "--"))
543 550
551(declare-function log-edit-extract-headers "log-edit" (headers string))
544 552
545(defun vc-git-checkin (files rev comment) 553(defun vc-git-checkin (files rev comment)
546 (let ((coding-system-for-write git-commits-coding-system)) 554 (let ((coding-system-for-write vc-git-commits-coding-system))
547 (vc-git-command nil 0 files "commit" 555 (apply 'vc-git-command nil 0 files
548 "-m" comment "--only" "--"))) 556 (nconc (list "commit" "-m")
557 (log-edit-extract-headers '(("Author" . "--author")
558 ("Date" . "--date"))
559 comment)
560 (list "--only" "--")))))
549 561
550(defun vc-git-find-revision (file rev buffer) 562(defun vc-git-find-revision (file rev buffer)
551 (let* (process-file-side-effects 563 (let* (process-file-side-effects
@@ -580,7 +592,7 @@ or an empty string if none."
580 "Get change log associated with FILES. 592 "Get change log associated with FILES.
581Note that using SHORTLOG requires at least Git version 1.5.6, 593Note that using SHORTLOG requires at least Git version 1.5.6,
582for the --graph option." 594for the --graph option."
583 (let ((coding-system-for-read git-commits-coding-system)) 595 (let ((coding-system-for-read vc-git-commits-coding-system))
584 ;; `vc-do-command' creates the buffer, but we need it before running 596 ;; `vc-do-command' creates the buffer, but we need it before running
585 ;; the command. 597 ;; the command.
586 (vc-setup-buffer buffer) 598 (vc-setup-buffer buffer)
@@ -600,25 +612,46 @@ for the --graph option."
600 (when start-revision (list start-revision)) 612 (when start-revision (list start-revision))
601 '("--"))))))) 613 '("--")))))))
602 614
615(defun vc-git-log-outgoing (buffer remote-location)
616 (interactive)
617 (vc-git-command
618 buffer 0 nil
619 "log"
620 "--no-color" "--graph" "--decorate" "--date=short"
621 "--pretty=tformat:%d%h %ad %s" "--abbrev-commit"
622 (concat (if (string= remote-location "")
623 "@{upstream}"
624 remote-location)
625 "..HEAD")))
626
627(defun vc-git-log-incoming (buffer remote-location)
628 (interactive)
629 (vc-git-command nil 0 nil "fetch")
630 (vc-git-command
631 buffer 0 nil
632 "log"
633 "--no-color" "--graph" "--decorate" "--date=short"
634 "--pretty=tformat:%d%h %ad %s" "--abbrev-commit"
635 (concat "HEAD.." (if (string= remote-location "")
636 "@{upstream}"
637 remote-location))))
638
603(defvar log-view-message-re) 639(defvar log-view-message-re)
604(defvar log-view-file-re) 640(defvar log-view-file-re)
605(defvar log-view-font-lock-keywords) 641(defvar log-view-font-lock-keywords)
606(defvar log-view-per-file-logs) 642(defvar log-view-per-file-logs)
607 643
608;; Dynamically bound.
609(defvar vc-short-log)
610
611(define-derived-mode vc-git-log-view-mode log-view-mode "Git-Log-View" 644(define-derived-mode vc-git-log-view-mode log-view-mode "Git-Log-View"
612 (require 'add-log) ;; We need the faces add-log. 645 (require 'add-log) ;; We need the faces add-log.
613 ;; Don't have file markers, so use impossible regexp. 646 ;; Don't have file markers, so use impossible regexp.
614 (set (make-local-variable 'log-view-file-re) "\\`a\\`") 647 (set (make-local-variable 'log-view-file-re) "\\`a\\`")
615 (set (make-local-variable 'log-view-per-file-logs) nil) 648 (set (make-local-variable 'log-view-per-file-logs) nil)
616 (set (make-local-variable 'log-view-message-re) 649 (set (make-local-variable 'log-view-message-re)
617 (if vc-short-log 650 (if (not (eq vc-log-view-type 'long))
618 "^\\(?:[*/\\| ]+ \\)?\\(?: ([^)]+)\\)?\\([0-9a-z]+\\) \\([-a-z0-9]+\\) \\(.*\\)" 651 "^\\(?:[*/\\| ]+ \\)?\\(?: ([^)]+)\\)?\\([0-9a-z]+\\) \\([-a-z0-9]+\\) \\(.*\\)"
619 "^commit *\\([0-9a-z]+\\)")) 652 "^commit *\\([0-9a-z]+\\)"))
620 (set (make-local-variable 'log-view-font-lock-keywords) 653 (set (make-local-variable 'log-view-font-lock-keywords)
621 (if vc-short-log 654 (if (not (eq vc-log-view-type 'long))
622 '( 655 '(
623 ;; Same as log-view-message-re, except that we don't 656 ;; Same as log-view-message-re, except that we don't
624 ;; want the shy group for the tag name. 657 ;; want the shy group for the tag name.
@@ -681,7 +714,8 @@ or BRANCH^ (where \"^\" can be repeated)."
681 (with-temp-buffer 714 (with-temp-buffer
682 (vc-git-command t nil nil "for-each-ref" "--format=%(refname)") 715 (vc-git-command t nil nil "for-each-ref" "--format=%(refname)")
683 (goto-char (point-min)) 716 (goto-char (point-min))
684 (while (re-search-forward "^refs/\\(heads\\|tags\\)/\\(.*\\)$" nil t) 717 (while (re-search-forward "^refs/\\(heads\\|tags\\|remotes\\)/\\(.*\\)$"
718 nil t)
685 (push (match-string 2) table))) 719 (push (match-string 2) table)))
686 table)) 720 table))
687 721
diff --git a/lisp/vc-hg.el b/lisp/vc-hg.el
index b29f229e26f..2339f887a34 100644
--- a/lisp/vc-hg.el
+++ b/lisp/vc-hg.el
@@ -256,33 +256,33 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
256 (with-current-buffer 256 (with-current-buffer
257 buffer 257 buffer
258 (apply 'vc-hg-command buffer 0 files "log" 258 (apply 'vc-hg-command buffer 0 files "log"
259 (append 259 (nconc
260 (when start-revision (list (format "-r%s:" start-revision))) 260 (when start-revision (list (format "-r%s:" start-revision)))
261 (when limit (list "-l" (format "%s" limit))) 261 (when limit (list "-l" (format "%s" limit)))
262 (when shortlog '("--style" "compact")) 262 (when shortlog (list "--style" "compact"))
263 vc-hg-log-switches))))) 263 vc-hg-log-switches)))))
264 264
265(defvar log-view-message-re) 265(defvar log-view-message-re)
266(defvar log-view-file-re) 266(defvar log-view-file-re)
267(defvar log-view-font-lock-keywords) 267(defvar log-view-font-lock-keywords)
268(defvar log-view-per-file-logs) 268(defvar log-view-per-file-logs)
269(defvar vc-short-log)
270 269
271(define-derived-mode vc-hg-log-view-mode log-view-mode "Hg-Log-View" 270(define-derived-mode vc-hg-log-view-mode log-view-mode "Hg-Log-View"
272 (require 'add-log) ;; we need the add-log faces 271 (require 'add-log) ;; we need the add-log faces
273 (set (make-local-variable 'log-view-file-re) "\\`a\\`") 272 (set (make-local-variable 'log-view-file-re) "\\`a\\`")
274 (set (make-local-variable 'log-view-per-file-logs) nil) 273 (set (make-local-variable 'log-view-per-file-logs) nil)
275 (set (make-local-variable 'log-view-message-re) 274 (set (make-local-variable 'log-view-message-re)
276 (if vc-short-log 275 (if (eq vc-log-view-type 'short)
277 "^\\([0-9]+\\)\\(?:\\[.*\\]\\)? +\\([0-9a-z]\\{12\\}\\) +\\(\\(?:[0-9]+\\)-\\(?:[0-9]+\\)-\\(?:[0-9]+\\) \\(?:[0-9]+\\):\\(?:[0-9]+\\) \\(?:[-+0-9]+\\)\\) +\\(.*\\)$" 276 "^\\([0-9]+\\)\\(\\[.*\\]\\)? +\\([0-9a-z]\\{12\\}\\) +\\(\\(?:[0-9]+\\)-\\(?:[0-9]+\\)-\\(?:[0-9]+\\) \\(?:[0-9]+\\):\\(?:[0-9]+\\) \\(?:[-+0-9]+\\)\\) +\\(.*\\)$"
278 "^changeset:[ \t]*\\([0-9]+\\):\\(.+\\)")) 277 "^changeset:[ \t]*\\([0-9]+\\):\\(.+\\)"))
279 (set (make-local-variable 'log-view-font-lock-keywords) 278 (set (make-local-variable 'log-view-font-lock-keywords)
280 (if vc-short-log 279 (if (eq vc-log-view-type 'short)
281 (append `((,log-view-message-re 280 (append `((,log-view-message-re
282 (1 'log-view-message-face) 281 (1 'log-view-message-face)
283 (2 'log-view-message-face) 282 (2 'highlight nil lax)
284 (3 'change-log-date) 283 (3 'log-view-message-face)
285 (4 'change-log-name)))) 284 (4 'change-log-date)
285 (5 'change-log-name))))
286 (append 286 (append
287 log-view-font-lock-keywords 287 log-view-font-lock-keywords
288 '( 288 '(
@@ -298,7 +298,8 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
298 ("^user:[ \t]+\\([A-Za-z0-9_.+-]+\\(?:@[A-Za-z0-9_.-]+\\)?\\)" 298 ("^user:[ \t]+\\([A-Za-z0-9_.+-]+\\(?:@[A-Za-z0-9_.-]+\\)?\\)"
299 (1 'change-log-email)) 299 (1 'change-log-email))
300 ("^date: \\(.+\\)" (1 'change-log-date)) 300 ("^date: \\(.+\\)" (1 'change-log-date))
301 ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))) 301 ("^tag: +\\([^ ]+\\)$" (1 'highlight))
302 ("^summary:[ \t]+\\(.+\\)" (1 'log-view-message)))))))
302 303
303(defun vc-hg-diff (files &optional oldvers newvers buffer) 304(defun vc-hg-diff (files &optional oldvers newvers buffer)
304 "Get a difference report using hg between two revisions of FILES." 305 "Get a difference report using hg between two revisions of FILES."
@@ -423,10 +424,16 @@ COMMENT is ignored."
423;; "Unregister FILE from hg." 424;; "Unregister FILE from hg."
424;; (vc-hg-command nil nil file "remove")) 425;; (vc-hg-command nil nil file "remove"))
425 426
427(declare-function log-edit-extract-headers "log-edit" (headers string))
428
426(defun vc-hg-checkin (files rev comment) 429(defun vc-hg-checkin (files rev comment)
427 "Hg-specific version of `vc-backend-checkin'. 430 "Hg-specific version of `vc-backend-checkin'.
428REV is ignored." 431REV is ignored."
429 (vc-hg-command nil 0 files "commit" "-m" comment)) 432 (apply 'vc-hg-command nil 0 files
433 (nconc (list "commit" "-m")
434 (log-edit-extract-headers '(("Author" . "--user")
435 ("Date" . "--date"))
436 comment))))
430 437
431(defun vc-hg-find-revision (file rev buffer) 438(defun vc-hg-find-revision (file rev buffer)
432 (let ((coding-system-for-read 'binary) 439 (let ((coding-system-for-read 'binary)
@@ -460,8 +467,6 @@ REV is the revision to check out into WORKFILE."
460 467
461(defvar vc-hg-extra-menu-map 468(defvar vc-hg-extra-menu-map
462 (let ((map (make-sparse-keymap))) 469 (let ((map (make-sparse-keymap)))
463 (define-key map [incoming] '(menu-item "Show incoming" vc-hg-incoming))
464 (define-key map [outgoing] '(menu-item "Show outgoing" vc-hg-outgoing))
465 map)) 470 map))
466 471
467(defun vc-hg-extra-menu () vc-hg-extra-menu-map) 472(defun vc-hg-extra-menu () vc-hg-extra-menu-map)
@@ -470,14 +475,6 @@ REV is the revision to check out into WORKFILE."
470 475
471(defvar log-view-vc-backend) 476(defvar log-view-vc-backend)
472 477
473(define-derived-mode vc-hg-outgoing-mode vc-hg-log-view-mode "Hg-Outgoing"
474 "Mode for browsing Hg outgoing changes."
475 (set (make-local-variable 'log-view-vc-backend) 'Hg))
476
477(define-derived-mode vc-hg-incoming-mode vc-hg-log-view-mode "Hg-Incoming"
478 "Mode for browsing Hg incoming changes."
479 (set (make-local-variable 'log-view-vc-backend) 'Hg))
480
481(defstruct (vc-hg-extra-fileinfo 478(defstruct (vc-hg-extra-fileinfo
482 (:copier nil) 479 (:copier nil)
483 (:constructor vc-hg-create-extra-fileinfo (rename-state extra-name)) 480 (:constructor vc-hg-create-extra-fileinfo (rename-state extra-name))
@@ -583,33 +580,13 @@ REV is the revision to check out into WORKFILE."
583 ;; (vc-hg-dir-extra-header "Global id : " "id" "-i") 580 ;; (vc-hg-dir-extra-header "Global id : " "id" "-i")
584 ))) 581 )))
585 582
586;; FIXME: this adds another top level menu, instead figure out how to 583(defun vc-hg-log-incoming (buffer remote-location)
587;; replace the Log-View menu. 584 (vc-hg-command buffer 1 nil "incoming" "-n" (unless (string= remote-location "")
588(easy-menu-define log-view-mode-menu vc-hg-outgoing-mode-map 585 remote-location)))
589 "Hg-outgoing Display Menu"
590 `("Hg-outgoing"
591 ["Push selected" vc-hg-push]))
592
593(easy-menu-define log-view-mode-menu vc-hg-incoming-mode-map
594 "Hg-incoming Display Menu"
595 `("Hg-incoming"
596 ["Pull selected" vc-hg-pull]))
597 586
598(defun vc-hg-outgoing () 587(defun vc-hg-log-outgoing (buffer remote-location)
599 (interactive) 588 (vc-hg-command buffer 1 nil "outgoing" "-n" (unless (string= remote-location "")
600 (let ((bname "*Hg outgoing*") 589 remote-location)))
601 (vc-short-log nil))
602 (vc-hg-command bname 1 nil "outgoing" "-n")
603 (pop-to-buffer bname)
604 (vc-hg-outgoing-mode)))
605
606(defun vc-hg-incoming ()
607 (interactive)
608 (let ((bname "*Hg incoming*")
609 (vc-short-log nil))
610 (vc-hg-command bname 0 nil "incoming" "-n")
611 (pop-to-buffer bname)
612 (vc-hg-incoming-mode)))
613 590
614(declare-function log-view-get-marked "log-view" ()) 591(declare-function log-view-get-marked "log-view" ())
615 592
@@ -618,22 +595,22 @@ REV is the revision to check out into WORKFILE."
618 (interactive) 595 (interactive)
619 (let ((marked-list (log-view-get-marked))) 596 (let ((marked-list (log-view-get-marked)))
620 (if marked-list 597 (if marked-list
621 (vc-hg-command 598 (apply #'vc-hg-command
622 nil 0 nil 599 nil 0 nil
623 (cons "push" 600 "push"
624 (apply 'nconc 601 (apply 'nconc
625 (mapcar (lambda (arg) (list "-r" arg)) marked-list)))) 602 (mapcar (lambda (arg) (list "-r" arg)) marked-list)))
626 (error "No log entries selected for push")))) 603 (error "No log entries selected for push"))))
627 604
628(defun vc-hg-pull () 605(defun vc-hg-pull ()
629 (interactive) 606 (interactive)
630 (let ((marked-list (log-view-get-marked))) 607 (let ((marked-list (log-view-get-marked)))
631 (if marked-list 608 (if marked-list
632 (vc-hg-command 609 (apply #'vc-hg-command
633 nil 0 nil 610 nil 0 nil
634 (cons "pull" 611 "pull"
635 (apply 'nconc 612 (apply 'nconc
636 (mapcar (lambda (arg) (list "-r" arg)) marked-list)))) 613 (mapcar (lambda (arg) (list "-r" arg)) marked-list)))
637 (error "No log entries selected for pull")))) 614 (error "No log entries selected for pull"))))
638 615
639;;; Internal functions 616;;; Internal functions
diff --git a/lisp/vc-hooks.el b/lisp/vc-hooks.el
index 70369df06fe..a0cf06fbe12 100644
--- a/lisp/vc-hooks.el
+++ b/lisp/vc-hooks.el
@@ -403,7 +403,7 @@ If the argument is a list, the files must all have the same back end."
403 403
404 404
405(defun vc-backend-subdirectory-name (file) 405(defun vc-backend-subdirectory-name (file)
406 "Return where the master and lock FILEs for the current directory are kept." 406 "Return where the repository for the current directory is kept."
407 (symbol-name (vc-backend file))) 407 (symbol-name (vc-backend file)))
408 408
409(defun vc-name (file) 409(defun vc-name (file)
@@ -471,13 +471,13 @@ For registered files, the value returned is one of:
471 USER The current version of the working file is locked by 471 USER The current version of the working file is locked by
472 some other USER (a string). 472 some other USER (a string).
473 473
474 'needs-update The file has not been edited by the user, but there is 474 'needs-update The file has not been edited by the user, but there is
475 a more recent version on the current branch stored 475 a more recent version on the current branch stored
476 in the master file. 476 in the repository.
477 477
478 'needs-merge The file has been edited by the user, and there is also 478 'needs-merge The file has been edited by the user, and there is also
479 a more recent version on the current branch stored in 479 a more recent version on the current branch stored in
480 the master file. This state can only occur if locking 480 the repository. This state can only occur if locking
481 is not used for the file. 481 is not used for the file.
482 482
483 'unlocked-changes The working version of the file is not locked, 483 'unlocked-changes The working version of the file is not locked,
@@ -556,7 +556,7 @@ and does not employ any heuristic at all."
556 unchanged)))) 556 unchanged))))
557 557
558(defun vc-default-workfile-unchanged-p (backend file) 558(defun vc-default-workfile-unchanged-p (backend file)
559 "Check if FILE is unchanged by diffing against the master version. 559 "Check if FILE is unchanged by diffing against the repository version.
560Return non-nil if FILE is unchanged." 560Return non-nil if FILE is unchanged."
561 (zerop (condition-case err 561 (zerop (condition-case err
562 ;; If the implementation supports it, let the output 562 ;; If the implementation supports it, let the output
@@ -818,6 +818,9 @@ Format:
818 \"BACKEND-REV\" if the file is up-to-date 818 \"BACKEND-REV\" if the file is up-to-date
819 \"BACKEND:REV\" if the file is edited (or locked by the calling user) 819 \"BACKEND:REV\" if the file is edited (or locked by the calling user)
820 \"BACKEND:LOCKER:REV\" if the file is locked by somebody else 820 \"BACKEND:LOCKER:REV\" if the file is locked by somebody else
821 \"BACKEND@REV\" if the file was locally added
822 \"BACKEND!REV\" if the file contains conflicts or was removed
823 \"BACKEND?REV\" if the file is under VC, but is missing
821 824
822This function assumes that the file is registered." 825This function assumes that the file is registered."
823 (let* ((backend-name (symbol-name backend)) 826 (let* ((backend-name (symbol-name backend))
@@ -947,6 +950,8 @@ current, and kill the buffer that visits the link."
947 (define-key map "i" 'vc-register) 950 (define-key map "i" 'vc-register)
948 (define-key map "l" 'vc-print-log) 951 (define-key map "l" 'vc-print-log)
949 (define-key map "L" 'vc-print-root-log) 952 (define-key map "L" 'vc-print-root-log)
953 (define-key map "I" 'vc-log-incoming)
954 (define-key map "O" 'vc-log-outgoing)
950 (define-key map "m" 'vc-merge) 955 (define-key map "m" 'vc-merge)
951 (define-key map "r" 'vc-retrieve-tag) 956 (define-key map "r" 'vc-retrieve-tag)
952 (define-key map "s" 'vc-create-tag) 957 (define-key map "s" 'vc-create-tag)
@@ -989,6 +994,12 @@ current, and kill the buffer that visits the link."
989 (define-key map [vc-update-change-log] 994 (define-key map [vc-update-change-log]
990 `(menu-item ,(purecopy "Update ChangeLog") vc-update-change-log 995 `(menu-item ,(purecopy "Update ChangeLog") vc-update-change-log
991 :help ,(purecopy "Find change log file and add entries from recent version control logs"))) 996 :help ,(purecopy "Find change log file and add entries from recent version control logs")))
997 (define-key map [vc-log-out]
998 `(menu-item ,(purecopy "Show Outgoing Log") vc-log-outgoing
999 :help ,(purecopy "Show a log of changes that will be sent with a push operation")))
1000 (define-key map [vc-log-in]
1001 `(menu-item ,(purecopy "Show Incoming Log") vc-log-incoming
1002 :help ,(purecopy "Show a log of changes that will be received with a pull operation")))
992 (define-key map [vc-print-log] 1003 (define-key map [vc-print-log]
993 `(menu-item ,(purecopy "Show History") vc-print-log 1004 `(menu-item ,(purecopy "Show History") vc-print-log
994 :help ,(purecopy "List the change log of the current file set in a window"))) 1005 :help ,(purecopy "List the change log of the current file set in a window")))
diff --git a/lisp/vc-mtn.el b/lisp/vc-mtn.el
index db9f5eb3333..aa90fdabc87 100644
--- a/lisp/vc-mtn.el
+++ b/lisp/vc-mtn.el
@@ -172,8 +172,14 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
172(defun vc-mtn-responsible-p (file) (vc-mtn-root file)) 172(defun vc-mtn-responsible-p (file) (vc-mtn-root file))
173(defun vc-mtn-could-register (file) (vc-mtn-root file)) 173(defun vc-mtn-could-register (file) (vc-mtn-root file))
174 174
175(declare-function log-edit-extract-headers "log-edit" (headers string))
176
175(defun vc-mtn-checkin (files rev comment) 177(defun vc-mtn-checkin (files rev comment)
176 (vc-mtn-command nil 0 files "commit" "-m" comment)) 178 (apply 'vc-mtn-command nil 0 files
179 (nconc (list "commit" "-m")
180 (log-edit-extract-headers '(("Author" . "--author")
181 ("Date" . "--date"))
182 comment))))
177 183
178(defun vc-mtn-find-revision (file rev buffer) 184(defun vc-mtn-find-revision (file rev buffer)
179 (vc-mtn-command buffer 0 file "cat" "-r" rev)) 185 (vc-mtn-command buffer 0 file "cat" "-r" rev))
diff --git a/lisp/vc.el b/lisp/vc.el
index a7d4ec66391..7ba24821ef6 100644
--- a/lisp/vc.el
+++ b/lisp/vc.el
@@ -63,11 +63,18 @@
63;; although you might prefer to use C-c C-a (i.e. `log-edit-insert-changelog') 63;; although you might prefer to use C-c C-a (i.e. `log-edit-insert-changelog')
64;; from the commit buffer instead or to set `log-edit-setup-invert'. 64;; from the commit buffer instead or to set `log-edit-setup-invert'.
65;; 65;;
66;; The vc code maintains some internal state in order to reduce expensive 66;; When using SCCS, RCS, CVS: be careful not to do repo surgery, or
67;; version-control operations to a minimum. Some names are only computed 67;; operations like registrations and deletions and renames, outside VC
68;; once. If you perform version control operations with the backend while 68;; while VC is running. The support for these systems was designed
69;; vc's back is turned, or move/rename master files while vc is running, 69;; when disks were much slower, and the code maintains a lot of
70;; vc may get seriously confused. Don't do these things! 70;; internal state in order to reduce expensive operations to a
71;; minimum. Thus, if you mess with the repo while VC's back is turned,
72;; VC may get seriously confused.
73;;
74;; When using Subversion or a later system, anything you do outside VC
75;; *through the VCS tools* should safely interlock with VC
76;; operations. Under these VC does little state caching, because local
77;; operations are assumed to be fast. The dividing line is
71;; 78;;
72;; ADDING SUPPORT FOR OTHER BACKENDS 79;; ADDING SUPPORT FOR OTHER BACKENDS
73;; 80;;
@@ -196,7 +203,7 @@
196;; 203;;
197;; Return non-nil if FILE is unchanged from the working revision. 204;; Return non-nil if FILE is unchanged from the working revision.
198;; This function should do a brief comparison of FILE's contents 205;; This function should do a brief comparison of FILE's contents
199;; with those of the repository master of the working revision. If 206;; with those of the repository copy of the working revision. If
200;; the backend does not have such a brief-comparison feature, the 207;; the backend does not have such a brief-comparison feature, the
201;; default implementation of this function can be used, which 208;; default implementation of this function can be used, which
202;; delegates to a full vc-BACKEND-diff. (Note that vc-BACKEND-diff 209;; delegates to a full vc-BACKEND-diff. (Note that vc-BACKEND-diff
@@ -263,12 +270,10 @@
263;; 270;;
264;; * checkin (files rev comment) 271;; * checkin (files rev comment)
265;; 272;;
266;; 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
267;; should become the new revision number (not all backends do 274;; and should be ignored. COMMENT is used as a check-in comment.
268;; anything with it). COMMENT is used as a check-in comment. The 275;; The implementation should pass the value of vc-checkin-switches to
269;; implementation should pass the value of vc-checkin-switches to 276;; the backend command.
270;; the backend command. (Note: in older versions of VC, this
271;; command took a single file argument and not a list.)
272;; 277;;
273;; * find-revision (file rev buffer) 278;; * find-revision (file rev buffer)
274;; 279;;
@@ -344,6 +349,16 @@
344;; revision. At this point START-REVISION is only required to work 349;; revision. At this point START-REVISION is only required to work
345;; in conjunction with LIMIT = 1. 350;; in conjunction with LIMIT = 1.
346;; 351;;
352;; * log-outgoing (backend remote-location)
353;;
354;; Insert in BUFFER the revision log for the changes that will be
355;; sent when performing a push operation to REMOTE-LOCATION.
356;;
357;; * log-incoming (backend remote-location)
358;;
359;; Insert in BUFFER the revision log for the changes that will be
360;; received when performing a pull operation from REMOTE-LOCATION.
361;;
347;; - log-view-mode () 362;; - log-view-mode ()
348;; 363;;
349;; Mode to use for the output of print-log. This defaults to 364;; Mode to use for the output of print-log. This defaults to
@@ -477,6 +492,12 @@
477;; Return the revision number that follows REV for FILE, or nil if no such 492;; Return the revision number that follows REV for FILE, or nil if no such
478;; revision exists. 493;; revision exists.
479;; 494;;
495;; - log-edit-mode ()
496;;
497;; Turn on the mode used for editing the check in log. This
498;; defaults to `log-edit-mode'. If changed, it should use a mode
499;; derived from`log-edit-mode'.
500;;
480;; - check-headers () 501;; - check-headers ()
481;; 502;;
482;; Return non-nil if the current buffer contains any version headers. 503;; Return non-nil if the current buffer contains any version headers.
@@ -524,6 +545,12 @@
524;; makes it possible to provide menu entries for functionality that 545;; makes it possible to provide menu entries for functionality that
525;; 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
526;; 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?
527 554
528;;; Todo: 555;;; Todo:
529 556
@@ -553,9 +580,6 @@
553;; display the branch name in the mode-line. Replace 580;; display the branch name in the mode-line. Replace
554;; vc-cvs-sticky-tag with that. 581;; vc-cvs-sticky-tag with that.
555;; 582;;
556;; - vc-create-tag and vc-retrieve-tag should update the
557;; buffers that might be visiting the affected files.
558;;
559;;;; Internal cleanups: 583;;;; Internal cleanups:
560;; 584;;
561;; - backends that care about vc-stay-local should try to take it into 585;; - backends that care about vc-stay-local should try to take it into
@@ -746,7 +770,7 @@ See `run-hooks'."
746 "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n#endif /* lint */\n")) 770 "\n#ifndef lint\nstatic char vcid[] = \"\%s\";\n#endif /* lint */\n"))
747 "Associate static header string templates with file types. 771 "Associate static header string templates with file types.
748A \%s in the template is replaced with the first string associated with 772A \%s in the template is replaced with the first string associated with
749the file's version control type in `vc-header-alist'." 773the file's version control type in `vc-BACKEND-header'."
750 :type '(repeat (cons :format "%v" 774 :type '(repeat (cons :format "%v"
751 (regexp :tag "File Type") 775 (regexp :tag "File Type")
752 (string :tag "Header String"))) 776 (string :tag "Header String")))
@@ -767,7 +791,7 @@ is sensitive to blank lines."
767(defcustom vc-checkout-carefully (= (user-uid) 0) 791(defcustom vc-checkout-carefully (= (user-uid) 0)
768 "Non-nil means be extra-careful in checkout. 792 "Non-nil means be extra-careful in checkout.
769Verify that the file really is not locked 793Verify that the file really is not locked
770and that its contents match what the master file says." 794and that its contents match what the repository version says."
771 :type 'boolean 795 :type 'boolean
772 :group 'vc) 796 :group 'vc)
773(make-obsolete-variable 'vc-checkout-carefully 797(make-obsolete-variable 'vc-checkout-carefully
@@ -889,6 +913,16 @@ Within directories, only files already under version control are noticed."
889 (nreverse flattened))) 913 (nreverse flattened)))
890 914
891(defvar vc-dir-backend) 915(defvar vc-dir-backend)
916(defvar log-view-vc-backend)
917(defvar diff-vc-backend)
918
919(defun vc-deduce-backend ()
920 (cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend)
921 ((derived-mode-p 'log-view-mode) log-view-vc-backend)
922 ((derived-mode-p 'diff-mode) diff-vc-backend)
923 ((derived-mode-p 'dired-mode)
924 (vc-responsible-backend default-directory))
925 (vc-mode (vc-backend buffer-file-name))))
892 926
893(declare-function vc-dir-current-file "vc-dir" ()) 927(declare-function vc-dir-current-file "vc-dir" ())
894(declare-function vc-dir-deduce-fileset "vc-dir" (&optional state-model-only-files)) 928(declare-function vc-dir-deduce-fileset "vc-dir" (&optional state-model-only-files))
@@ -1030,8 +1064,7 @@ merge in the changes into your working copy."
1030 (state (nth 3 vc-fileset)) 1064 (state (nth 3 vc-fileset))
1031 ;; The backend should check that the checkout-model is consistent 1065 ;; The backend should check that the checkout-model is consistent
1032 ;; among all the `files'. 1066 ;; among all the `files'.
1033 (model (nth 4 vc-fileset)) 1067 (model (nth 4 vc-fileset)))
1034 revision)
1035 1068
1036 ;; Do the right thing 1069 ;; Do the right thing
1037 (cond 1070 (cond
@@ -1046,11 +1079,13 @@ merge in the changes into your working copy."
1046 (cond 1079 (cond
1047 (verbose 1080 (verbose
1048 ;; go to a different revision 1081 ;; go to a different revision
1049 (setq revision (read-string "Branch, revision, or backend to move to: ")) 1082 (let* ((revision
1050 (let ((revision-downcase (downcase revision))) 1083 (read-string "Branch, revision, or backend to move to: "))
1084 (revision-downcase (downcase revision)))
1051 (if (member 1085 (if (member
1052 revision-downcase 1086 revision-downcase
1053 (mapcar (lambda (arg) (downcase (symbol-name arg))) vc-handled-backends)) 1087 (mapcar (lambda (arg) (downcase (symbol-name arg)))
1088 vc-handled-backends))
1054 (let ((vsym (intern-soft revision-downcase))) 1089 (let ((vsym (intern-soft revision-downcase)))
1055 (dolist (file files) (vc-transfer-file file vsym))) 1090 (dolist (file files) (vc-transfer-file file vsym)))
1056 (dolist (file files) 1091 (dolist (file files)
@@ -1095,8 +1130,8 @@ merge in the changes into your working copy."
1095 (message "No files remain to be committed") 1130 (message "No files remain to be committed")
1096 (if (not verbose) 1131 (if (not verbose)
1097 (vc-checkin ready-for-commit backend) 1132 (vc-checkin ready-for-commit backend)
1098 (setq revision (read-string "New revision or backend: ")) 1133 (let* ((revision (read-string "New revision or backend: "))
1099 (let ((revision-downcase (downcase revision))) 1134 (revision-downcase (downcase revision)))
1100 (if (member 1135 (if (member
1101 revision-downcase 1136 revision-downcase
1102 (mapcar (lambda (arg) (downcase (symbol-name arg))) 1137 (mapcar (lambda (arg) (downcase (symbol-name arg)))
@@ -1341,7 +1376,7 @@ Type \\[vc-next-action] to check in changes.")
1341(defun vc-checkin (files backend &optional rev comment initial-contents) 1376(defun vc-checkin (files backend &optional rev comment initial-contents)
1342 "Check in FILES. 1377 "Check in FILES.
1343The optional argument REV may be a string specifying the new revision 1378The optional argument REV may be a string specifying the new revision
1344level (if nil increment the current level). COMMENT is a comment 1379level (strongly deprecated). COMMENT is a comment
1345string; if omitted, a buffer is popped up to accept a comment. If 1380string; if omitted, a buffer is popped up to accept a comment. If
1346INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents 1381INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents
1347of the log entry buffer. 1382of the log entry buffer.
@@ -1355,26 +1390,30 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
1355 (lexical-let 1390 (lexical-let
1356 ((backend backend)) 1391 ((backend backend))
1357 (vc-start-logentry 1392 (vc-start-logentry
1358 files rev comment initial-contents 1393 files comment initial-contents
1359 "Enter a change comment." 1394 "Enter a change comment."
1360 "*VC-log*" 1395 "*VC-log*"
1361 (lambda (files rev comment) 1396 (lambda ()
1362 (message "Checking in %s..." (vc-delistify files)) 1397 (vc-call-backend backend 'log-edit-mode))
1363 ;; "This log message intentionally left almost blank". 1398 (lexical-let ((rev rev))
1364 ;; RCS 5.7 gripes about white-space-only comments too. 1399 (lambda (files comment)
1365 (or (and comment (string-match "[^\t\n ]" comment)) 1400 (message "Checking in %s..." (vc-delistify files))
1366 (setq comment "*** empty log message ***")) 1401 ;; "This log message intentionally left almost blank".
1367 (with-vc-properties 1402 ;; RCS 5.7 gripes about white-space-only comments too.
1368 files 1403 (or (and comment (string-match "[^\t\n ]" comment))
1369 ;; We used to change buffers to get local value of vc-checkin-switches, 1404 (setq comment "*** empty log message ***"))
1370 ;; but 'the' local buffer is not a well-defined concept for filesets. 1405 (with-vc-properties
1371 (progn 1406 files
1372 (vc-call-backend backend 'checkin files rev comment) 1407 ;; We used to change buffers to get local value of
1373 (mapc 'vc-delete-automatic-version-backups files)) 1408 ;; vc-checkin-switches, but 'the' local buffer is
1374 `((vc-state . up-to-date) 1409 ;; not a well-defined concept for filesets.
1375 (vc-checkout-time . ,(nth 5 (file-attributes file))) 1410 (progn
1376 (vc-working-revision . nil))) 1411 (vc-call-backend backend 'checkin files rev comment)
1377 (message "Checking in %s...done" (vc-delistify files))) 1412 (mapc 'vc-delete-automatic-version-backups files))
1413 `((vc-state . up-to-date)
1414 (vc-checkout-time . ,(nth 5 (file-attributes file)))
1415 (vc-working-revision . nil)))
1416 (message "Checking in %s...done" (vc-delistify files))))
1378 'vc-checkin-hook))) 1417 'vc-checkin-hook)))
1379 1418
1380;;; Additional entry points for examining version histories 1419;;; Additional entry points for examining version histories
@@ -1514,7 +1553,7 @@ returns t if the buffer had changes, nil otherwise."
1514 (not (string= (vc-working-revision file) "0"))) 1553 (not (string= (vc-working-revision file) "0")))
1515 (push file filtered) 1554 (push file filtered)
1516 ;; This file is added but not yet committed; 1555 ;; This file is added but not yet committed;
1517 ;; there is no master file to diff against. 1556 ;; there is no repository version to diff against.
1518 (if (or rev1 rev2) 1557 (if (or rev1 rev2)
1519 (error "No revisions of %s exist" file) 1558 (error "No revisions of %s exist" file)
1520 ;; We regard this as "changed". 1559 ;; We regard this as "changed".
@@ -1533,6 +1572,10 @@ returns t if the buffer had changes, nil otherwise."
1533 (message "%s" (cdr messages)) 1572 (message "%s" (cdr messages))
1534 nil) 1573 nil)
1535 (diff-mode) 1574 (diff-mode)
1575 (set (make-local-variable 'diff-vc-backend) (car vc-fileset))
1576 (set (make-local-variable 'revert-buffer-function)
1577 `(lambda (ignore-auto noconfirm)
1578 (vc-diff-internal ,async ',vc-fileset ,rev1 ,rev2 ,verbose)))
1536 ;; Make the *vc-diff* buffer read only, the diff-mode key 1579 ;; Make the *vc-diff* buffer read only, the diff-mode key
1537 ;; bindings are nicer for read only buffers. pcl-cvs does the 1580 ;; bindings are nicer for read only buffers. pcl-cvs does the
1538 ;; same thing. 1581 ;; same thing.
@@ -1639,18 +1682,20 @@ saving the buffer."
1639 ;; that's not what we want here, we want the diff for the VC root dir. 1682 ;; that's not what we want here, we want the diff for the VC root dir.
1640 (call-interactively 'vc-version-diff) 1683 (call-interactively 'vc-version-diff)
1641 (when buffer-file-name (vc-buffer-sync not-urgent)) 1684 (when buffer-file-name (vc-buffer-sync not-urgent))
1642 (let ((backend 1685 (let ((backend (vc-deduce-backend))
1643 (cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend)
1644 ((derived-mode-p 'dired-mode) (vc-responsible-backend default-directory))
1645 (vc-mode (vc-backend buffer-file-name))))
1646 rootdir working-revision) 1686 rootdir working-revision)
1647 (unless backend 1687 (unless backend
1648 (error "Buffer is not version controlled")) 1688 (error "Buffer is not version controlled"))
1649 (setq rootdir (vc-call-backend backend 'root default-directory)) 1689 (setq rootdir (vc-call-backend backend 'root default-directory))
1650 (setq working-revision (vc-working-revision rootdir)) 1690 (setq working-revision (vc-working-revision rootdir))
1651 (vc-diff-internal 1691 ;; VC diff for the root directory produces output that is
1652 t (list backend (list rootdir) working-revision) nil nil 1692 ;; relative to it. Bind default-directory to the root directory
1653 (called-interactively-p 'interactive))))) 1693 ;; here, this way the *vc-diff* buffer is setup correctly, so
1694 ;; relative file names work.
1695 (let ((default-directory rootdir))
1696 (vc-diff-internal
1697 t (list backend (list rootdir) working-revision) nil nil
1698 (called-interactively-p 'interactive))))))
1654 1699
1655;;;###autoload 1700;;;###autoload
1656(defun vc-revision-other-window (rev) 1701(defun vc-revision-other-window (rev)
@@ -1754,17 +1799,19 @@ The headers are reset to their non-expanded form."
1754 1799
1755(defun vc-modify-change-comment (files rev oldcomment) 1800(defun vc-modify-change-comment (files rev oldcomment)
1756 "Edit the comment associated with the given files and revision." 1801 "Edit the comment associated with the given files and revision."
1757 (vc-start-logentry 1802 ;; Less of a kluge than it looks like; log-view mode only passes
1758 files rev oldcomment t 1803 ;; this function a singleton list. Arguments left in this form in
1759 "Enter a replacement change comment." 1804 ;; case the more general operation ever becomes meaningful.
1760 "*VC-log*" 1805 (let ((backend (vc-responsible-backend (car files))))
1761 (lambda (files rev comment) 1806 (vc-start-logentry
1762 (vc-call-backend 1807 files oldcomment t
1763 ;; Less of a kluge than it looks like; log-view mode only passes 1808 "Enter a replacement change comment."
1764 ;; this function a singleton list. Arguments left in this form in 1809 "*VC-log*"
1765 ;; case the more general operation ever becomes meaningful. 1810 (lambda () (vc-call-backend backend 'log-edit-mode))
1766 (vc-responsible-backend (car files)) 1811 (lexical-let ((rev rev))
1767 'modify-change-comment files rev comment)))) 1812 (lambda (files comment)
1813 (vc-call-backend backend
1814 'modify-change-comment files rev comment))))))
1768 1815
1769;;;###autoload 1816;;;###autoload
1770(defun vc-merge () 1817(defun vc-merge ()
@@ -1825,6 +1872,31 @@ See Info node `Merging'."
1825;;;###autoload 1872;;;###autoload
1826(defalias 'vc-resolve-conflicts 'smerge-ediff) 1873(defalias 'vc-resolve-conflicts 'smerge-ediff)
1827 1874
1875;; TODO: This is OK but maybe we could integrate it better.
1876;; E.g. it could be run semi-automatically (via a prompt?) when saving a file
1877;; that was conflicted (i.e. upon mark-resolved).
1878;; FIXME: should we add an "other-window" version? Or maybe we should
1879;; hook it inside find-file so it automatically works for
1880;; find-file-other-window as well. E.g. find-file could use a new
1881;; `default-next-file' variable for its default file (M-n), and
1882;; we could then set it upon mark-resolve, so C-x C-s C-x C-f M-n would
1883;; automatically offer the next conflicted file.
1884(defun vc-find-conflicted-file ()
1885 "Visit the next conflicted file in the current project."
1886 (interactive)
1887 (let* ((backend (or (if buffer-file-name (vc-backend buffer-file-name))
1888 (vc-responsible-backend default-directory)
1889 (error "No VC backend")))
1890 (files (vc-call-backend backend
1891 'conflicted-files default-directory)))
1892 ;; Don't try and visit the current file.
1893 (if (equal (car files) buffer-file-name) (pop files))
1894 (if (null files)
1895 (message "No more conflicted files")
1896 (find-file (pop files))
1897 (message "%s more conflicted files after this one"
1898 (if files (length files) "No")))))
1899
1828;; Named-configuration entry points 1900;; Named-configuration entry points
1829 1901
1830(defun vc-tag-precondition (dir) 1902(defun vc-tag-precondition (dir)
@@ -1850,13 +1922,22 @@ the named configuration. If the prefix argument BRANCHP is
1850given, the tag is made as a new branch and the files are 1922given, the tag is made as a new branch and the files are
1851checked out in that new branch." 1923checked out in that new branch."
1852 (interactive 1924 (interactive
1853 (list (read-file-name "Directory: " default-directory default-directory t) 1925 (let ((granularity
1854 (read-string "New tag name: ") 1926 (vc-call-backend (vc-responsible-backend default-directory)
1855 current-prefix-arg)) 1927 'revision-granularity)))
1928 (list
1929 (if (eq granularity 'repository)
1930 ;; For VC's that do not work at file level, it's pointless
1931 ;; to ask for a directory, branches are created at repository level.
1932 default-directory
1933 (read-file-name "Directory: " default-directory default-directory t))
1934 (read-string (if current-prefix-arg "New branch name: " "New tag name: "))
1935 current-prefix-arg)))
1856 (message "Making %s... " (if branchp "branch" "tag")) 1936 (message "Making %s... " (if branchp "branch" "tag"))
1857 (when (file-directory-p dir) (setq dir (file-name-as-directory dir))) 1937 (when (file-directory-p dir) (setq dir (file-name-as-directory dir)))
1858 (vc-call-backend (vc-responsible-backend dir) 1938 (vc-call-backend (vc-responsible-backend dir)
1859 'create-tag dir name branchp) 1939 'create-tag dir name branchp)
1940 (vc-resynch-buffer dir t t t)
1860 (message "Making %s... done" (if branchp "branch" "tag"))) 1941 (message "Making %s... done" (if branchp "branch" "tag")))
1861 1942
1862;;;###autoload 1943;;;###autoload
@@ -1867,8 +1948,16 @@ If locking is used for the files in DIR, then there must not be any
1867locked files at or below DIR (but if NAME is empty, locked files are 1948locked files at or below DIR (but if NAME is empty, locked files are
1868allowed and simply skipped)." 1949allowed and simply skipped)."
1869 (interactive 1950 (interactive
1870 (list (read-file-name "Directory: " default-directory default-directory t) 1951 (let ((granularity
1871 (read-string "Tag name to retrieve (default latest revisions): "))) 1952 (vc-call-backend (vc-responsible-backend default-directory)
1953 'revision-granularity)))
1954 (list
1955 (if (eq granularity 'repository)
1956 ;; For VC's that do not work at file level, it's pointless
1957 ;; to ask for a directory, branches are created at repository level.
1958 default-directory
1959 (read-file-name "Directory: " default-directory default-directory t))
1960 (read-string "Tag name to retrieve (default latest revisions): "))))
1872 (let ((update (yes-or-no-p "Update any affected buffers? ")) 1961 (let ((update (yes-or-no-p "Update any affected buffers? "))
1873 (msg (if (or (not name) (string= name "")) 1962 (msg (if (or (not name) (string= name ""))
1874 (format "Updating %s... " (abbreviate-file-name dir)) 1963 (format "Updating %s... " (abbreviate-file-name dir))
@@ -1877,8 +1966,10 @@ allowed and simply skipped)."
1877 (message "%s" msg) 1966 (message "%s" msg)
1878 (vc-call-backend (vc-responsible-backend dir) 1967 (vc-call-backend (vc-responsible-backend dir)
1879 'retrieve-tag dir name update) 1968 'retrieve-tag dir name update)
1969 (vc-resynch-buffer dir t t t)
1880 (message "%s" (concat msg "done")))) 1970 (message "%s" (concat msg "done"))))
1881 1971
1972
1882;; Miscellaneous other entry points 1973;; Miscellaneous other entry points
1883 1974
1884;; FIXME: this should be a defcustom 1975;; FIXME: this should be a defcustom
@@ -1891,9 +1982,31 @@ If it contains `directory' then if the fileset contains a directory show a short
1891If it contains `file' then show short logs for files. 1982If it contains `file' then show short logs for files.
1892Not all VC backends support short logs!") 1983Not all VC backends support short logs!")
1893 1984
1894(defvar log-view-vc-backend)
1895(defvar log-view-vc-fileset) 1985(defvar log-view-vc-fileset)
1896 1986
1987(defun vc-print-log-setup-buttons (working-revision is-start-revision limit pl-return)
1988 (when (and limit (not (eq 'limit-unsupported pl-return))
1989 (not is-start-revision))
1990 (goto-char (point-max))
1991 (lexical-let ((working-revision working-revision)
1992 (limit limit))
1993 (widget-create 'push-button
1994 :notify (lambda (&rest ignore)
1995 (vc-print-log-internal
1996 log-view-vc-backend log-view-vc-fileset
1997 working-revision nil (* 2 limit)))
1998 :help-echo "Show the log again, and double the number of log entries shown"
1999 "Show 2X entries")
2000 (widget-insert " ")
2001 (widget-create 'push-button
2002 :notify (lambda (&rest ignore)
2003 (vc-print-log-internal
2004 log-view-vc-backend log-view-vc-fileset
2005 working-revision nil nil))
2006 :help-echo "Show the log again, showing all entries"
2007 "Show unlimited entries"))
2008 (widget-setup)))
2009
1897(defun vc-print-log-internal (backend files working-revision 2010(defun vc-print-log-internal (backend files working-revision
1898 &optional is-start-revision limit) 2011 &optional is-start-revision limit)
1899 ;; Don't switch to the output buffer before running the command, 2012 ;; Don't switch to the output buffer before running the command,
@@ -1901,6 +2014,8 @@ Not all VC backends support short logs!")
1901 ;; buffer can be accessed by the command. 2014 ;; buffer can be accessed by the command.
1902 (let ((dir-present nil) 2015 (let ((dir-present nil)
1903 (vc-short-log nil) 2016 (vc-short-log nil)
2017 (buffer-name "*vc-change-log*")
2018 type
1904 pl-return) 2019 pl-return)
1905 (dolist (file files) 2020 (dolist (file files)
1906 (when (file-directory-p file) 2021 (when (file-directory-p file)
@@ -1909,44 +2024,78 @@ Not all VC backends support short logs!")
1909 (not (null (if dir-present 2024 (not (null (if dir-present
1910 (memq 'directory vc-log-short-style) 2025 (memq 'directory vc-log-short-style)
1911 (memq 'file vc-log-short-style))))) 2026 (memq 'file vc-log-short-style)))))
1912 2027 (setq type (if vc-short-log 'short 'long))
1913 (setq pl-return (vc-call-backend 2028 (lexical-let
1914 backend 'print-log files "*vc-change-log*" 2029 ((working-revision working-revision)
1915 vc-short-log (when is-start-revision working-revision) limit)) 2030 (backend backend)
1916 (pop-to-buffer "*vc-change-log*") 2031 (limit limit)
2032 (shortlog vc-short-log)
2033 (files files)
2034 (is-start-revision is-start-revision))
2035 (vc-log-internal-common
2036 backend buffer-name files type
2037 (lambda (bk buf type-arg files-arg)
2038 (vc-call-backend bk 'print-log files-arg buf
2039 shortlog (when is-start-revision working-revision) limit))
2040 (lambda (bk files-arg ret)
2041 (vc-print-log-setup-buttons working-revision
2042 is-start-revision limit ret))
2043 (lambda (bk)
2044 (vc-call-backend bk 'show-log-entry working-revision))
2045 (lambda (ignore-auto noconfirm)
2046 (vc-print-log-internal backend files working-revision is-start-revision limit))))))
2047
2048(defvar vc-log-view-type nil
2049 "Set this to differentiate the different types of logs.")
2050(put 'vc-log-view-type 'permanent-local t)
2051
2052(defun vc-log-internal-common (backend
2053 buffer-name
2054 files
2055 type
2056 backend-func
2057 setup-buttons-func
2058 goto-location-func
2059 rev-buff-func)
2060 (let (retval)
2061 (with-current-buffer (get-buffer-create buffer-name)
2062 (set (make-local-variable 'vc-log-view-type) type))
2063 (setq retval (funcall backend-func backend buffer-name type files))
2064 (pop-to-buffer buffer-name)
1917 (let ((inhibit-read-only t)) 2065 (let ((inhibit-read-only t))
1918 ;; log-view-mode used to be called with inhibit-read-only bound 2066 ;; log-view-mode used to be called with inhibit-read-only bound
1919 ;; to t, so let's keep doing it, just in case. 2067 ;; to t, so let's keep doing it, just in case.
1920 (vc-call-backend backend 'log-view-mode)) 2068 (vc-call-backend backend 'log-view-mode)
1921 (set (make-local-variable 'log-view-vc-backend) backend) 2069 (set (make-local-variable 'log-view-vc-backend) backend)
1922 (set (make-local-variable 'log-view-vc-fileset) files) 2070 (set (make-local-variable 'log-view-vc-fileset) files)
1923 2071 (set (make-local-variable 'revert-buffer-function)
2072 rev-buff-func))
1924 (vc-exec-after 2073 (vc-exec-after
1925 `(let ((inhibit-read-only t)) 2074 `(let ((inhibit-read-only t))
1926 (when (and ,limit (not ,(eq 'limit-unsupported pl-return)) 2075 (funcall ',setup-buttons-func ',backend ',files ',retval)
1927 (not ,is-start-revision))
1928 (goto-char (point-max))
1929 (widget-create 'push-button
1930 :notify (lambda (&rest ignore)
1931 (vc-print-log-internal
1932 ',backend ',files ',working-revision nil (* 2 ,limit)))
1933 :help-echo "Show the log again, and double the number of log entries shown"
1934 "Show 2X entries")
1935 (widget-insert " ")
1936 (widget-create 'push-button
1937 :notify (lambda (&rest ignore)
1938 (vc-print-log-internal
1939 ',backend ',files ',working-revision nil nil))
1940 :help-echo "Show the log again, showing all entries"
1941 "Show unlimited entries")
1942 (widget-setup))
1943
1944 (shrink-window-if-larger-than-buffer) 2076 (shrink-window-if-larger-than-buffer)
1945 ;; move point to the log entry for the working revision 2077 (funcall ',goto-location-func ',backend)
1946 (vc-call-backend ',backend 'show-log-entry ',working-revision)
1947 (setq vc-sentinel-movepoint (point)) 2078 (setq vc-sentinel-movepoint (point))
1948 (set-buffer-modified-p nil))))) 2079 (set-buffer-modified-p nil)))))
1949 2080
2081(defun vc-incoming-outgoing-internal (backend remote-location buffer-name type)
2082 (vc-log-internal-common
2083 backend buffer-name nil type
2084 (lexical-let
2085 ((remote-location remote-location))
2086 (lambda (bk buf type-arg files)
2087 (vc-call-backend bk type-arg buf remote-location)))
2088 (lambda (bk files-arg ret))
2089 (lambda (bk)
2090 (goto-char (point-min)))
2091 (lexical-let
2092 ((backend backend)
2093 (remote-location remote-location)
2094 (buffer-name buffer-name)
2095 (type type))
2096 (lambda (ignore-auto noconfirm)
2097 (vc-incoming-outgoing-internal backend remote-location buffer-name type)))))
2098
1950;;;###autoload 2099;;;###autoload
1951(defun vc-print-log (&optional working-revision limit) 2100(defun vc-print-log (&optional working-revision limit)
1952 "List the change log of the current fileset in a window. 2101 "List the change log of the current fileset in a window.
@@ -1995,10 +2144,7 @@ When called interactively with a prefix argument, prompt for LIMIT."
1995 (list lim))) 2144 (list lim)))
1996 (t 2145 (t
1997 (list (when (> vc-log-show-limit 0) vc-log-show-limit))))) 2146 (list (when (> vc-log-show-limit 0) vc-log-show-limit)))))
1998 (let ((backend 2147 (let ((backend (vc-deduce-backend))
1999 (cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend)
2000 ((derived-mode-p 'dired-mode) (vc-responsible-backend default-directory))
2001 (vc-mode (vc-backend buffer-file-name))))
2002 rootdir working-revision) 2148 rootdir working-revision)
2003 (unless backend 2149 (unless backend
2004 (error "Buffer is not version controlled")) 2150 (error "Buffer is not version controlled"))
@@ -2007,6 +2153,32 @@ When called interactively with a prefix argument, prompt for LIMIT."
2007 (vc-print-log-internal backend (list rootdir) working-revision nil limit))) 2153 (vc-print-log-internal backend (list rootdir) working-revision nil limit)))
2008 2154
2009;;;###autoload 2155;;;###autoload
2156(defun vc-log-incoming (&optional remote-location)
2157 "Show a log of changes that will be received with a pull operation from REMOTE-LOCATION.
2158When called interactively with a prefix argument, prompt for REMOTE-LOCATION.."
2159 (interactive
2160 (when current-prefix-arg
2161 (list (read-string "Remote location (empty for default): "))))
2162 (let ((backend (vc-deduce-backend))
2163 rootdir working-revision)
2164 (unless backend
2165 (error "Buffer is not version controlled"))
2166 (vc-incoming-outgoing-internal backend remote-location "*vc-incoming*" 'log-incoming)))
2167
2168;;;###autoload
2169(defun vc-log-outgoing (&optional remote-location)
2170 "Show a log of changes that will be sent with a push operation to REMOTE-LOCATION.
2171When called interactively with a prefix argument, prompt for REMOTE-LOCATION."
2172 (interactive
2173 (when current-prefix-arg
2174 (list (read-string "Remote location (empty for default): "))))
2175 (let ((backend (vc-deduce-backend))
2176 rootdir working-revision)
2177 (unless backend
2178 (error "Buffer is not version controlled"))
2179 (vc-incoming-outgoing-internal backend remote-location "*vc-outgoing*" 'log-outgoing)))
2180
2181;;;###autoload
2010(defun vc-revert () 2182(defun vc-revert ()
2011 "Revert working copies of the selected fileset to their repository contents. 2183 "Revert working copies of the selected fileset to their repository contents.
2012This asks for confirmation if the buffer contents are not identical 2184This asks for confirmation if the buffer contents are not identical
@@ -2240,7 +2412,7 @@ backend to NEW-BACKEND, and unregister FILE from the current backend.
2240 (if unmodified-file 2412 (if unmodified-file
2241 (copy-file unmodified-file file 2413 (copy-file unmodified-file file
2242 'ok-if-already-exists 'keep-date) 2414 'ok-if-already-exists 'keep-date)
2243 (when (y-or-n-p "Get base revision from master? ") 2415 (when (y-or-n-p "Get base revision from repository? ")
2244 (vc-revert-file file)))) 2416 (vc-revert-file file))))
2245 (vc-call-backend new-backend 'receive-file file rev)) 2417 (vc-call-backend new-backend 'receive-file file rev))
2246 (when modified-file 2418 (when modified-file
@@ -2327,7 +2499,7 @@ backend to NEW-BACKEND, and unregister FILE from the current backend.
2327 2499
2328;;;###autoload 2500;;;###autoload
2329(defun vc-rename-file (old new) 2501(defun vc-rename-file (old new)
2330 "Rename file OLD to NEW, and rename its master file likewise." 2502 "Rename file OLD to NEW in both work area and repository."
2331 (interactive "fVC rename file: \nFRename to: ") 2503 (interactive "fVC rename file: \nFRename to: ")
2332 ;; in CL I would have said (setq new (merge-pathnames new old)) 2504 ;; in CL I would have said (setq new (merge-pathnames new old))
2333 (let ((old-base (file-name-nondirectory old))) 2505 (let ((old-base (file-name-nondirectory old)))
@@ -2451,6 +2623,10 @@ to provide the `find-revision' operation instead."
2451 2623
2452(defalias 'vc-default-check-headers 'ignore) 2624(defalias 'vc-default-check-headers 'ignore)
2453 2625
2626(declare-function log-edit-mode "log-edit" ())
2627
2628(defun vc-default-log-edit-mode (backend) (log-edit-mode))
2629
2454(defun vc-default-log-view-mode (backend) (log-view-mode)) 2630(defun vc-default-log-view-mode (backend) (log-view-mode))
2455 2631
2456(defun vc-default-show-log-entry (backend rev) 2632(defun vc-default-show-log-entry (backend rev)