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