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