(file-truename): Get truename of ancestors if file does
[bpt/emacs.git] / lisp / vc-hooks.el
CommitLineData
aae56ea7 1;;; vc-hooks.el --- resident support for version-control
594722a8 2
c90f2757 3;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
409cc4a3 4;; 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
594722a8 5
0e0d9831
GM
6;; Author: FSF (see vc.el for full credits)
7;; Maintainer: Andre Spiegel <spiegel@gnu.org>
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
e18cf2ee 50(defvar vc-header-alist ())
329a656e 51(make-obsolete-variable 'vc-header-alist 'vc-BACKEND-header "21.1")
0e0d9831 52
456e749f
SM
53(defcustom vc-ignore-dir-regexp
54 ;; Stop SMB, automounter, AFS, and DFS host lookups.
55 "\\`\\(?:[\\/][\\/]\\|/\\(?:net\\|afs\\|\\.\\\.\\.\\)/\\)\\'"
43621386 56 "Regexp matching directory names that are not under VC's control.
ce9f8ffb
SM
57The default regexp prevents fruitless and time-consuming attempts
58to determine the VC status in directories in which filenames are
43621386
SM
59interpreted as hostnames."
60 :type 'regexp
61 :group 'vc)
ce9f8ffb 62
db86064f 63(defcustom vc-handled-backends '(RCS CVS SVN SCCS Bzr Git Hg Mtn Arch)
b1dc6d44
SM
64 ;; RCS, CVS, SVN and SCCS come first because they are per-dir
65 ;; rather than per-tree. RCS comes first because of the multibackend
66 ;; support intended to use RCS for local commits (with a remote CVS server).
e5162bc1 67 "List of version control backends for which VC will be used.
0e0d9831
GM
68Entries in this list will be tried in order to determine whether a
69file is under that sort of version control.
70Removing an entry from the list prevents VC from being activated
71when visiting a file managed by that backend.
72An empty list disables VC altogether."
73 :type '(repeat symbol)
dbd3d787 74 :version "23.1"
50bec091 75 :group 'vc)
31888047 76
1f0bee0a 77;; Note: we don't actually have a darcs back end yet.
db86064f 78;; Also, Meta-CVS (corresponsding to MCVS) is unsupported.
527b313d
SS
79(defcustom vc-directory-exclusion-list '("SCCS" "RCS" "CVS" "MCVS"
80 ".svn" ".git" ".hg" ".bzr"
1f0bee0a 81 "_MTN" "_darcs" "{arch}")
9c4b89d5
ER
82 "List of directory names to be ignored when walking directory trees."
83 :type '(repeat string)
84 :group 'vc)
85
14b11401 86(defcustom vc-path nil
e5162bc1 87 "List of extra directories to search for version control commands."
50bec091
KH
88 :type '(repeat directory)
89 :group 'vc)
e1c0c2d1 90
50bec091 91(defcustom vc-make-backup-files nil
e5162bc1 92 "If non-nil, backups of registered files are made as with other files.
50bec091
KH
93If nil (the default), files covered by version control don't get backups."
94 :type 'boolean
8f383484
DL
95 :group 'vc
96 :group 'backup)
594722a8 97
50bec091 98(defcustom vc-follow-symlinks 'ask
e5162bc1 99 "What to do if visiting a symbolic link to a file under version control.
0e0d9831
GM
100Editing such a file through the link bypasses the version control system,
101which is dangerous and probably not what you want.
102
103If this variable is t, VC follows the link and visits the real file,
b8063212
AS
104telling you about it in the echo area. If it is `ask', VC asks for
105confirmation whether it should follow the link. If nil, the link is
50bec091 106visited and a warning displayed."
0e0d9831
GM
107 :type '(choice (const :tag "Ask for confirmation" ask)
108 (const :tag "Visit link and warn" nil)
109 (const :tag "Follow link" t))
50bec091 110 :group 'vc)
b8063212 111
50bec091 112(defcustom vc-display-status t
e5162bc1 113 "If non-nil, display revision number and lock status in modeline.
50bec091
KH
114Otherwise, not displayed."
115 :type 'boolean
116 :group 'vc)
117
198d5c00 118
50bec091 119(defcustom vc-consult-headers t
e5162bc1 120 "If non-nil, identify work files by searching for version headers."
50bec091
KH
121 :type 'boolean
122 :group 'vc)
e1c0c2d1 123
50bec091 124(defcustom vc-keep-workfiles t
e5162bc1 125 "If non-nil, don't delete working files after registering changes.
e1c0c2d1 126If the back-end is CVS, workfiles are always kept, regardless of the
50bec091
KH
127value of this flag."
128 :type 'boolean
129 :group 'vc)
e1c0c2d1 130
50bec091 131(defcustom vc-mistrust-permissions nil
e5162bc1 132 "If non-nil, don't assume permissions/ownership track version-control status.
0e0d9831 133If nil, do rely on the permissions.
50bec091
KH
134See also variable `vc-consult-headers'."
135 :type 'boolean
136 :group 'vc)
e66eac08
AS
137
138(defun vc-mistrust-permissions (file)
0e0d9831 139 "Internal access function to variable `vc-mistrust-permissions' for FILE."
e66eac08
AS
140 (or (eq vc-mistrust-permissions 't)
141 (and vc-mistrust-permissions
0e0d9831 142 (funcall vc-mistrust-permissions
e66eac08
AS
143 (vc-backend-subdirectory-name file)))))
144
113414a9 145(defcustom vc-stay-local t
e5162bc1 146 "Non-nil means use local operations when possible for remote repositories.
113414a9
SM
147This avoids slow queries over the network and instead uses heuristics
148and past information to determine the current status of a file.
149
150The value can also be a regular expression or list of regular
151expressions to match against the host name of a repository; then VC
152only stays local for hosts that match it. Alternatively, the value
153can be a list of regular expressions where the first element is the
154symbol `except'; then VC always stays local except for hosts matched
155by these regular expressions."
156 :type '(choice (const :tag "Always stay local" t)
157 (const :tag "Don't stay local" nil)
158 (list :format "\nExamine hostname and %v" :tag "Examine hostname ..."
159 (set :format "%v" :inline t (const :format "%t" :tag "don't" except))
160 (regexp :format " stay local,\n%t: %v" :tag "if it matches")
161 (repeat :format "%v%i\n" :inline t (regexp :tag "or"))))
bf247b6e 162 :version "22.1"
113414a9
SM
163 :group 'vc)
164
165(defun vc-stay-local-p (file)
166 "Return non-nil if VC should stay local when handling FILE.
33e0847d
TTN
167This uses the `repository-hostname' backend operation.
168If FILE is a list of files, return non-nil if any of them
169individually should stay local."
e4d26892 170 (if (listp file)
33e0847d 171 (delq nil (mapcar 'vc-stay-local-p file))
e4d26892
ER
172 (let* ((backend (vc-backend file))
173 (sym (vc-make-backend-sym backend 'stay-local))
174 (stay-local (if (boundp sym) (symbol-value sym) t)))
175 (if (eq stay-local t) (setq stay-local vc-stay-local))
176 (if (symbolp stay-local) stay-local
177 (let ((dirname (if (file-directory-p file)
178 (directory-file-name file)
179 (file-name-directory file))))
180 (eq 'yes
181 (or (vc-file-getprop dirname 'vc-stay-local-p)
182 (vc-file-setprop
183 dirname 'vc-stay-local-p
184 (let ((hostname (vc-call-backend
185 backend 'repository-hostname dirname)))
186 (if (not hostname)
187 'no
188 (let ((default t))
189 (if (eq (car-safe stay-local) 'except)
190 (setq default nil stay-local (cdr stay-local)))
191 (when (consp stay-local)
192 (setq stay-local
193 (mapconcat 'identity stay-local "\\|")))
194 (if (if (string-match stay-local hostname)
195 default (not default))
196 'yes 'no))))))))))))
113414a9 197
9bd06e95 198;;; This is handled specially now.
594722a8 199;; Tell Emacs about this new kind of minor mode
9bd06e95 200;; (add-to-list 'minor-mode-alist '(vc-mode vc-mode))
594722a8 201
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."
e1c0c2d1 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
b038f9fb 324(defun vc-find-root (file witness &optional invert)
ce9f8ffb
SM
325 "Find the root of a checked out project.
326The function walks up the directory tree from FILE looking for WITNESS.
b038f9fb
TTN
327If WITNESS if not found, return nil, otherwise return the root.
328Optional arg INVERT non-nil reverses the sense of the check;
329the root is the last directory for which WITNESS *is* found."
43621386
SM
330 ;; Represent /home/luser/foo as ~/foo so that we don't try to look for
331 ;; witnesses in /home or in /.
332 (setq file (abbreviate-file-name file))
6e94b3b6 333 (let ((root nil)
b038f9fb 334 (prev-file file)
5f8ea2c8
SM
335 ;; `user' is not initialized outside the loop because
336 ;; `file' may not exist, so we may have to walk up part of the
337 ;; hierarchy before we find the "initial UID".
b03f96dc 338 (user nil)
b038f9fb 339 try)
ce9f8ffb 340 (while (not (or root
3b27900d
SM
341 (null file)
342 ;; As a heuristic, we stop looking up the hierarchy of
343 ;; directories as soon as we find a directory belonging
344 ;; to another user. This should save us from looking in
345 ;; things like /net and /afs. This assumes that all the
346 ;; files inside a project belong to the same user.
5f8ea2c8
SM
347 (let ((prev-user user))
348 (setq user (nth 2 (file-attributes file)))
349 (and prev-user (not (equal user prev-user))))
3b27900d 350 (string-match vc-ignore-dir-regexp file)))
b038f9fb
TTN
351 (setq try (file-exists-p (expand-file-name witness file)))
352 (cond ((and invert (not try)) (setq root prev-file))
353 ((and (not invert) try) (setq root file))
354 ((equal file (setq prev-file file
355 file (file-name-directory
356 (directory-file-name file))))
357 (setq file nil))))
358 ;; Handle the case where ~/WITNESS exists and the original FILE is "~".
359 ;; (This occurs, for example, when placing dotfiles under RCS.)
360 (when (and (not root) invert prev-file)
361 (setq root prev-file))
ce9f8ffb
SM
362 root))
363
14fef9de
SM
364;; Access functions to file properties
365;; (Properties should be _set_ using vc-file-setprop, but
366;; _retrieved_ only through these functions, which decide
d4e772c4 367;; if the property is already known or not. A property should
14fef9de
SM
368;; only be retrieved by vc-file-getprop if there is no
369;; access function.)
02d383eb 370
14fef9de 371;; properties indicating the backend being used for FILE
e1c0c2d1 372
0e0d9831
GM
373(defun vc-registered (file)
374 "Return non-nil if FILE is registered in a version control system.
375
1f22ad24
AS
376This function performs the check each time it is called. To rely
377on the result of a previous call, use `vc-backend' instead. If the
378file was previously registered under a certain backend, then that
379backend is tried first."
0e0d9831 380 (let (handler)
ce9f8ffb 381 (cond
44cd688b
ER
382 ((and (file-name-directory file) (string-match vc-ignore-dir-regexp (file-name-directory file)))
383 nil)
ce9f8ffb
SM
384 ((and (boundp 'file-name-handler-alist)
385 (setq handler (find-file-name-handler file 'vc-registered)))
386 ;; handler should set vc-backend and return t if registered
387 (funcall handler 'vc-registered file))
388 (t
0e0d9831
GM
389 ;; There is no file name handler.
390 ;; Try vc-BACKEND-registered for each handled BACKEND.
391 (catch 'found
1f22ad24 392 (let ((backend (vc-file-getprop file 'vc-backend)))
a549ce70 393 (mapc
1f22ad24
AS
394 (lambda (b)
395 (and (vc-call-backend b 'registered file)
396 (vc-file-setprop file 'vc-backend b)
397 (throw 'found t)))
f8b72742 398 (if (or (not backend) (eq backend 'none))
1f22ad24
AS
399 vc-handled-backends
400 (cons backend vc-handled-backends))))
0e0d9831
GM
401 ;; File is not registered.
402 (vc-file-setprop file 'vc-backend 'none)
ce9f8ffb 403 nil)))))
0e0d9831 404
e4d26892
ER
405(defun vc-backend (file-or-list)
406 "Return the version control type of FILE-OR-LIST, nil if it's not registered.
407If the argument is a list, the files must all have the same back end."
0e0d9831 408 ;; `file' can be nil in several places (typically due to the use of
5232a436 409 ;; code like (vc-backend buffer-file-name)).
e4d26892
ER
410 (cond ((stringp file-or-list)
411 (let ((property (vc-file-getprop file-or-list 'vc-backend)))
412 ;; Note that internally, Emacs remembers unregistered
413 ;; files by setting the property to `none'.
414 (cond ((eq property 'none) nil)
415 (property)
416 ;; vc-registered sets the vc-backend property
417 (t (if (vc-registered file-or-list)
418 (vc-file-getprop file-or-list 'vc-backend)
419 nil)))))
420 ((and file-or-list (listp file-or-list))
421 (vc-backend (car file-or-list)))
422 (t
423 nil)))
424
0e0d9831
GM
425
426(defun vc-backend-subdirectory-name (file)
427 "Return where the master and lock FILEs for the current directory are kept."
428 (symbol-name (vc-backend file)))
e1c0c2d1 429
02d383eb 430(defun vc-name (file)
5eb2b516
DL
431 "Return the master name of FILE.
432If the file is not registered, or the master name is not known, return nil."
433 ;; TODO: This should ultimately become obsolete, at least up here
0e0d9831 434 ;; in vc-hooks.
02d383eb 435 (or (vc-file-getprop file 'vc-name)
64341022
AS
436 ;; force computation of the property by calling
437 ;; vc-BACKEND-registered explicitly
438 (if (and (vc-backend file)
439 (vc-call-backend (vc-backend file) 'registered file))
8aa81ea8 440 (vc-file-getprop file 'vc-name))))
e1c0c2d1 441
e0607aaa
SM
442(defun vc-checkout-model (backend files)
443 "Indicate how FILES are checked out.
0e0d9831 444
e0607aaa 445If FILES are not registered, this function always returns nil.
cb5af02a 446For registered files, the possible values are:
0e0d9831 447
e0607aaa 448 'implicit FILES are always writeable, and checked out `implicitly'
0e0d9831
GM
449 when the user saves the first changes to the file.
450
e0607aaa 451 'locking FILES are read-only if up-to-date; user must type
db8afaee 452 \\[vc-next-action] before editing. Strict locking
0e0d9831
GM
453 is assumed.
454
e0607aaa 455 'announce FILES are read-only if up-to-date; user must type
db8afaee 456 \\[vc-next-action] before editing. But other users
0e0d9831 457 may be editing at the same time."
e0607aaa 458 (vc-call-backend backend 'checkout-model files))
7064821c 459
8d2b9c1a
AS
460(defun vc-user-login-name (file)
461 "Return the name under which the user accesses the given FILE."
462 (or (and (eq (string-match tramp-file-name-regexp file) 0)
463 ;; tramp case: execute "whoami" via tramp
464 (let ((default-directory (file-name-directory file)))
465 (with-temp-buffer
466 (if (not (zerop (process-file "whoami" nil t)))
467 ;; fall through if "whoami" didn't work
468 nil
469 ;; remove trailing newline
470 (delete-region (1- (point-max)) (point-max))
471 (buffer-string)))))
472 ;; normal case
473 (user-login-name)
474 ;; if user-login-name is nil, return the UID as a string
475 (number-to-string (user-uid))))
0e0d9831
GM
476
477(defun vc-state (file)
478 "Return the version control state of FILE.
479
cb5af02a
AS
480If FILE is not registered, this function always returns nil.
481For registered files, the value returned is one of:
0e0d9831
GM
482
483 'up-to-date The working file is unmodified with respect to the
484 latest version on the current branch, and not locked.
485
486 'edited The working file has been edited by the user. If
487 locking is used for the file, this state means that
488 the current version is locked by the calling user.
489
490 USER The current version of the working file is locked by
491 some other USER (a string).
f8b72742 492
3702367b 493 'needs-update The file has not been edited by the user, but there is
0e0d9831
GM
494 a more recent version on the current branch stored
495 in the master file.
496
497 'needs-merge The file has been edited by the user, and there is also
498 a more recent version on the current branch stored in
499 the master file. This state can only occur if locking
500 is not used for the file.
501
fae00181 502 'unlocked-changes The working version of the file is not locked,
0e0d9831
GM
503 but the working file has been changed with respect
504 to that version. This state can only occur for files
505 with locking; it represents an erroneous condition that
506 should be resolved by the user (vc-next-action will
fae00181
ER
507 prompt the user to do it).
508
509 'added Scheduled to go into the repository on the next commit.
14f26054 510 Often represented by vc-working-revision = \"0\" in VCSes
722f037f
ER
511 with monotonic IDs like Subversion and Mercurial.
512
484c1b1f 513 'removed Scheduled to be deleted from the repository on next commit.
527b313d 514
7fbb4797 515 'conflict The file contains conflicts as the result of a merge.
329a656e
JB
516 For now the conflicts are text conflicts. In the
517 future this might be extended to deal with metadata
7fbb4797
DN
518 conflicts too.
519
329a656e 520 'missing The file is not present in the file system, but the VC
dd0d723c
DN
521 system still tracks it.
522
4903369a 523 'ignored The file showed up in a dir-status listing with a flag
722f037f 524 indicating the version-control system is ignoring it,
527b313d
SS
525 Note: This property is not set reliably (some VCSes
526 don't have useful directory-status commands) so assume
722f037f 527 that any file with vc-state nil might be ignorable
527b313d 528 without VC knowing it.
722f037f 529
3702367b 530 'unregistered The file is not under version control.
722f037f 531
527b313d 532A return of nil from this function means we have no information on the
d4e772c4 533status of this file."
a970a27e
ER
534 ;; Note: in Emacs 22 and older, return of nil meant the file was
535 ;; unregistered. This is potentially a source of
536 ;; backward-compatibility bugs.
fae00181 537
2a3897f5 538 ;; FIXME: New (sub)states needed (?):
2a3897f5 539 ;; - `copied' and `moved' (might be handled by `removed' and `added')
0e0d9831 540 (or (vc-file-getprop file 'vc-state)
a749e19d
SM
541 (when (> (length file) 0)
542 (let ((backend (vc-backend file)))
543 (when backend
544 (vc-file-setprop
545 file 'vc-state
546 (vc-call-backend backend 'state-heuristic file)))))))
0e0d9831
GM
547
548(defsubst vc-up-to-date-p (file)
549 "Convenience function that checks whether `vc-state' of FILE is `up-to-date'."
550 (eq (vc-state file) 'up-to-date))
551
552(defun vc-default-state-heuristic (backend file)
d4e772c4 553 "Default implementation of vc-BACKEND-state-heuristic.
5eb2b516
DL
554It simply calls the real state computation function `vc-BACKEND-state'
555and does not employ any heuristic at all."
0e0d9831 556 (vc-call-backend backend 'state file))
1efcbf46 557
e767004f
AS
558(defun vc-workfile-unchanged-p (file)
559 "Return non-nil if FILE has not changed since the last checkout."
560 (let ((checkout-time (vc-file-getprop file 'vc-checkout-time))
561 (lastmod (nth 5 (file-attributes file))))
04e77778
AS
562 (if (and checkout-time
563 ;; Tramp and Ange-FTP return this when they don't know the time.
564 (not (equal lastmod '(0 0))))
e767004f
AS
565 (equal checkout-time lastmod)
566 (let ((unchanged (vc-call workfile-unchanged-p file)))
567 (vc-file-setprop file 'vc-checkout-time (if unchanged lastmod 0))
568 unchanged))))
569
570(defun vc-default-workfile-unchanged-p (backend file)
571 "Check if FILE is unchanged by diffing against the master version.
572Return non-nil if FILE is unchanged."
f8836381 573 (zerop (condition-case err
4392edab
AS
574 ;; If the implementation supports it, let the output
575 ;; go to *vc*, not *vc-diff*, since this is an internal call.
a749e19d 576 (vc-call-backend backend 'diff (list file) nil nil "*vc*")
f8836381
AS
577 (wrong-number-of-arguments
578 ;; If this error came from the above call to vc-BACKEND-diff,
579 ;; try again without the optional buffer argument (for
580 ;; backward compatibility). Otherwise, resignal.
581 (if (or (not (eq (cadr err)
582 (indirect-function
a749e19d 583 (vc-find-backend-function backend 'diff))))
0d2ce4ef
JB
584 (not (eq (caddr err) 4)))
585 (signal (car err) (cdr err))
a749e19d 586 (vc-call-backend backend 'diff (list file)))))))
e767004f 587
ac3f4c6f 588(defun vc-working-revision (file)
e4d26892 589 "Return the repository version from which FILE was checked out.
cb5af02a 590If FILE is not registered, this function always returns nil."
ac3f4c6f 591 (or (vc-file-getprop file 'vc-working-revision)
a749e19d
SM
592 (let ((backend (vc-backend file)))
593 (when backend
594 (vc-file-setprop file 'vc-working-revision
595 (vc-call-backend backend 'working-revision file))))))
b5446276 596
6e5d0e9e
SM
597;; Backward compatibility.
598(define-obsolete-function-alias
599 'vc-workfile-version 'vc-working-revision "23.1")
9b7b3814
DN
600(define-obsolete-function-alias
601 'vc-previous-version 'vc-previous-revision "23.1")
6e5d0e9e
SM
602(defun vc-default-working-revision (backend file)
603 (message
604 "`working-revision' not found: using the old `workfile-version' instead")
605 (vc-call-backend backend 'workfile-version file))
f2ee4191 606
0e0d9831
GM
607(defun vc-default-registered (backend file)
608 "Check if FILE is registered in BACKEND using vc-BACKEND-master-templates."
609 (let ((sym (vc-make-backend-sym backend 'master-templates)))
610 (unless (get backend 'vc-templates-grabbed)
611 (put backend 'vc-templates-grabbed t)
612 (set sym (append (delq nil
613 (mapcar
614 (lambda (template)
615 (and (consp template)
616 (eq (cdr template) backend)
617 (car template)))
3756d481
AS
618 (with-no-warnings
619 vc-master-templates)))
0e0d9831
GM
620 (symbol-value sym))))
621 (let ((result (vc-check-master-templates file (symbol-value sym))))
622 (if (stringp result)
623 (vc-file-setprop file 'vc-name result)
624 nil)))) ; Not registered
625
626(defun vc-possible-master (s dirname basename)
627 (cond
628 ((stringp s) (format s dirname basename))
629 ((functionp s)
630 ;; The template is a function to invoke. If the
631 ;; function returns non-nil, that means it has found a
632 ;; master. For backward compatibility, we also handle
633 ;; the case that the function throws a 'found atom
634 ;; and a pair (cons MASTER-FILE BACKEND).
635 (let ((result (catch 'found (funcall s dirname basename))))
636 (if (consp result) (car result) result)))))
637
638(defun vc-check-master-templates (file templates)
cb5af02a 639 "Return non-nil if there is a master corresponding to FILE.
0e0d9831
GM
640
641TEMPLATES is a list of strings or functions. If an element is a
642string, it must be a control string as required by `format', with two
643string placeholders, such as \"%sRCS/%s,v\". The directory part of
644FILE is substituted for the first placeholder, the basename of FILE
645for the second. If a file with the resulting name exists, it is taken
646as the master of FILE, and returned.
647
648If an element of TEMPLATES is a function, it is called with the
649directory part and the basename of FILE as arguments. It should
650return non-nil if it finds a master; that value is then returned by
651this function."
652 (let ((dirname (or (file-name-directory file) ""))
653 (basename (file-name-nondirectory file)))
654 (catch 'found
5eb2b516 655 (mapcar
0e0d9831
GM
656 (lambda (s)
657 (let ((trial (vc-possible-master s dirname basename)))
b5446276
DN
658 (when (and trial (file-exists-p trial)
659 ;; Make sure the file we found with name
660 ;; TRIAL is not the source file itself.
661 ;; That can happen with RCS-style names if
662 ;; the file name is truncated (e.g. to 14
663 ;; chars). See if either directory or
664 ;; attributes differ.
665 (or (not (string= dirname
666 (file-name-directory trial)))
667 (not (equal (file-attributes file)
668 (file-attributes trial)))))
0e0d9831
GM
669 (throw 'found trial))))
670 templates))))
f2ee4191 671
c844616c 672(defun vc-toggle-read-only (&optional verbose)
c43e436c 673 "Change read-only status of current buffer, perhaps via version control.
db8afaee 674
c43e436c 675If the buffer is visiting a file registered with version control,
d4e772c4
JB
676throw an error, because this is not a safe or really meaningful operation
677on any version-control system newer than RCS.
25e94278
ER
678
679Otherwise, just change the read-only flag of the buffer.
680
681If you bind this function to \\[toggle-read-only], then Emacs
682will properly intercept all attempts to toggle the read-only flag
683on version-controlled buffer."
c844616c 684 (interactive "P")
25e94278
ER
685 (if (vc-backend buffer-file-name)
686 (error "Toggling the readability of a version controlled file is likely to wreak havoc.")
594722a8
ER
687 (toggle-read-only)))
688
e896a9e1 689(defun vc-default-make-version-backups-p (backend file)
cb5af02a 690 "Return non-nil if unmodified versions should be backed up locally.
9aa10a43 691The default is to switch off this feature."
d445a975
AS
692 nil)
693
e896a9e1
AS
694(defun vc-version-backup-file-name (file &optional rev manual regexp)
695 "Return a backup file name for REV or the current version of FILE.
696If MANUAL is non-nil it means that a name for backups created by
697the user should be returned; if REGEXP is non-nil that means to return
698a regexp for matching all such backup files, regardless of the version."
e3f955b6
AS
699 (if regexp
700 (concat (regexp-quote (file-name-nondirectory file))
d4c813e9 701 "\\.~.+" (unless manual "\\.") "~")
f8b72742 702 (expand-file-name (concat (file-name-nondirectory file)
d4c813e9 703 ".~" (subst-char-in-string
ac3f4c6f 704 ?/ ?_ (or rev (vc-working-revision file)))
e3f955b6
AS
705 (unless manual ".") "~")
706 (file-name-directory file))))
e896a9e1
AS
707
708(defun vc-delete-automatic-version-backups (file)
709 "Delete all existing automatic version backups for FILE."
d455f4f7 710 (condition-case nil
a549ce70 711 (mapc
d455f4f7 712 'delete-file
79e954d0 713 (directory-files (or (file-name-directory file) default-directory) t
d455f4f7
SM
714 (vc-version-backup-file-name file nil nil t)))
715 ;; Don't fail when the directory doesn't exist.
716 (file-error nil)))
e896a9e1
AS
717
718(defun vc-make-version-backup (file)
719 "Make a backup copy of FILE, which is assumed in sync with the repository.
720Before doing that, check if there are any old backups and get rid of them."
48b15d3f 721 (unless (and (fboundp 'msdos-long-file-names)
ee9be3de 722 (not (with-no-warnings (msdos-long-file-names))))
48b15d3f 723 (vc-delete-automatic-version-backups file)
27707243
AS
724 (condition-case nil
725 (copy-file file (vc-version-backup-file-name file)
726 nil 'keep-date)
727 ;; It's ok if it doesn't work (e.g. directory not writable),
728 ;; since this is just for efficiency.
bf247b6e 729 (file-error
27707243
AS
730 (message
731 (concat "Warning: Cannot make version backup; "
732 "diff/revert therefore not local"))))))
d445a975
AS
733
734(defun vc-before-save ()
735 "Function to be called by `basic-save-buffer' (in files.el)."
736 ;; If the file on disk is still in sync with the repository,
737 ;; and version backups should be made, copy the file to
738 ;; another name. This enables local diffs and local reverting.
e0607aaa
SM
739 (let ((file buffer-file-name)
740 backend)
f42af255 741 (ignore-errors ;Be careful not to prevent saving the file.
e0607aaa 742 (and (setq backend (vc-backend file))
f42af255 743 (vc-up-to-date-p file)
70e2f6c7 744 (eq (vc-checkout-model backend (list file)) 'implicit)
a749e19d 745 (vc-call-backend backend 'make-version-backups-p file)
f42af255 746 (vc-make-version-backup file)))))
d445a975 747
74d0991f 748(declare-function vc-dir-resynch-file "vc-dir" (&optional fname))
004a00f4 749
e66eac08 750(defun vc-after-save ()
0e0d9831 751 "Function to be called by `basic-save-buffer' (in files.el)."
5eb2b516 752 ;; If the file in the current buffer is under version control,
0e0d9831
GM
753 ;; up-to-date, and locking is not used for the file, set
754 ;; the state to 'edited and redisplay the mode line.
e0607aaa
SM
755 (let* ((file buffer-file-name)
756 (backend (vc-backend file)))
757 (and backend
b23a2306
AS
758 (or (and (equal (vc-file-getprop file 'vc-checkout-time)
759 (nth 5 (file-attributes file)))
760 ;; File has been saved in the same second in which
761 ;; it was checked out. Clear the checkout-time
762 ;; to avoid confusion.
763 (vc-file-setprop file 'vc-checkout-time nil))
764 t)
0e0d9831 765 (vc-up-to-date-p file)
70e2f6c7 766 (eq (vc-checkout-model backend (list file)) 'implicit)
0e0d9831
GM
767 (vc-file-setprop file 'vc-state 'edited)
768 (vc-mode-line file)
e02d8ae7
DN
769 ;; Try to avoid unnecessary work, a *vc-dir* buffer is only
770 ;; present if this is true.
771 (when (memq 'vc-dir-resynch-file after-save-hook)
772 (vc-dir-resynch-file file)))))
04446ed0 773
e2247dc8
SM
774(defvar vc-menu-entry
775 '(menu-item "Version Control" vc-menu-map
776 :filter vc-menu-map-filter))
777
778(when (boundp 'menu-bar-tools-menu)
779 ;; We do not need to worry here about the placement of this entry
780 ;; because menu-bar.el has already created the proper spot for us
781 ;; and this will simply use it.
782 (define-key menu-bar-tools-menu [vc] vc-menu-entry))
783
5719a098
SM
784(defconst vc-mode-line-map
785 (let ((map (make-sparse-keymap)))
e2247dc8 786 (define-key map [mode-line down-mouse-1] vc-menu-entry)
5719a098
SM
787 map))
788
0e0d9831 789(defun vc-mode-line (file)
7bc2b98b 790 "Set `vc-mode' to display type of version control for FILE.
594722a8 791The value is set in the current buffer, which should be the buffer
0e0d9831 792visiting FILE."
67c6f446 793 (interactive (list buffer-file-name))
5719a098 794 (let ((backend (vc-backend file)))
5232a436
SM
795 (if (not backend)
796 (setq vc-mode nil)
a749e19d 797 (let* ((ml-string (vc-call-backend backend 'mode-line-string file))
5719a098
SM
798 (ml-echo (get-text-property 0 'help-echo ml-string)))
799 (setq vc-mode
800 (concat
801 " "
802 (if (null vc-display-status)
803 (symbol-name backend)
804 (propertize
805 ml-string
806 'mouse-face 'mode-line-highlight
527b313d 807 'help-echo
5719a098
SM
808 (concat (or ml-echo
809 (format "File under the %s version control system"
810 backend))
811 "\nmouse-1: Version Control menu")
812 'local-map vc-mode-line-map)))))
5232a436
SM
813 ;; If the file is locked by some other user, make
814 ;; the buffer read-only. Like this, even root
815 ;; cannot modify a file that someone else has locked.
816 (and (equal file buffer-file-name)
817 (stringp (vc-state file))
818 (setq buffer-read-only t))
819 ;; If the user is root, and the file is not owner-writable,
820 ;; then pretend that we can't write it
821 ;; even though we can (because root can write anything).
e02d8ae7
DN
822 ;; This way, even root cannot modify a file that isn't locked.
823 (and (equal file buffer-file-name)
824 (not buffer-read-only)
5232a436
SM
825 (zerop (user-real-uid))
826 (zerop (logand (file-modes buffer-file-name) 128))
827 (setq buffer-read-only t)))
828 (force-mode-line-update)
829 backend))
0e0d9831
GM
830
831(defun vc-default-mode-line-string (backend file)
832 "Return string for placement in modeline by `vc-mode-line' for FILE.
833Format:
834
835 \"BACKEND-REV\" if the file is up-to-date
836 \"BACKEND:REV\" if the file is edited (or locked by the calling user)
837 \"BACKEND:LOCKER:REV\" if the file is locked by somebody else
0e0d9831
GM
838
839This function assumes that the file is registered."
840 (setq backend (symbol-name backend))
841 (let ((state (vc-state file))
82c4728d 842 (state-echo nil)
ac3f4c6f 843 (rev (vc-working-revision file)))
82c4728d
DN
844 (propertize
845 (cond ((or (eq state 'up-to-date)
3702367b 846 (eq state 'needs-update))
82c4728d
DN
847 (setq state-echo "Up to date file")
848 (concat backend "-" rev))
849 ((stringp state)
850 (setq state-echo (concat "File locked by" state))
851 (concat backend ":" state ":" rev))
45b24b4d
SM
852 ((eq state 'added)
853 (setq state-echo "Locally added file")
854 (concat backend "@" rev))
7fbb4797
DN
855 ((eq state 'conflict)
856 (setq state-echo "File contains conflicts after the last merge")
857 (concat backend "!" rev))
a58b57e2
DN
858 ((eq state 'removed)
859 (setq state-echo "File removed from the VC system")
860 (concat backend "!" rev))
861 ((eq state 'missing)
862 (setq state-echo "File tracked by the VC system, but missing from the file system")
5bad3140 863 (concat backend "?" rev))
82c4728d
DN
864 (t
865 ;; Not just for the 'edited state, but also a fallback
866 ;; for all other states. Think about different symbols
3702367b 867 ;; for 'needs-update and 'needs-merge.
3a12f9f8 868 (setq state-echo "Locally modified file")
82c4728d 869 (concat backend ":" rev)))
33e0847d 870 'help-echo (concat state-echo " under the " backend
3a12f9f8 871 " version control system"))))
f2ee4191 872
a3a39848 873(defun vc-follow-link ()
0e0d9831
GM
874 "If current buffer visits a symbolic link, visit the real file.
875If the real file is already visited in another buffer, make that buffer
876current, and kill the buffer that visits the link."
566f2169 877 (let* ((truename (abbreviate-file-name (file-chase-links buffer-file-name)))
e7f5ddc2
RS
878 (true-buffer (find-buffer-visiting truename))
879 (this-buffer (current-buffer)))
880 (if (eq true-buffer this-buffer)
881 (progn
d8221951 882 (kill-buffer this-buffer)
e7f5ddc2
RS
883 ;; In principle, we could do something like set-visited-file-name.
884 ;; However, it can't be exactly the same as set-visited-file-name.
885 ;; I'm not going to work out the details right now. -- rms.
d8221951 886 (set-buffer (find-file-noselect truename)))
e7f5ddc2
RS
887 (set-buffer true-buffer)
888 (kill-buffer this-buffer))))
a3a39848 889
b8d1db77
SM
890(defun vc-default-find-file-hook (backend)
891 nil)
892
594722a8 893(defun vc-find-file-hook ()
be4d6a6f 894 "Function for `find-file-hook' activating VC mode if appropriate."
18c8a18e
PE
895 ;; Recompute whether file is version controlled,
896 ;; if user has killed the buffer and revisited.
060a1456
AS
897 (if vc-mode
898 (setq vc-mode nil))
0e0d9831 899 (when buffer-file-name
f2ee4191 900 (vc-file-clearprops buffer-file-name)
c8d4f1a0 901 (add-hook 'mode-line-hook 'vc-mode-line nil t)
f2ee4191 902 (cond
fc8b8d0f 903 ((with-demoted-errors (vc-backend buffer-file-name))
0bfb74a9 904 ;; Compute the state and put it in the modeline.
f2ee4191 905 (vc-mode-line buffer-file-name)
0bfb74a9
SM
906 (unless vc-make-backup-files
907 ;; Use this variable, not make-backup-files,
908 ;; because this is for things that depend on the file name.
b8d1db77
SM
909 (set (make-local-variable 'backup-inhibited) t))
910 ;; Let the backend setup any buffer-local things he needs.
911 (vc-call-backend (vc-backend buffer-file-name) 'find-file-hook))
4d11f532
SM
912 ((let ((link-type (and (file-symlink-p buffer-file-name)
913 (vc-backend (file-chase-links buffer-file-name)))))
0bfb74a9
SM
914 (cond ((not link-type) nil) ;Nothing to do.
915 ((eq vc-follow-symlinks nil)
916 (message
b8063212 917 "Warning: symbolic link to %s-controlled source file" link-type))
0bfb74a9
SM
918 ((or (not (eq vc-follow-symlinks 'ask))
919 ;; If we already visited this file by following
920 ;; the link, don't ask again if we try to visit
921 ;; it again. GUD does that, and repeated questions
922 ;; are painful.
923 (get-file-buffer
924 (abbreviate-file-name
925 (file-chase-links buffer-file-name))))
926
927 (vc-follow-link)
928 (message "Followed link to %s" buffer-file-name)
929 (vc-find-file-hook))
930 (t
931 (if (yes-or-no-p (format
b8063212 932 "Symbolic link to %s-controlled source file; follow link? " link-type))
0bfb74a9
SM
933 (progn (vc-follow-link)
934 (message "Followed link to %s" buffer-file-name)
935 (vc-find-file-hook))
936 (message
b8063212 937 "Warning: editing through the link bypasses version control")
0bfb74a9 938 ))))))))
594722a8 939
be4d6a6f 940(add-hook 'find-file-hook 'vc-find-file-hook)
594722a8 941
14fef9de 942;; more hooks, this time for file-not-found
594722a8 943(defun vc-file-not-found-hook ()
0e0d9831
GM
944 "When file is not found, try to check it out from version control.
945Returns t if checkout was successful, nil otherwise.
d3d558a9 946Used in `find-file-not-found-functions'."
5f42a1d4
RS
947 ;; When a file does not exist, ignore cached info about it
948 ;; from a previous visit.
949 (vc-file-clearprops buffer-file-name)
4a330ab7 950 (let ((backend (vc-backend buffer-file-name)))
b5446276 951 (when backend (vc-call-backend backend 'find-file-not-found-hook))))
4a330ab7
SM
952
953(defun vc-default-find-file-not-found-hook (backend)
a3773730
SM
954 ;; This used to do what vc-rcs-find-file-not-found-hook does, but it only
955 ;; really makes sense for RCS. For other backends, better not do anything.
956 nil)
594722a8 957
3756d481 958(add-hook 'find-file-not-found-functions 'vc-file-not-found-hook)
594722a8 959
f2ee4191 960(defun vc-kill-buffer-hook ()
0e0d9831 961 "Discard VC info about a file when we kill its buffer."
b5446276 962 (when buffer-file-name (vc-file-clearprops buffer-file-name)))
f2ee4191 963
cd32d5d1 964(add-hook 'kill-buffer-hook 'vc-kill-buffer-hook)
f2ee4191 965
14fef9de
SM
966;; Now arrange for (autoloaded) bindings of the main package.
967;; Bindings for this have to go in the global map, as we'll often
968;; want to call them from random buffers.
969
970;; Autoloading works fine, but it prevents shortcuts from appearing
971;; in the menu because they don't exist yet when the menu is built.
972;; (autoload 'vc-prefix-map "vc" nil nil 'keymap)
973(defvar vc-prefix-map
974 (let ((map (make-sparse-keymap)))
975 (define-key map "a" 'vc-update-change-log)
976 (define-key map "b" 'vc-switch-backend)
e4d26892 977 (define-key map "c" 'vc-rollback)
e1aec6fb 978 (define-key map "d" 'vc-dir)
14fef9de
SM
979 (define-key map "g" 'vc-annotate)
980 (define-key map "h" 'vc-insert-headers)
981 (define-key map "i" 'vc-register)
982 (define-key map "l" 'vc-print-log)
983 (define-key map "m" 'vc-merge)
370fded4
ER
984 (define-key map "r" 'vc-retrieve-tag)
985 (define-key map "s" 'vc-create-tag)
e4d26892 986 (define-key map "u" 'vc-revert)
14fef9de 987 (define-key map "v" 'vc-next-action)
e4d26892 988 (define-key map "+" 'vc-update)
14fef9de 989 (define-key map "=" 'vc-diff)
0a0ca7f1 990 (define-key map "~" 'vc-revision-other-window)
14fef9de
SM
991 map))
992(fset 'vc-prefix-map vc-prefix-map)
c1fdf758 993(define-key global-map "\C-xv" 'vc-prefix-map)
624c0e9d 994
e2247dc8
SM
995(defvar vc-menu-map
996 (let ((map (make-sparse-keymap "Version Control")))
997 ;;(define-key map [show-files]
998 ;; '("Show Files under VC" . (vc-directory t)))
370fded4
ER
999 (define-key map [vc-retrieve-tag]
1000 '(menu-item "Retrieve Tag" vc-retrieve-tag
1001 :help "Retrieve tagged version or branch"))
1002 (define-key map [vc-create-tag]
1003 '(menu-item "Create Tag" vc-create-tag
1004 :help "Create version tag"))
e2247dc8 1005 (define-key map [separator1] '("----"))
6dbb5c76 1006 (define-key map [vc-annotate]
40fabc71
DN
1007 '(menu-item "Annotate" vc-annotate
1008 :help "Display the edit history of the current file using colors"))
6dbb5c76 1009 (define-key map [vc-rename-file]
40fabc71
DN
1010 '(menu-item "Rename File" vc-rename-file
1011 :help "Rename file"))
0a0ca7f1 1012 (define-key map [vc-revision-other-window]
40fabc71
DN
1013 '(menu-item "Show Other Version" vc-revision-other-window
1014 :help "Visit another version of the current file in another window"))
6dbb5c76 1015 (define-key map [vc-diff]
40fabc71
DN
1016 '(menu-item "Compare with Base Version" vc-diff
1017 :help "Compare file set with the base version"))
e2247dc8 1018 (define-key map [vc-update-change-log]
40fabc71
DN
1019 '(menu-item "Update ChangeLog" vc-update-change-log
1020 :help "Find change log file and add entries from recent version control logs"))
6dbb5c76 1021 (define-key map [vc-print-log]
40fabc71
DN
1022 '(menu-item "Show History" vc-print-log
1023 :help "List the change log of the current file set in a window"))
e2247dc8
SM
1024 (define-key map [separator2] '("----"))
1025 (define-key map [vc-insert-header]
40fabc71
DN
1026 '(menu-item "Insert Header" vc-insert-headers
1027 :help "Insert headers into a file for use with a version control system.
1028"))
6dbb5c76 1029 (define-key map [undo]
40fabc71
DN
1030 '(menu-item "Undo Last Check-In" vc-rollback
1031 :help "Remove the most recent changeset committed to the repository"))
e2247dc8 1032 (define-key map [vc-revert]
40fabc71
DN
1033 '(menu-item "Revert to Base Version" vc-revert
1034 :help "Revert working copies of the selected file set to their repository contents"))
e2247dc8 1035 (define-key map [vc-update]
40fabc71
DN
1036 '(menu-item "Update to Latest Version" vc-update
1037 :help "Update the current fileset's files to their tip revisions"))
6dbb5c76 1038 (define-key map [vc-next-action]
40fabc71
DN
1039 '(menu-item "Check In/Out" vc-next-action
1040 :help "Do the next logical version control operation on the current fileset"))
6dbb5c76 1041 (define-key map [vc-register]
40fabc71
DN
1042 '(menu-item "Register" vc-register
1043 :help "Register file set into a version control system"))
e1aec6fb
SM
1044 (define-key map [vc-dir]
1045 '(menu-item "VC Dir" vc-dir
7fbb4797 1046 :help "Show the VC status of files in a directory"))
e2247dc8
SM
1047 map))
1048
1049(defalias 'vc-menu-map vc-menu-map)
1050
aafb0703
GM
1051(declare-function vc-responsible-backend "vc" (file &optional register))
1052
e2247dc8
SM
1053(defun vc-menu-map-filter (orig-binding)
1054 (if (and (symbolp orig-binding) (fboundp orig-binding))
1055 (setq orig-binding (indirect-function orig-binding)))
1056 (let ((ext-binding
f3d57a2c 1057 (when vc-mode
aafb0703 1058 (vc-call-backend
f3d57a2c
DN
1059 (if buffer-file-name
1060 (vc-backend buffer-file-name)
1061 (vc-responsible-backend default-directory))
1062 'extra-menu))))
e2247dc8
SM
1063 ;; Give the VC backend a chance to add menu entries
1064 ;; specific for that backend.
1065 (if (null ext-binding)
98481bad 1066 orig-binding
e2247dc8
SM
1067 (append orig-binding
1068 '((ext-menu-separator "---"))
98481bad 1069 ext-binding))))
738efc8e 1070
cb223bba
DN
1071(defun vc-default-extra-menu (backend)
1072 nil)
1073
14fef9de
SM
1074;; These are not correct and it's not currently clear how doing it
1075;; better (with more complicated expressions) might slow things down
1076;; on older systems.
1077
1078;;(put 'vc-rename-file 'menu-enable 'vc-mode)
1079;;(put 'vc-annotate 'menu-enable '(eq (vc-buffer-backend) 'CVS))
0a0ca7f1 1080;;(put 'vc-revision-other-window 'menu-enable 'vc-mode)
14fef9de
SM
1081;;(put 'vc-diff 'menu-enable 'vc-mode)
1082;;(put 'vc-update-change-log 'menu-enable
1083;; '(member (vc-buffer-backend) '(RCS CVS)))
1084;;(put 'vc-print-log 'menu-enable 'vc-mode)
e4d26892
ER
1085;;(put 'vc-rollback 'menu-enable 'vc-mode)
1086;;(put 'vc-revert 'menu-enable 'vc-mode)
14fef9de
SM
1087;;(put 'vc-insert-headers 'menu-enable 'vc-mode)
1088;;(put 'vc-next-action 'menu-enable 'vc-mode)
1089;;(put 'vc-register 'menu-enable '(and buffer-file-name (not vc-mode)))
594722a8 1090
594722a8
ER
1091(provide 'vc-hooks)
1092
ce9f8ffb 1093;; arch-tag: 2e5a6fa7-1d30-48e2-8bd0-e3d335f04f32
594722a8 1094;;; vc-hooks.el ends here