* lisp/vc/vc-rcs.el: Remove some ancient comments.
[bpt/emacs.git] / lisp / vc / vc-hooks.el
CommitLineData
aae56ea7 1;;; vc-hooks.el --- resident support for version-control
594722a8 2
95df8112 3;; Copyright (C) 1992-1996, 1998-2011 Free Software Foundation, Inc.
594722a8 4
0e0d9831
GM
5;; Author: FSF (see vc.el for full credits)
6;; Maintainer: Andre Spiegel <spiegel@gnu.org>
bd78fa1d 7;; Package: vc
594722a8
ER
8
9;; This file is part of GNU Emacs.
10
eb3fa2cf 11;; GNU Emacs is free software: you can redistribute it and/or modify
594722a8 12;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
594722a8
ER
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7d56ad0d 19;; GNU General Public License for more details.
594722a8
ER
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
594722a8
ER
23
24;;; Commentary:
25
0e0d9831
GM
26;; This is the always-loaded portion of VC. It takes care of
27;; VC-related activities that are done when you visit a file, so that
28;; vc.el itself is loaded only when you use a VC command. See the
29;; commentary of vc.el.
594722a8
ER
30
31;;; Code:
32
c3ce5e29
AS
33(eval-when-compile
34 (require 'cl))
099bd78a 35
e1c0c2d1
KH
36;; Customization Variables (the rest is in vc.el)
37
e18cf2ee 38(defvar vc-ignore-vc-files nil)
5499f9dc 39(make-obsolete-variable 'vc-ignore-vc-files
329a656e
JB
40 "set `vc-handled-backends' to nil to disable VC."
41 "21.1")
5499f9dc 42
e18cf2ee 43(defvar vc-master-templates ())
0d2ce4ef
JB
44(make-obsolete-variable 'vc-master-templates
45 "to define master templates for a given BACKEND, use
5499f9dc 46vc-BACKEND-master-templates. To enable or disable VC for a given
329a656e
JB
47BACKEND, use `vc-handled-backends'."
48 "21.1")
5499f9dc 49
456e749f
SM
50(defcustom vc-ignore-dir-regexp
51 ;; Stop SMB, automounter, AFS, and DFS host lookups.
8cd56959 52 locate-dominating-stop-dir-regexp
43621386 53 "Regexp matching directory names that are not under VC's control.
ce9f8ffb
SM
54The default regexp prevents fruitless and time-consuming attempts
55to determine the VC status in directories in which filenames are
43621386
SM
56interpreted as hostnames."
57 :type 'regexp
58 :group 'vc)
ce9f8ffb 59
db86064f 60(defcustom vc-handled-backends '(RCS CVS SVN SCCS Bzr Git Hg Mtn Arch)
b1dc6d44
SM
61 ;; RCS, CVS, SVN and SCCS come first because they are per-dir
62 ;; rather than per-tree. RCS comes first because of the multibackend
63 ;; support intended to use RCS for local commits (with a remote CVS server).
e5162bc1 64 "List of version control backends for which VC will be used.
0e0d9831
GM
65Entries in this list will be tried in order to determine whether a
66file is under that sort of version control.
67Removing an entry from the list prevents VC from being activated
68when visiting a file managed by that backend.
69An empty list disables VC altogether."
70 :type '(repeat symbol)
dbd3d787 71 :version "23.1"
50bec091 72 :group 'vc)
31888047 73
1f0bee0a 74;; Note: we don't actually have a darcs back end yet.
db86064f 75;; Also, Meta-CVS (corresponsding to MCVS) is unsupported.
0b7f397c 76(defcustom vc-directory-exclusion-list (purecopy '("SCCS" "RCS" "CVS" "MCVS"
527b313d 77 ".svn" ".git" ".hg" ".bzr"
0b7f397c 78 "_MTN" "_darcs" "{arch}"))
9c4b89d5
ER
79 "List of directory names to be ignored when walking directory trees."
80 :type '(repeat string)
81 :group 'vc)
82
50bec091 83(defcustom vc-make-backup-files nil
e5162bc1 84 "If non-nil, backups of registered files are made as with other files.
50bec091
KH
85If nil (the default), files covered by version control don't get backups."
86 :type 'boolean
8f383484
DL
87 :group 'vc
88 :group 'backup)
594722a8 89
50bec091 90(defcustom vc-follow-symlinks 'ask
e5162bc1 91 "What to do if visiting a symbolic link to a file under version control.
0e0d9831
GM
92Editing such a file through the link bypasses the version control system,
93which is dangerous and probably not what you want.
94
95If this variable is t, VC follows the link and visits the real file,
b8063212
AS
96telling you about it in the echo area. If it is `ask', VC asks for
97confirmation whether it should follow the link. If nil, the link is
50bec091 98visited and a warning displayed."
0e0d9831
GM
99 :type '(choice (const :tag "Ask for confirmation" ask)
100 (const :tag "Visit link and warn" nil)
101 (const :tag "Follow link" t))
50bec091 102 :group 'vc)
b8063212 103
50bec091 104(defcustom vc-display-status t
e5162bc1 105 "If non-nil, display revision number and lock status in modeline.
50bec091
KH
106Otherwise, not displayed."
107 :type 'boolean
108 :group 'vc)
109
198d5c00 110
50bec091 111(defcustom vc-consult-headers t
e5162bc1 112 "If non-nil, identify work files by searching for version headers."
50bec091
KH
113 :type 'boolean
114 :group 'vc)
e1c0c2d1 115
50bec091 116(defcustom vc-keep-workfiles t
e5162bc1 117 "If non-nil, don't delete working files after registering changes.
e1c0c2d1 118If the back-end is CVS, workfiles are always kept, regardless of the
50bec091
KH
119value of this flag."
120 :type 'boolean
121 :group 'vc)
e1c0c2d1 122
50bec091 123(defcustom vc-mistrust-permissions nil
e5162bc1 124 "If non-nil, don't assume permissions/ownership track version-control status.
0e0d9831 125If nil, do rely on the permissions.
50bec091
KH
126See also variable `vc-consult-headers'."
127 :type 'boolean
128 :group 'vc)
e66eac08
AS
129
130(defun vc-mistrust-permissions (file)
0e0d9831 131 "Internal access function to variable `vc-mistrust-permissions' for FILE."
e66eac08
AS
132 (or (eq vc-mistrust-permissions 't)
133 (and vc-mistrust-permissions
0e0d9831 134 (funcall vc-mistrust-permissions
e66eac08
AS
135 (vc-backend-subdirectory-name file)))))
136
5870cb76 137(defcustom vc-stay-local 'only-file
e5162bc1 138 "Non-nil means use local operations when possible for remote repositories.
113414a9
SM
139This avoids slow queries over the network and instead uses heuristics
140and past information to determine the current status of a file.
141
5870cb76
DN
142If value is the symbol `only-file' `vc-dir' will connect to the
143server, but heuristics will be used to determine the status for
144all other VC operations.
145
113414a9
SM
146The value can also be a regular expression or list of regular
147expressions to match against the host name of a repository; then VC
148only stays local for hosts that match it. Alternatively, the value
149can be a list of regular expressions where the first element is the
150symbol `except'; then VC always stays local except for hosts matched
151by these regular expressions."
5870cb76
DN
152 :type '(choice
153 (const :tag "Always stay local" t)
37e14a62 154 (const :tag "Only for file operations" only-file)
113414a9
SM
155 (const :tag "Don't stay local" nil)
156 (list :format "\nExamine hostname and %v" :tag "Examine hostname ..."
157 (set :format "%v" :inline t (const :format "%t" :tag "don't" except))
158 (regexp :format " stay local,\n%t: %v" :tag "if it matches")
159 (repeat :format "%v%i\n" :inline t (regexp :tag "or"))))
5870cb76 160 :version "23.1"
113414a9
SM
161 :group 'vc)
162
77bf3f54 163(defun vc-stay-local-p (file &optional backend)
113414a9 164 "Return non-nil if VC should stay local when handling FILE.
33e0847d
TTN
165This uses the `repository-hostname' backend operation.
166If FILE is a list of files, return non-nil if any of them
167individually should stay local."
e4d26892 168 (if (listp file)
77bf3f54
DN
169 (delq nil (mapcar (lambda (arg) (vc-stay-local-p arg backend)) file))
170 (setq backend (or backend (vc-backend file)))
171 (let* ((sym (vc-make-backend-sym backend 'stay-local))
95541017 172 (stay-local (if (boundp sym) (symbol-value sym) vc-stay-local)))
e4d26892
ER
173 (if (symbolp stay-local) stay-local
174 (let ((dirname (if (file-directory-p file)
175 (directory-file-name file)
176 (file-name-directory file))))
177 (eq 'yes
178 (or (vc-file-getprop dirname 'vc-stay-local-p)
179 (vc-file-setprop
180 dirname 'vc-stay-local-p
181 (let ((hostname (vc-call-backend
182 backend 'repository-hostname dirname)))
183 (if (not hostname)
184 'no
185 (let ((default t))
186 (if (eq (car-safe stay-local) 'except)
187 (setq default nil stay-local (cdr stay-local)))
188 (when (consp stay-local)
189 (setq stay-local
190 (mapconcat 'identity stay-local "\\|")))
191 (if (if (string-match stay-local hostname)
192 default (not default))
193 'yes 'no))))))))))))
113414a9 194
9bd06e95 195;;; This is handled specially now.
594722a8 196;; Tell Emacs about this new kind of minor mode
9bd06e95 197;; (add-to-list 'minor-mode-alist '(vc-mode vc-mode))
594722a8 198
d270305a 199;;;###autoload
6dc3311d 200(put 'vc-mode 'risky-local-variable t)
7bc2b98b 201(make-variable-buffer-local 'vc-mode)
c43e436c 202(put 'vc-mode 'permanent-local t)
594722a8 203
14fef9de
SM
204(defun vc-mode (&optional arg)
205 ;; Dummy function for C-h m
206 "Version Control minor mode.
207This minor mode is automatically activated whenever you visit a file under
208control of one of the revision control systems in `vc-handled-backends'.
209VC commands are globally reachable under the prefix `\\[vc-prefix-map]':
210\\{vc-prefix-map}")
211
099bd78a 212(defmacro vc-error-occurred (&rest body)
becd6193 213 `(condition-case nil (progn ,@body nil) (error t)))
099bd78a 214
594722a8 215;; We need a notion of per-file properties because the version
f2ee4191 216;; control state of a file is expensive to derive --- we compute
0e0d9831 217;; them when the file is initially found, keep them up to date
f2ee4191
RS
218;; during any subsequent VC operations, and forget them when
219;; the buffer is killed.
594722a8 220
becd6193 221(defvar vc-file-prop-obarray (make-vector 17 0)
594722a8
ER
222 "Obarray for per-file properties.")
223
099bd78a
SM
224(defvar vc-touched-properties nil)
225
594722a8 226(defun vc-file-setprop (file property value)
0e0d9831 227 "Set per-file VC PROPERTY for FILE to VALUE."
099bd78a
SM
228 (if (and vc-touched-properties
229 (not (memq property vc-touched-properties)))
230 (setq vc-touched-properties (append (list property)
231 vc-touched-properties)))
594722a8
ER
232 (put (intern file vc-file-prop-obarray) property value))
233
234(defun vc-file-getprop (file property)
099bd78a 235 "Get per-file VC PROPERTY for FILE."
594722a8
ER
236 (get (intern file vc-file-prop-obarray) property))
237
e1c0c2d1 238(defun vc-file-clearprops (file)
0e0d9831 239 "Clear all VC properties of FILE."
f98c9a23 240 (setplist (intern file vc-file-prop-obarray) nil))
f2ee4191 241
0e0d9831
GM
242\f
243;; We keep properties on each symbol naming a backend as follows:
244;; * `vc-functions': an alist mapping vc-FUNCTION to vc-BACKEND-FUNCTION.
245
246(defun vc-make-backend-sym (backend sym)
247 "Return BACKEND-specific version of VC symbol SYM."
248 (intern (concat "vc-" (downcase (symbol-name backend))
249 "-" (symbol-name sym))))
250
251(defun vc-find-backend-function (backend fun)
252 "Return BACKEND-specific implementation of FUN.
f8b72742 253If there is no such implementation, return the default implementation;
0e0d9831
GM
254if that doesn't exist either, return nil."
255 (let ((f (vc-make-backend-sym backend fun)))
256 (if (fboundp f) f
257 ;; Load vc-BACKEND.el if needed.
258 (require (intern (concat "vc-" (downcase (symbol-name backend)))))
259 (if (fboundp f) f
260 (let ((def (vc-make-backend-sym 'default fun)))
261 (if (fboundp def) (cons def backend) nil))))))
262
263(defun vc-call-backend (backend function-name &rest args)
264 "Call for BACKEND the implementation of FUNCTION-NAME with the given ARGS.
265Calls
266
267 (apply 'vc-BACKEND-FUN ARGS)
268
269if vc-BACKEND-FUN exists (after trying to find it in vc-BACKEND.el)
270and else calls
271
272 (apply 'vc-default-FUN BACKEND ARGS)
273
274It is usually called via the `vc-call' macro."
0bfb74a9
SM
275 (let ((f (assoc function-name (get backend 'vc-functions))))
276 (if f (setq f (cdr f))
0e0d9831 277 (setq f (vc-find-backend-function backend function-name))
0bfb74a9
SM
278 (push (cons function-name f) (get backend 'vc-functions)))
279 (cond
280 ((null f)
281 (error "Sorry, %s is not implemented for %s" function-name backend))
282 ((consp f) (apply (car f) (cdr f) args))
283 (t (apply f args)))))
0e0d9831
GM
284
285(defmacro vc-call (fun file &rest args)
daffc81a
JR
286 "A convenience macro for calling VC backend functions.
287Functions called by this macro must accept FILE as the first argument.
d4e772c4
JB
288ARGS specifies any additional arguments. FUN should be unquoted.
289BEWARE!! FILE is evaluated twice!!"
0e0d9831 290 `(vc-call-backend (vc-backend ,file) ',fun ,file ,@args))
0e0d9831
GM
291\f
292(defsubst vc-parse-buffer (pattern i)
293 "Find PATTERN in the current buffer and return its Ith submatch."
294 (goto-char (point-min))
295 (if (re-search-forward pattern nil t)
296 (match-string i)))
e1c0c2d1 297
02d383eb 298(defun vc-insert-file (file &optional limit blocksize)
0e0d9831
GM
299 "Insert the contents of FILE into the current buffer.
300
301Optional argument LIMIT is a regexp. If present, the file is inserted
302in chunks of size BLOCKSIZE (default 8 kByte), until the first
f8b72742 303occurrence of LIMIT is found. Anything from the start of that occurrence
e30140ce
AS
304to the end of the buffer is then deleted. The function returns
305non-nil if FILE exists and its contents were successfully inserted."
07de4c3d 306 (erase-buffer)
ff40374a
AS
307 (when (file-exists-p file)
308 (if (not limit)
309 (insert-file-contents file)
b5446276 310 (unless blocksize (setq blocksize 8192))
4d2806e2
SM
311 (let ((filepos 0))
312 (while
313 (and (< 0 (cadr (insert-file-contents
314 file nil filepos (incf filepos blocksize))))
315 (progn (beginning-of-line)
e30140ce 316 (let ((pos (re-search-forward limit nil 'move)))
b5446276
DN
317 (when pos (delete-region (match-beginning 0)
318 (point-max)))
e30140ce 319 (not pos)))))))
ff40374a
AS
320 (set-buffer-modified-p nil)
321 t))
02d383eb 322
3dd2acc9 323(defun vc-find-root (file witness)
ce9f8ffb
SM
324 "Find the root of a checked out project.
325The function walks up the directory tree from FILE looking for WITNESS.
3dd2acc9 326If WITNESS if not found, return nil, otherwise return the root."
8cd56959
SM
327 (let ((locate-dominating-stop-dir-regexp
328 (or vc-ignore-dir-regexp locate-dominating-stop-dir-regexp)))
329 (locate-dominating-file file witness)))
37e14a62 330
14fef9de
SM
331;; Access functions to file properties
332;; (Properties should be _set_ using vc-file-setprop, but
333;; _retrieved_ only through these functions, which decide
d4e772c4 334;; if the property is already known or not. A property should
14fef9de
SM
335;; only be retrieved by vc-file-getprop if there is no
336;; access function.)
02d383eb 337
14fef9de 338;; properties indicating the backend being used for FILE
e1c0c2d1 339
0e0d9831
GM
340(defun vc-registered (file)
341 "Return non-nil if FILE is registered in a version control system.
342
1f22ad24
AS
343This function performs the check each time it is called. To rely
344on the result of a previous call, use `vc-backend' instead. If the
345file was previously registered under a certain backend, then that
346backend is tried first."
0e0d9831 347 (let (handler)
ce9f8ffb 348 (cond
8cd56959
SM
349 ((and (file-name-directory file)
350 (string-match vc-ignore-dir-regexp (file-name-directory file)))
44cd688b 351 nil)
ce9f8ffb
SM
352 ((and (boundp 'file-name-handler-alist)
353 (setq handler (find-file-name-handler file 'vc-registered)))
354 ;; handler should set vc-backend and return t if registered
355 (funcall handler 'vc-registered file))
356 (t
0e0d9831
GM
357 ;; There is no file name handler.
358 ;; Try vc-BACKEND-registered for each handled BACKEND.
359 (catch 'found
1f22ad24 360 (let ((backend (vc-file-getprop file 'vc-backend)))
a549ce70 361 (mapc
1f22ad24
AS
362 (lambda (b)
363 (and (vc-call-backend b 'registered file)
364 (vc-file-setprop file 'vc-backend b)
365 (throw 'found t)))
f8b72742 366 (if (or (not backend) (eq backend 'none))
1f22ad24
AS
367 vc-handled-backends
368 (cons backend vc-handled-backends))))
0e0d9831
GM
369 ;; File is not registered.
370 (vc-file-setprop file 'vc-backend 'none)
ce9f8ffb 371 nil)))))
0e0d9831 372
e4d26892
ER
373(defun vc-backend (file-or-list)
374 "Return the version control type of FILE-OR-LIST, nil if it's not registered.
375If the argument is a list, the files must all have the same back end."
0e0d9831 376 ;; `file' can be nil in several places (typically due to the use of
5232a436 377 ;; code like (vc-backend buffer-file-name)).
e4d26892
ER
378 (cond ((stringp file-or-list)
379 (let ((property (vc-file-getprop file-or-list 'vc-backend)))
380 ;; Note that internally, Emacs remembers unregistered
381 ;; files by setting the property to `none'.
382 (cond ((eq property 'none) nil)
383 (property)
384 ;; vc-registered sets the vc-backend property
385 (t (if (vc-registered file-or-list)
386 (vc-file-getprop file-or-list 'vc-backend)
387 nil)))))
388 ((and file-or-list (listp file-or-list))
389 (vc-backend (car file-or-list)))
390 (t
391 nil)))
392
0e0d9831
GM
393
394(defun vc-backend-subdirectory-name (file)
004f9b3f 395 "Return where the repository for the current directory is kept."
0e0d9831 396 (symbol-name (vc-backend file)))
e1c0c2d1 397
02d383eb 398(defun vc-name (file)
5eb2b516
DL
399 "Return the master name of FILE.
400If the file is not registered, or the master name is not known, return nil."
401 ;; TODO: This should ultimately become obsolete, at least up here
0e0d9831 402 ;; in vc-hooks.
02d383eb 403 (or (vc-file-getprop file 'vc-name)
64341022
AS
404 ;; force computation of the property by calling
405 ;; vc-BACKEND-registered explicitly
32ca5ee4
DN
406 (let ((backend (vc-backend file)))
407 (if (and backend
408 (vc-call-backend backend 'registered file))
409 (vc-file-getprop file 'vc-name)))))
e1c0c2d1 410
e0607aaa
SM
411(defun vc-checkout-model (backend files)
412 "Indicate how FILES are checked out.
0e0d9831 413
e0607aaa 414If FILES are not registered, this function always returns nil.
cb5af02a 415For registered files, the possible values are:
0e0d9831 416
fe3e2715 417 'implicit FILES are always writable, and checked out `implicitly'
0e0d9831
GM
418 when the user saves the first changes to the file.
419
e0607aaa 420 'locking FILES are read-only if up-to-date; user must type
db8afaee 421 \\[vc-next-action] before editing. Strict locking
0e0d9831
GM
422 is assumed.
423
e0607aaa 424 'announce FILES are read-only if up-to-date; user must type
db8afaee 425 \\[vc-next-action] before editing. But other users
0e0d9831 426 may be editing at the same time."
e0607aaa 427 (vc-call-backend backend 'checkout-model files))
7064821c 428
8d2b9c1a
AS
429(defun vc-user-login-name (file)
430 "Return the name under which the user accesses the given FILE."
431 (or (and (eq (string-match tramp-file-name-regexp file) 0)
432 ;; tramp case: execute "whoami" via tramp
ba2318b7
MA
433 (let ((default-directory (file-name-directory file))
434 process-file-side-effects)
8d2b9c1a
AS
435 (with-temp-buffer
436 (if (not (zerop (process-file "whoami" nil t)))
437 ;; fall through if "whoami" didn't work
438 nil
439 ;; remove trailing newline
440 (delete-region (1- (point-max)) (point-max))
441 (buffer-string)))))
442 ;; normal case
443 (user-login-name)
444 ;; if user-login-name is nil, return the UID as a string
445 (number-to-string (user-uid))))
0e0d9831 446
77bf3f54 447(defun vc-state (file &optional backend)
0e0d9831
GM
448 "Return the version control state of FILE.
449
cb5af02a
AS
450If FILE is not registered, this function always returns nil.
451For registered files, the value returned is one of:
0e0d9831
GM
452
453 'up-to-date The working file is unmodified with respect to the
454 latest version on the current branch, and not locked.
455
456 'edited The working file has been edited by the user. If
457 locking is used for the file, this state means that
458 the current version is locked by the calling user.
f6d90772
ER
459 This status should *not* be reported for files
460 which have a changed mtime but the same content
461 as the repo copy.
0e0d9831
GM
462
463 USER The current version of the working file is locked by
464 some other USER (a string).
f8b72742 465
004f9b3f 466 'needs-update The file has not been edited by the user, but there is
0e0d9831 467 a more recent version on the current branch stored
004f9b3f 468 in the repository.
0e0d9831
GM
469
470 'needs-merge The file has been edited by the user, and there is also
471 a more recent version on the current branch stored in
004f9b3f 472 the repository. This state can only occur if locking
0e0d9831
GM
473 is not used for the file.
474
fae00181 475 'unlocked-changes The working version of the file is not locked,
0e0d9831
GM
476 but the working file has been changed with respect
477 to that version. This state can only occur for files
478 with locking; it represents an erroneous condition that
479 should be resolved by the user (vc-next-action will
fae00181
ER
480 prompt the user to do it).
481
482 'added Scheduled to go into the repository on the next commit.
14f26054 483 Often represented by vc-working-revision = \"0\" in VCSes
722f037f
ER
484 with monotonic IDs like Subversion and Mercurial.
485
484c1b1f 486 'removed Scheduled to be deleted from the repository on next commit.
527b313d 487
7fbb4797 488 'conflict The file contains conflicts as the result of a merge.
329a656e
JB
489 For now the conflicts are text conflicts. In the
490 future this might be extended to deal with metadata
7fbb4797
DN
491 conflicts too.
492
329a656e 493 'missing The file is not present in the file system, but the VC
dd0d723c
DN
494 system still tracks it.
495
4903369a 496 'ignored The file showed up in a dir-status listing with a flag
722f037f 497 indicating the version-control system is ignoring it,
527b313d
SS
498 Note: This property is not set reliably (some VCSes
499 don't have useful directory-status commands) so assume
722f037f 500 that any file with vc-state nil might be ignorable
527b313d 501 without VC knowing it.
722f037f 502
3702367b 503 'unregistered The file is not under version control.
722f037f 504
527b313d 505A return of nil from this function means we have no information on the
d4e772c4 506status of this file."
a970a27e
ER
507 ;; Note: in Emacs 22 and older, return of nil meant the file was
508 ;; unregistered. This is potentially a source of
509 ;; backward-compatibility bugs.
fae00181 510
2a3897f5 511 ;; FIXME: New (sub)states needed (?):
2a3897f5 512 ;; - `copied' and `moved' (might be handled by `removed' and `added')
0e0d9831 513 (or (vc-file-getprop file 'vc-state)
dcbbecd4 514 (when (> (length file) 0) ;Why?? --Stef
77bf3f54
DN
515 (setq backend (or backend (vc-backend file)))
516 (when backend
dcbbecd4
SM
517 (vc-state-refresh file backend)))))
518
519(defun vc-state-refresh (file backend)
520 "Quickly recompute the `state' of FILE."
521 (vc-file-setprop
522 file 'vc-state
523 (vc-call-backend backend 'state-heuristic file)))
0e0d9831
GM
524
525(defsubst vc-up-to-date-p (file)
526 "Convenience function that checks whether `vc-state' of FILE is `up-to-date'."
527 (eq (vc-state file) 'up-to-date))
528
529(defun vc-default-state-heuristic (backend file)
d4e772c4 530 "Default implementation of vc-BACKEND-state-heuristic.
5eb2b516
DL
531It simply calls the real state computation function `vc-BACKEND-state'
532and does not employ any heuristic at all."
0e0d9831 533 (vc-call-backend backend 'state file))
1efcbf46 534
e767004f
AS
535(defun vc-workfile-unchanged-p (file)
536 "Return non-nil if FILE has not changed since the last checkout."
537 (let ((checkout-time (vc-file-getprop file 'vc-checkout-time))
538 (lastmod (nth 5 (file-attributes file))))
70c8a390
CY
539 ;; This is a shortcut for determining when the workfile is
540 ;; unchanged. It can fail under some circumstances; see the
541 ;; discussion in bug#694.
542 (if (and checkout-time
543 ;; Tramp and Ange-FTP return this when they don't know the time.
544 (not (equal lastmod '(0 0))))
545 (equal checkout-time lastmod)
546 (let ((unchanged (vc-call workfile-unchanged-p file)))
547 (vc-file-setprop file 'vc-checkout-time (if unchanged lastmod 0))
548 unchanged))))
e767004f
AS
549
550(defun vc-default-workfile-unchanged-p (backend file)
004f9b3f 551 "Check if FILE is unchanged by diffing against the repository version.
e767004f 552Return non-nil if FILE is unchanged."
f8836381 553 (zerop (condition-case err
4392edab
AS
554 ;; If the implementation supports it, let the output
555 ;; go to *vc*, not *vc-diff*, since this is an internal call.
a749e19d 556 (vc-call-backend backend 'diff (list file) nil nil "*vc*")
f8836381
AS
557 (wrong-number-of-arguments
558 ;; If this error came from the above call to vc-BACKEND-diff,
559 ;; try again without the optional buffer argument (for
560 ;; backward compatibility). Otherwise, resignal.
561 (if (or (not (eq (cadr err)
562 (indirect-function
a749e19d 563 (vc-find-backend-function backend 'diff))))
0d2ce4ef
JB
564 (not (eq (caddr err) 4)))
565 (signal (car err) (cdr err))
a749e19d 566 (vc-call-backend backend 'diff (list file)))))))
e767004f 567
77bf3f54 568(defun vc-working-revision (file &optional backend)
e4d26892 569 "Return the repository version from which FILE was checked out.
cb5af02a 570If FILE is not registered, this function always returns nil."
ac3f4c6f 571 (or (vc-file-getprop file 'vc-working-revision)
77bf3f54
DN
572 (progn
573 (setq backend (or backend (vc-backend file)))
574 (when backend
575 (vc-file-setprop file 'vc-working-revision
576 (vc-call-backend backend 'working-revision file))))))
b5446276 577
6e5d0e9e
SM
578;; Backward compatibility.
579(define-obsolete-function-alias
580 'vc-workfile-version 'vc-working-revision "23.1")
581(defun vc-default-working-revision (backend file)
582 (message
583 "`working-revision' not found: using the old `workfile-version' instead")
584 (vc-call-backend backend 'workfile-version file))
f2ee4191 585
0e0d9831
GM
586(defun vc-default-registered (backend file)
587 "Check if FILE is registered in BACKEND using vc-BACKEND-master-templates."
588 (let ((sym (vc-make-backend-sym backend 'master-templates)))
589 (unless (get backend 'vc-templates-grabbed)
590 (put backend 'vc-templates-grabbed t)
591 (set sym (append (delq nil
592 (mapcar
593 (lambda (template)
594 (and (consp template)
595 (eq (cdr template) backend)
596 (car template)))
3756d481
AS
597 (with-no-warnings
598 vc-master-templates)))
0e0d9831
GM
599 (symbol-value sym))))
600 (let ((result (vc-check-master-templates file (symbol-value sym))))
601 (if (stringp result)
602 (vc-file-setprop file 'vc-name result)
603 nil)))) ; Not registered
604
605(defun vc-possible-master (s dirname basename)
606 (cond
607 ((stringp s) (format s dirname basename))
608 ((functionp s)
609 ;; The template is a function to invoke. If the
610 ;; function returns non-nil, that means it has found a
611 ;; master. For backward compatibility, we also handle
612 ;; the case that the function throws a 'found atom
613 ;; and a pair (cons MASTER-FILE BACKEND).
614 (let ((result (catch 'found (funcall s dirname basename))))
615 (if (consp result) (car result) result)))))
616
617(defun vc-check-master-templates (file templates)
cb5af02a 618 "Return non-nil if there is a master corresponding to FILE.
0e0d9831
GM
619
620TEMPLATES is a list of strings or functions. If an element is a
621string, it must be a control string as required by `format', with two
622string placeholders, such as \"%sRCS/%s,v\". The directory part of
623FILE is substituted for the first placeholder, the basename of FILE
624for the second. If a file with the resulting name exists, it is taken
625as the master of FILE, and returned.
626
627If an element of TEMPLATES is a function, it is called with the
628directory part and the basename of FILE as arguments. It should
629return non-nil if it finds a master; that value is then returned by
630this function."
631 (let ((dirname (or (file-name-directory file) ""))
632 (basename (file-name-nondirectory file)))
633 (catch 'found
5eb2b516 634 (mapcar
0e0d9831
GM
635 (lambda (s)
636 (let ((trial (vc-possible-master s dirname basename)))
b5446276
DN
637 (when (and trial (file-exists-p trial)
638 ;; Make sure the file we found with name
639 ;; TRIAL is not the source file itself.
640 ;; That can happen with RCS-style names if
641 ;; the file name is truncated (e.g. to 14
642 ;; chars). See if either directory or
643 ;; attributes differ.
644 (or (not (string= dirname
645 (file-name-directory trial)))
646 (not (equal (file-attributes file)
647 (file-attributes trial)))))
0e0d9831
GM
648 (throw 'found trial))))
649 templates))))
f2ee4191 650
c844616c 651(defun vc-toggle-read-only (&optional verbose)
c43e436c 652 "Change read-only status of current buffer, perhaps via version control.
db8afaee 653
c43e436c 654If the buffer is visiting a file registered with version control,
d4e772c4
JB
655throw an error, because this is not a safe or really meaningful operation
656on any version-control system newer than RCS.
25e94278
ER
657
658Otherwise, just change the read-only flag of the buffer.
659
660If you bind this function to \\[toggle-read-only], then Emacs
661will properly intercept all attempts to toggle the read-only flag
662on version-controlled buffer."
c844616c 663 (interactive "P")
25e94278 664 (if (vc-backend buffer-file-name)
5a0c3f56 665 (error "Toggling the readability of a version controlled file is likely to wreak havoc")
594722a8
ER
666 (toggle-read-only)))
667
e896a9e1 668(defun vc-default-make-version-backups-p (backend file)
cb5af02a 669 "Return non-nil if unmodified versions should be backed up locally.
9aa10a43 670The default is to switch off this feature."
d445a975
AS
671 nil)
672
e896a9e1
AS
673(defun vc-version-backup-file-name (file &optional rev manual regexp)
674 "Return a backup file name for REV or the current version of FILE.
675If MANUAL is non-nil it means that a name for backups created by
676the user should be returned; if REGEXP is non-nil that means to return
677a regexp for matching all such backup files, regardless of the version."
e3f955b6
AS
678 (if regexp
679 (concat (regexp-quote (file-name-nondirectory file))
d4c813e9 680 "\\.~.+" (unless manual "\\.") "~")
f8b72742 681 (expand-file-name (concat (file-name-nondirectory file)
d4c813e9 682 ".~" (subst-char-in-string
ac3f4c6f 683 ?/ ?_ (or rev (vc-working-revision file)))
e3f955b6
AS
684 (unless manual ".") "~")
685 (file-name-directory file))))
e896a9e1
AS
686
687(defun vc-delete-automatic-version-backups (file)
688 "Delete all existing automatic version backups for FILE."
d455f4f7 689 (condition-case nil
a549ce70 690 (mapc
d455f4f7 691 'delete-file
79e954d0 692 (directory-files (or (file-name-directory file) default-directory) t
d455f4f7
SM
693 (vc-version-backup-file-name file nil nil t)))
694 ;; Don't fail when the directory doesn't exist.
695 (file-error nil)))
e896a9e1
AS
696
697(defun vc-make-version-backup (file)
698 "Make a backup copy of FILE, which is assumed in sync with the repository.
699Before doing that, check if there are any old backups and get rid of them."
48b15d3f 700 (unless (and (fboundp 'msdos-long-file-names)
ee9be3de 701 (not (with-no-warnings (msdos-long-file-names))))
48b15d3f 702 (vc-delete-automatic-version-backups file)
27707243
AS
703 (condition-case nil
704 (copy-file file (vc-version-backup-file-name file)
705 nil 'keep-date)
706 ;; It's ok if it doesn't work (e.g. directory not writable),
707 ;; since this is just for efficiency.
bf247b6e 708 (file-error
27707243
AS
709 (message
710 (concat "Warning: Cannot make version backup; "
711 "diff/revert therefore not local"))))))
d445a975
AS
712
713(defun vc-before-save ()
714 "Function to be called by `basic-save-buffer' (in files.el)."
715 ;; If the file on disk is still in sync with the repository,
716 ;; and version backups should be made, copy the file to
717 ;; another name. This enables local diffs and local reverting.
e0607aaa
SM
718 (let ((file buffer-file-name)
719 backend)
f42af255 720 (ignore-errors ;Be careful not to prevent saving the file.
e0607aaa 721 (and (setq backend (vc-backend file))
f42af255 722 (vc-up-to-date-p file)
70e2f6c7 723 (eq (vc-checkout-model backend (list file)) 'implicit)
a749e19d 724 (vc-call-backend backend 'make-version-backups-p file)
f42af255 725 (vc-make-version-backup file)))))
d445a975 726
74d0991f 727(declare-function vc-dir-resynch-file "vc-dir" (&optional fname))
004a00f4 728
dcbbecd4
SM
729(defvar vc-dir-buffers nil "List of vc-dir buffers.")
730
e66eac08 731(defun vc-after-save ()
0e0d9831 732 "Function to be called by `basic-save-buffer' (in files.el)."
5eb2b516 733 ;; If the file in the current buffer is under version control,
0e0d9831
GM
734 ;; up-to-date, and locking is not used for the file, set
735 ;; the state to 'edited and redisplay the mode line.
e0607aaa
SM
736 (let* ((file buffer-file-name)
737 (backend (vc-backend file)))
738 (and backend
b23a2306
AS
739 (or (and (equal (vc-file-getprop file 'vc-checkout-time)
740 (nth 5 (file-attributes file)))
741 ;; File has been saved in the same second in which
742 ;; it was checked out. Clear the checkout-time
743 ;; to avoid confusion.
744 (vc-file-setprop file 'vc-checkout-time nil))
745 t)
70e2f6c7 746 (eq (vc-checkout-model backend (list file)) 'implicit)
dcbbecd4
SM
747 (vc-state-refresh file backend)
748 (vc-mode-line file backend))
749 ;; Try to avoid unnecessary work, a *vc-dir* buffer is
750 ;; present if this is true.
751 (when vc-dir-buffers
752 (vc-dir-resynch-file file))))
04446ed0 753
e2247dc8 754(defvar vc-menu-entry
8f43cbf3 755 `(menu-item ,(purecopy "Version Control") vc-menu-map
e2247dc8
SM
756 :filter vc-menu-map-filter))
757
758(when (boundp 'menu-bar-tools-menu)
759 ;; We do not need to worry here about the placement of this entry
760 ;; because menu-bar.el has already created the proper spot for us
761 ;; and this will simply use it.
762 (define-key menu-bar-tools-menu [vc] vc-menu-entry))
763
5719a098
SM
764(defconst vc-mode-line-map
765 (let ((map (make-sparse-keymap)))
e2247dc8 766 (define-key map [mode-line down-mouse-1] vc-menu-entry)
5719a098
SM
767 map))
768
32ca5ee4 769(defun vc-mode-line (file &optional backend)
7bc2b98b 770 "Set `vc-mode' to display type of version control for FILE.
594722a8 771The value is set in the current buffer, which should be the buffer
32ca5ee4
DN
772visiting FILE.
773If BACKEND is passed use it as the VC backend when computing the result."
67c6f446 774 (interactive (list buffer-file-name))
32ca5ee4
DN
775 (setq backend (or backend (vc-backend file)))
776 (if (not backend)
777 (setq vc-mode nil)
778 (let* ((ml-string (vc-call-backend backend 'mode-line-string file))
779 (ml-echo (get-text-property 0 'help-echo ml-string)))
780 (setq vc-mode
781 (concat
782 " "
783 (if (null vc-display-status)
784 (symbol-name backend)
785 (propertize
786 ml-string
787 'mouse-face 'mode-line-highlight
788 'help-echo
789 (concat (or ml-echo
790 (format "File under the %s version control system"
791 backend))
792 "\nmouse-1: Version Control menu")
793 'local-map vc-mode-line-map)))))
32ca5ee4
DN
794 ;; If the user is root, and the file is not owner-writable,
795 ;; then pretend that we can't write it
796 ;; even though we can (because root can write anything).
797 ;; This way, even root cannot modify a file that isn't locked.
798 (and (equal file buffer-file-name)
799 (not buffer-read-only)
800 (zerop (user-real-uid))
801 (zerop (logand (file-modes buffer-file-name) 128))
802 (setq buffer-read-only t)))
803 (force-mode-line-update)
804 backend)
0e0d9831
GM
805
806(defun vc-default-mode-line-string (backend file)
807 "Return string for placement in modeline by `vc-mode-line' for FILE.
808Format:
809
810 \"BACKEND-REV\" if the file is up-to-date
811 \"BACKEND:REV\" if the file is edited (or locked by the calling user)
812 \"BACKEND:LOCKER:REV\" if the file is locked by somebody else
cad90f3b
EZ
813 \"BACKEND@REV\" if the file was locally added
814 \"BACKEND!REV\" if the file contains conflicts or was removed
815 \"BACKEND?REV\" if the file is under VC, but is missing
0e0d9831
GM
816
817This function assumes that the file is registered."
77bf3f54
DN
818 (let* ((backend-name (symbol-name backend))
819 (state (vc-state file backend))
820 (state-echo nil)
821 (rev (vc-working-revision file backend)))
82c4728d
DN
822 (propertize
823 (cond ((or (eq state 'up-to-date)
3702367b 824 (eq state 'needs-update))
82c4728d 825 (setq state-echo "Up to date file")
77bf3f54 826 (concat backend-name "-" rev))
82c4728d
DN
827 ((stringp state)
828 (setq state-echo (concat "File locked by" state))
77bf3f54 829 (concat backend-name ":" state ":" rev))
45b24b4d
SM
830 ((eq state 'added)
831 (setq state-echo "Locally added file")
77bf3f54 832 (concat backend-name "@" rev))
7fbb4797
DN
833 ((eq state 'conflict)
834 (setq state-echo "File contains conflicts after the last merge")
77bf3f54 835 (concat backend-name "!" rev))
a58b57e2
DN
836 ((eq state 'removed)
837 (setq state-echo "File removed from the VC system")
77bf3f54 838 (concat backend-name "!" rev))
a58b57e2
DN
839 ((eq state 'missing)
840 (setq state-echo "File tracked by the VC system, but missing from the file system")
77bf3f54 841 (concat backend-name "?" rev))
82c4728d
DN
842 (t
843 ;; Not just for the 'edited state, but also a fallback
844 ;; for all other states. Think about different symbols
3702367b 845 ;; for 'needs-update and 'needs-merge.
3a12f9f8 846 (setq state-echo "Locally modified file")
77bf3f54
DN
847 (concat backend-name ":" rev)))
848 'help-echo (concat state-echo " under the " backend-name
3a12f9f8 849 " version control system"))))
f2ee4191 850
a3a39848 851(defun vc-follow-link ()
0e0d9831
GM
852 "If current buffer visits a symbolic link, visit the real file.
853If the real file is already visited in another buffer, make that buffer
854current, and kill the buffer that visits the link."
33f95a82 855 (let* ((true-buffer (find-buffer-visiting buffer-file-truename))
e7f5ddc2
RS
856 (this-buffer (current-buffer)))
857 (if (eq true-buffer this-buffer)
066b7259 858 (let ((truename buffer-file-truename))
d8221951 859 (kill-buffer this-buffer)
e7f5ddc2
RS
860 ;; In principle, we could do something like set-visited-file-name.
861 ;; However, it can't be exactly the same as set-visited-file-name.
862 ;; I'm not going to work out the details right now. -- rms.
d8221951 863 (set-buffer (find-file-noselect truename)))
e7f5ddc2
RS
864 (set-buffer true-buffer)
865 (kill-buffer this-buffer))))
a3a39848 866
b8d1db77
SM
867(defun vc-default-find-file-hook (backend)
868 nil)
869
594722a8 870(defun vc-find-file-hook ()
be4d6a6f 871 "Function for `find-file-hook' activating VC mode if appropriate."
18c8a18e
PE
872 ;; Recompute whether file is version controlled,
873 ;; if user has killed the buffer and revisited.
32ca5ee4
DN
874 (when vc-mode
875 (setq vc-mode nil))
0e0d9831 876 (when buffer-file-name
f2ee4191 877 (vc-file-clearprops buffer-file-name)
8c6eab5a
SM
878 ;; FIXME: Why use a hook? Why pass it buffer-file-name?
879 (add-hook 'vc-mode-line-hook 'vc-mode-line nil t)
32ca5ee4
DN
880 (let (backend)
881 (cond
882 ((setq backend (with-demoted-errors (vc-backend buffer-file-name)))
883 ;; Compute the state and put it in the modeline.
884 (vc-mode-line buffer-file-name backend)
885 (unless vc-make-backup-files
886 ;; Use this variable, not make-backup-files,
887 ;; because this is for things that depend on the file name.
888 (set (make-local-variable 'backup-inhibited) t))
889 ;; Let the backend setup any buffer-local things he needs.
890 (vc-call-backend backend 'find-file-hook))
891 ((let ((link-type (and (not (equal buffer-file-name buffer-file-truename))
892 (vc-backend buffer-file-truename))))
893 (cond ((not link-type) nil) ;Nothing to do.
894 ((eq vc-follow-symlinks nil)
0bfb74a9 895 (message
32ca5ee4
DN
896 "Warning: symbolic link to %s-controlled source file" link-type))
897 ((or (not (eq vc-follow-symlinks 'ask))
898 ;; If we already visited this file by following
899 ;; the link, don't ask again if we try to visit
900 ;; it again. GUD does that, and repeated questions
901 ;; are painful.
902 (get-file-buffer
903 (abbreviate-file-name
904 (file-chase-links buffer-file-name))))
905
906 (vc-follow-link)
907 (message "Followed link to %s" buffer-file-name)
908 (vc-find-file-hook))
909 (t
910 (if (yes-or-no-p (format
911 "Symbolic link to %s-controlled source file; follow link? " link-type))
912 (progn (vc-follow-link)
913 (message "Followed link to %s" buffer-file-name)
914 (vc-find-file-hook))
915 (message
916 "Warning: editing through the link bypasses version control")
917 )))))))))
594722a8 918
be4d6a6f 919(add-hook 'find-file-hook 'vc-find-file-hook)
594722a8 920
f2ee4191 921(defun vc-kill-buffer-hook ()
0e0d9831 922 "Discard VC info about a file when we kill its buffer."
b5446276 923 (when buffer-file-name (vc-file-clearprops buffer-file-name)))
f2ee4191 924
cd32d5d1 925(add-hook 'kill-buffer-hook 'vc-kill-buffer-hook)
f2ee4191 926
14fef9de
SM
927;; Now arrange for (autoloaded) bindings of the main package.
928;; Bindings for this have to go in the global map, as we'll often
929;; want to call them from random buffers.
930
931;; Autoloading works fine, but it prevents shortcuts from appearing
932;; in the menu because they don't exist yet when the menu is built.
933;; (autoload 'vc-prefix-map "vc" nil nil 'keymap)
934(defvar vc-prefix-map
935 (let ((map (make-sparse-keymap)))
936 (define-key map "a" 'vc-update-change-log)
937 (define-key map "b" 'vc-switch-backend)
e4d26892 938 (define-key map "c" 'vc-rollback)
e1aec6fb 939 (define-key map "d" 'vc-dir)
14fef9de
SM
940 (define-key map "g" 'vc-annotate)
941 (define-key map "h" 'vc-insert-headers)
942 (define-key map "i" 'vc-register)
943 (define-key map "l" 'vc-print-log)
32ba3abc 944 (define-key map "L" 'vc-print-root-log)
54d3626e
DN
945 (define-key map "I" 'vc-log-incoming)
946 (define-key map "O" 'vc-log-outgoing)
14fef9de 947 (define-key map "m" 'vc-merge)
370fded4
ER
948 (define-key map "r" 'vc-retrieve-tag)
949 (define-key map "s" 'vc-create-tag)
e4d26892 950 (define-key map "u" 'vc-revert)
14fef9de 951 (define-key map "v" 'vc-next-action)
e4d26892 952 (define-key map "+" 'vc-update)
14fef9de 953 (define-key map "=" 'vc-diff)
32ba3abc 954 (define-key map "D" 'vc-root-diff)
0a0ca7f1 955 (define-key map "~" 'vc-revision-other-window)
14fef9de
SM
956 map))
957(fset 'vc-prefix-map vc-prefix-map)
c1fdf758 958(define-key global-map "\C-xv" 'vc-prefix-map)
624c0e9d 959
e2247dc8
SM
960(defvar vc-menu-map
961 (let ((map (make-sparse-keymap "Version Control")))
962 ;;(define-key map [show-files]
963 ;; '("Show Files under VC" . (vc-directory t)))
370fded4 964 (define-key map [vc-retrieve-tag]
8f43cbf3
DN
965 `(menu-item ,(purecopy "Retrieve Tag") vc-retrieve-tag
966 :help ,(purecopy "Retrieve tagged version or branch")))
370fded4 967 (define-key map [vc-create-tag]
8f43cbf3
DN
968 `(menu-item ,(purecopy "Create Tag") vc-create-tag
969 :help ,(purecopy "Create version tag")))
04991a1c 970 (define-key map [separator1] menu-bar-separator)
6dbb5c76 971 (define-key map [vc-annotate]
8f43cbf3
DN
972 `(menu-item ,(purecopy "Annotate") vc-annotate
973 :help ,(purecopy "Display the edit history of the current file using colors")))
6dbb5c76 974 (define-key map [vc-rename-file]
8f43cbf3
DN
975 `(menu-item ,(purecopy "Rename File") vc-rename-file
976 :help ,(purecopy "Rename file")))
0a0ca7f1 977 (define-key map [vc-revision-other-window]
8f43cbf3
DN
978 `(menu-item ,(purecopy "Show Other Version") vc-revision-other-window
979 :help ,(purecopy "Visit another version of the current file in another window")))
6dbb5c76 980 (define-key map [vc-diff]
8f43cbf3
DN
981 `(menu-item ,(purecopy "Compare with Base Version") vc-diff
982 :help ,(purecopy "Compare file set with the base version")))
32ba3abc 983 (define-key map [vc-root-diff]
8f43cbf3
DN
984 `(menu-item ,(purecopy "Compare Tree with Base Version") vc-root-diff
985 :help ,(purecopy "Compare current tree with the base version")))
e2247dc8 986 (define-key map [vc-update-change-log]
8f43cbf3
DN
987 `(menu-item ,(purecopy "Update ChangeLog") vc-update-change-log
988 :help ,(purecopy "Find change log file and add entries from recent version control logs")))
31527c56
DN
989 (define-key map [vc-log-out]
990 `(menu-item ,(purecopy "Show Outgoing Log") vc-log-outgoing
991 :help ,(purecopy "Show a log of changes that will be sent with a push operation")))
992 (define-key map [vc-log-in]
993 `(menu-item ,(purecopy "Show Incoming Log") vc-log-incoming
994 :help ,(purecopy "Show a log of changes that will be received with a pull operation")))
6dbb5c76 995 (define-key map [vc-print-log]
8f43cbf3
DN
996 `(menu-item ,(purecopy "Show History") vc-print-log
997 :help ,(purecopy "List the change log of the current file set in a window")))
32ba3abc 998 (define-key map [vc-print-root-log]
8f43cbf3
DN
999 `(menu-item ,(purecopy "Show Top of the Tree History ") vc-print-root-log
1000 :help ,(purecopy "List the change log for the current tree in a window")))
04991a1c 1001 (define-key map [separator2] menu-bar-separator)
e2247dc8 1002 (define-key map [vc-insert-header]
8f43cbf3
DN
1003 `(menu-item ,(purecopy "Insert Header") vc-insert-headers
1004 :help ,(purecopy "Insert headers into a file for use with a version control system.
1005")))
6dbb5c76 1006 (define-key map [undo]
8f43cbf3
DN
1007 `(menu-item ,(purecopy "Undo Last Check-In") vc-rollback
1008 :help ,(purecopy "Remove the most recent changeset committed to the repository")))
e2247dc8 1009 (define-key map [vc-revert]
8f43cbf3
DN
1010 `(menu-item ,(purecopy "Revert to Base Version") vc-revert
1011 :help ,(purecopy "Revert working copies of the selected file set to their repository contents")))
e2247dc8 1012 (define-key map [vc-update]
8f43cbf3
DN
1013 `(menu-item ,(purecopy "Update to Latest Version") vc-update
1014 :help ,(purecopy "Update the current fileset's files to their tip revisions")))
6dbb5c76 1015 (define-key map [vc-next-action]
8f43cbf3
DN
1016 `(menu-item ,(purecopy "Check In/Out") vc-next-action
1017 :help ,(purecopy "Do the next logical version control operation on the current fileset")))
6dbb5c76 1018 (define-key map [vc-register]
8f43cbf3
DN
1019 `(menu-item ,(purecopy "Register") vc-register
1020 :help ,(purecopy "Register file set into a version control system")))
e1aec6fb 1021 (define-key map [vc-dir]
8f43cbf3
DN
1022 `(menu-item ,(purecopy "VC Dir") vc-dir
1023 :help ,(purecopy "Show the VC status of files in a directory")))
e2247dc8
SM
1024 map))
1025
1026(defalias 'vc-menu-map vc-menu-map)
1027
d270305a 1028(declare-function vc-responsible-backend "vc" (file))
aafb0703 1029
e2247dc8
SM
1030(defun vc-menu-map-filter (orig-binding)
1031 (if (and (symbolp orig-binding) (fboundp orig-binding))
1032 (setq orig-binding (indirect-function orig-binding)))
1033 (let ((ext-binding
f3d57a2c 1034 (when vc-mode
aafb0703 1035 (vc-call-backend
f3d57a2c
DN
1036 (if buffer-file-name
1037 (vc-backend buffer-file-name)
1038 (vc-responsible-backend default-directory))
1039 'extra-menu))))
e2247dc8
SM
1040 ;; Give the VC backend a chance to add menu entries
1041 ;; specific for that backend.
1042 (if (null ext-binding)
98481bad 1043 orig-binding
e2247dc8 1044 (append orig-binding
04991a1c 1045 '((ext-menu-separator "--"))
98481bad 1046 ext-binding))))
738efc8e 1047
cb223bba
DN
1048(defun vc-default-extra-menu (backend)
1049 nil)
1050
594722a8
ER
1051(provide 'vc-hooks)
1052
1053;;; vc-hooks.el ends here