;;; vc-hooks.el --- resident support for version-control
;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-;; 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: Andre Spiegel <spiegel@gnu.org>
(defcustom vc-ignore-dir-regexp
;; Stop SMB, automounter, AFS, and DFS host lookups.
- "\\`\\(?:[\\/][\\/]\\|/\\(?:net\\|afs\\|\\.\\\.\\.\\)/\\)\\'"
+ locate-dominating-stop-dir-regexp
"Regexp matching directory names that are not under VC's control.
The default regexp prevents fruitless and time-consuming attempts
to determine the VC status in directories in which filenames are
(funcall vc-mistrust-permissions
(vc-backend-subdirectory-name file)))))
-(defcustom vc-stay-local t
+(defcustom vc-stay-local 'only-file
"Non-nil means use local operations when possible for remote repositories.
This avoids slow queries over the network and instead uses heuristics
and past information to determine the current status of a file.
+If value is the symbol `only-file' `vc-dir' will connect to the
+server, but heuristics will be used to determine the status for
+all other VC operations.
+
The value can also be a regular expression or list of regular
expressions to match against the host name of a repository; then VC
only stays local for hosts that match it. Alternatively, the value
can be a list of regular expressions where the first element is the
symbol `except'; then VC always stays local except for hosts matched
by these regular expressions."
- :type '(choice (const :tag "Always stay local" t)
+ :type '(choice
+ (const :tag "Always stay local" t)
+ (const :tag "Only for file operations" only-file)
(const :tag "Don't stay local" nil)
(list :format "\nExamine hostname and %v" :tag "Examine hostname ..."
(set :format "%v" :inline t (const :format "%t" :tag "don't" except))
(regexp :format " stay local,\n%t: %v" :tag "if it matches")
(repeat :format "%v%i\n" :inline t (regexp :tag "or"))))
- :version "22.1"
+ :version "23.1"
:group 'vc)
(defun vc-stay-local-p (file)
(set-buffer-modified-p nil)
t))
-(defun vc-find-root (file witness &optional invert)
+(defun vc-find-root (file witness)
"Find the root of a checked out project.
The function walks up the directory tree from FILE looking for WITNESS.
-If WITNESS if not found, return nil, otherwise return the root.
-Optional arg INVERT non-nil reverses the sense of the check;
-the root is the last directory for which WITNESS *is* found."
- ;; Represent /home/luser/foo as ~/foo so that we don't try to look for
- ;; witnesses in /home or in /.
- (setq file (abbreviate-file-name file))
- (let ((root nil)
- (prev-file file)
- ;; `user' is not initialized outside the loop because
- ;; `file' may not exist, so we may have to walk up part of the
- ;; hierarchy before we find the "initial UID".
- (user nil)
- try)
- (while (not (or root
- (null file)
- ;; As a heuristic, we stop looking up the hierarchy of
- ;; directories as soon as we find a directory belonging
- ;; to another user. This should save us from looking in
- ;; things like /net and /afs. This assumes that all the
- ;; files inside a project belong to the same user.
- (let ((prev-user user))
- (setq user (nth 2 (file-attributes file)))
- (and prev-user (not (equal user prev-user))))
- (string-match vc-ignore-dir-regexp file)))
- (setq try (file-exists-p (expand-file-name witness file)))
- (cond ((and invert (not try)) (setq root prev-file))
- ((and (not invert) try) (setq root file))
- ((equal file (setq prev-file file
- file (file-name-directory
- (directory-file-name file))))
- (setq file nil))))
- ;; Handle the case where ~/WITNESS exists and the original FILE is "~".
- ;; (This occurs, for example, when placing dotfiles under RCS.)
- (when (and (not root) invert prev-file)
- (setq root prev-file))
- root))
+If WITNESS if not found, return nil, otherwise return the root."
+ (let ((locate-dominating-stop-dir-regexp
+ (or vc-ignore-dir-regexp locate-dominating-stop-dir-regexp)))
+ (locate-dominating-file file witness)))
;; Access functions to file properties
;; (Properties should be _set_ using vc-file-setprop, but
backend is tried first."
(let (handler)
(cond
- ((and (file-name-directory file) (string-match vc-ignore-dir-regexp (file-name-directory file)))
+ ((and (file-name-directory file)
+ (string-match vc-ignore-dir-regexp (file-name-directory file)))
nil)
((and (boundp 'file-name-handler-alist)
(setq handler (find-file-name-handler file 'vc-registered)))
If FILES are not registered, this function always returns nil.
For registered files, the possible values are:
- 'implicit FILES are always writeable, and checked out `implicitly'
+ 'implicit FILES are always writable, and checked out `implicitly'
when the user saves the first changes to the file.
'locking FILES are read-only if up-to-date; user must type
"Return non-nil if FILE has not changed since the last checkout."
(let ((checkout-time (vc-file-getprop file 'vc-checkout-time))
(lastmod (nth 5 (file-attributes file))))
+ ;; This is a shortcut for determining when the workfile is
+ ;; unchanged. It can fail under some circumstances; see the
+ ;; discussion in bug#694.
(if (and checkout-time
- ;; Tramp and Ange-FTP return this when they don't know the time.
- (not (equal lastmod '(0 0))))
- (equal checkout-time lastmod)
+ ;; Tramp and Ange-FTP return this when they don't know the time.
+ (not (equal lastmod '(0 0))))
+ (equal checkout-time lastmod)
(let ((unchanged (vc-call workfile-unchanged-p file)))
- (vc-file-setprop file 'vc-checkout-time (if unchanged lastmod 0))
- unchanged))))
+ (vc-file-setprop file 'vc-checkout-time (if unchanged lastmod 0))
+ unchanged))))
(defun vc-default-workfile-unchanged-p (backend file)
"Check if FILE is unchanged by diffing against the master version.
;; Backward compatibility.
(define-obsolete-function-alias
'vc-workfile-version 'vc-working-revision "23.1")
-(define-obsolete-function-alias
- 'vc-previous-version 'vc-previous-revision "23.1")
(defun vc-default-working-revision (backend file)
(message
"`working-revision' not found: using the old `workfile-version' instead")
(vc-call-backend backend 'make-version-backups-p file)
(vc-make-version-backup file)))))
-(declare-function vc-dir-resynch-file "vc-dispatcher" (&optional fname))
+(declare-function vc-dir-resynch-file "vc-dir" (&optional fname))
(defun vc-after-save ()
"Function to be called by `basic-save-buffer' (in files.el)."
"If current buffer visits a symbolic link, visit the real file.
If the real file is already visited in another buffer, make that buffer
current, and kill the buffer that visits the link."
- (let* ((truename (abbreviate-file-name (file-chase-links buffer-file-name)))
- (true-buffer (find-buffer-visiting truename))
+ (let* ((true-buffer (find-buffer-visiting buffer-file-truename))
(this-buffer (current-buffer)))
(if (eq true-buffer this-buffer)
- (progn
+ (let ((truename buffer-file-truename))
(kill-buffer this-buffer)
;; In principle, we could do something like set-visited-file-name.
;; However, it can't be exactly the same as set-visited-file-name.
(set (make-local-variable 'backup-inhibited) t))
;; Let the backend setup any buffer-local things he needs.
(vc-call-backend (vc-backend buffer-file-name) 'find-file-hook))
- ((let ((link-type (and (file-symlink-p buffer-file-name)
- (vc-backend (file-chase-links buffer-file-name)))))
+ ((let ((link-type (and (not (equal buffer-file-name buffer-file-truename))
+ (vc-backend buffer-file-truename))))
(cond ((not link-type) nil) ;Nothing to do.
((eq vc-follow-symlinks nil)
(message
Used in `find-file-not-found-functions'."
;; When a file does not exist, ignore cached info about it
;; from a previous visit.
- (vc-file-clearprops buffer-file-name)
- (let ((backend (vc-backend buffer-file-name)))
- (when backend (vc-call-backend backend 'find-file-not-found-hook))))
+ ;; We check that `buffer-file-name' is non-nil. It should be always
+ ;; the case, but in conjunction with Tramp, it might be nil. M. Albinus.
+ (when buffer-file-name
+ (vc-file-clearprops buffer-file-name)
+ (let ((backend (vc-backend buffer-file-name)))
+ (when backend (vc-call-backend backend 'find-file-not-found-hook)))))
(defun vc-default-find-file-not-found-hook (backend)
;; This used to do what vc-rcs-find-file-not-found-hook does, but it only
(defun vc-default-extra-menu (backend)
nil)
-;; These are not correct and it's not currently clear how doing it
-;; better (with more complicated expressions) might slow things down
-;; on older systems.
-
-;;(put 'vc-rename-file 'menu-enable 'vc-mode)
-;;(put 'vc-annotate 'menu-enable '(eq (vc-buffer-backend) 'CVS))
-;;(put 'vc-revision-other-window 'menu-enable 'vc-mode)
-;;(put 'vc-diff 'menu-enable 'vc-mode)
-;;(put 'vc-update-change-log 'menu-enable
-;; '(member (vc-buffer-backend) '(RCS CVS)))
-;;(put 'vc-print-log 'menu-enable 'vc-mode)
-;;(put 'vc-rollback 'menu-enable 'vc-mode)
-;;(put 'vc-revert 'menu-enable 'vc-mode)
-;;(put 'vc-insert-headers 'menu-enable 'vc-mode)
-;;(put 'vc-next-action 'menu-enable 'vc-mode)
-;;(put 'vc-register 'menu-enable '(and buffer-file-name (not vc-mode)))
-
(provide 'vc-hooks)
;; arch-tag: 2e5a6fa7-1d30-48e2-8bd0-e3d335f04f32