summaryrefslogtreecommitdiff
path: root/lisp/vc-hooks.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/vc-hooks.el')
-rw-r--r--lisp/vc-hooks.el187
1 files changed, 112 insertions, 75 deletions
diff --git a/lisp/vc-hooks.el b/lisp/vc-hooks.el
index a47637d37ee..15238751679 100644
--- a/lisp/vc-hooks.el
+++ b/lisp/vc-hooks.el
@@ -62,35 +62,36 @@ interpreted as hostnames."
:type 'regexp
:group 'vc)
-(defcustom vc-handled-backends '(RCS CVS SVN SCCS Arch MCVS)
- ;; Arch and MCVS come last because they are per-tree rather than per-dir.
- "*List of version control backends for which VC will be used.
+(defcustom vc-handled-backends '(RCS CVS SVN SCCS BZR HG Arch MCVS)
+ ;; BZR, HG, Arch and MCVS come last because they are per-tree rather
+ ;; than per-dir.
+ "List of version control backends for which VC will be used.
Entries in this list will be tried in order to determine whether a
file is under that sort of version control.
Removing an entry from the list prevents VC from being activated
when visiting a file managed by that backend.
An empty list disables VC altogether."
:type '(repeat symbol)
- :version "21.1"
+ :version "23.1"
:group 'vc)
(defcustom vc-path
(if (file-directory-p "/usr/sccs")
'("/usr/sccs")
nil)
- "*List of extra directories to search for version control commands."
+ "List of extra directories to search for version control commands."
:type '(repeat directory)
:group 'vc)
(defcustom vc-make-backup-files nil
- "*If non-nil, backups of registered files are made as with other files.
+ "If non-nil, backups of registered files are made as with other files.
If nil (the default), files covered by version control don't get backups."
:type 'boolean
:group 'vc
:group 'backup)
(defcustom vc-follow-symlinks 'ask
- "*What to do if visiting a symbolic link to a file under version control.
+ "What to do if visiting a symbolic link to a file under version control.
Editing such a file through the link bypasses the version control system,
which is dangerous and probably not what you want.
@@ -104,26 +105,26 @@ visited and a warning displayed."
:group 'vc)
(defcustom vc-display-status t
- "*If non-nil, display revision number and lock status in modeline.
+ "If non-nil, display revision number and lock status in modeline.
Otherwise, not displayed."
:type 'boolean
:group 'vc)
(defcustom vc-consult-headers t
- "*If non-nil, identify work files by searching for version headers."
+ "If non-nil, identify work files by searching for version headers."
:type 'boolean
:group 'vc)
(defcustom vc-keep-workfiles t
- "*If non-nil, don't delete working files after registering changes.
+ "If non-nil, don't delete working files after registering changes.
If the back-end is CVS, workfiles are always kept, regardless of the
value of this flag."
:type 'boolean
:group 'vc)
(defcustom vc-mistrust-permissions nil
- "*If non-nil, don't assume permissions/ownership track version-control status.
+ "If non-nil, don't assume permissions/ownership track version-control status.
If nil, do rely on the permissions.
See also variable `vc-consult-headers'."
:type 'boolean
@@ -137,7 +138,7 @@ See also variable `vc-consult-headers'."
(vc-backend-subdirectory-name file)))))
(defcustom vc-stay-local t
- "*Non-nil means use local operations when possible for remote repositories.
+ "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.
@@ -158,32 +159,36 @@ by these regular expressions."
(defun vc-stay-local-p (file)
"Return non-nil if VC should stay local when handling FILE.
-This uses the `repository-hostname' backend operation."
- (let* ((backend (vc-backend file))
- (sym (vc-make-backend-sym backend 'stay-local))
- (stay-local (if (boundp sym) (symbol-value sym) t)))
- (if (eq stay-local t) (setq stay-local vc-stay-local))
- (if (symbolp stay-local) stay-local
- (let ((dirname (if (file-directory-p file)
- (directory-file-name file)
- (file-name-directory file))))
- (eq 'yes
- (or (vc-file-getprop dirname 'vc-stay-local-p)
- (vc-file-setprop
- dirname 'vc-stay-local-p
- (let ((hostname (vc-call-backend
- backend 'repository-hostname dirname)))
- (if (not hostname)
- 'no
- (let ((default t))
- (if (eq (car-safe stay-local) 'except)
- (setq default nil stay-local (cdr stay-local)))
- (when (consp stay-local)
- (setq stay-local
- (mapconcat 'identity stay-local "\\|")))
- (if (if (string-match stay-local hostname)
- default (not default))
- 'yes 'no)))))))))))
+This uses the `repository-hostname' backend operation.
+If FILE is a list of files, return non-nil if any of them
+individually should stay local."
+ (if (listp file)
+ (delq nil (mapcar 'vc-stay-local-p file))
+ (let* ((backend (vc-backend file))
+ (sym (vc-make-backend-sym backend 'stay-local))
+ (stay-local (if (boundp sym) (symbol-value sym) t)))
+ (if (eq stay-local t) (setq stay-local vc-stay-local))
+ (if (symbolp stay-local) stay-local
+ (let ((dirname (if (file-directory-p file)
+ (directory-file-name file)
+ (file-name-directory file))))
+ (eq 'yes
+ (or (vc-file-getprop dirname 'vc-stay-local-p)
+ (vc-file-setprop
+ dirname 'vc-stay-local-p
+ (let ((hostname (vc-call-backend
+ backend 'repository-hostname dirname)))
+ (if (not hostname)
+ 'no
+ (let ((default t))
+ (if (eq (car-safe stay-local) 'except)
+ (setq default nil stay-local (cdr stay-local)))
+ (when (consp stay-local)
+ (setq stay-local
+ (mapconcat 'identity stay-local "\\|")))
+ (if (if (string-match stay-local hostname)
+ default (not default))
+ 'yes 'no))))))))))))
;;; This is handled specially now.
;; Tell Emacs about this new kind of minor mode
@@ -375,20 +380,26 @@ backend is tried first."
(vc-file-setprop file 'vc-backend 'none)
nil)))))
-(defun vc-backend (file)
- "Return the version control type of FILE, nil if it is not registered."
+(defun vc-backend (file-or-list)
+ "Return the version control type of FILE-OR-LIST, nil if it's not registered.
+If the argument is a list, the files must all have the same back end."
;; `file' can be nil in several places (typically due to the use of
;; code like (vc-backend buffer-file-name)).
- (when (stringp file)
- (let ((property (vc-file-getprop file 'vc-backend)))
- ;; Note that internally, Emacs remembers unregistered
- ;; files by setting the property to `none'.
- (cond ((eq property 'none) nil)
- (property)
- ;; vc-registered sets the vc-backend property
- (t (if (vc-registered file)
- (vc-file-getprop file 'vc-backend)
- nil))))))
+ (cond ((stringp file-or-list)
+ (let ((property (vc-file-getprop file-or-list 'vc-backend)))
+ ;; Note that internally, Emacs remembers unregistered
+ ;; files by setting the property to `none'.
+ (cond ((eq property 'none) nil)
+ (property)
+ ;; vc-registered sets the vc-backend property
+ (t (if (vc-registered file-or-list)
+ (vc-file-getprop file-or-list 'vc-backend)
+ nil)))))
+ ((and file-or-list (listp file-or-list))
+ (vc-backend (car file-or-list)))
+ (t
+ nil)))
+
(defun vc-backend-subdirectory-name (file)
"Return where the master and lock FILEs for the current directory are kept."
@@ -482,7 +493,7 @@ For registered files, the value returned is one of:
;; - `removed'
;; - `copied' and `moved' (might be handled by `removed' and `added')
(or (vc-file-getprop file 'vc-state)
- (if (vc-backend file)
+ (if (and (> (length file) 0) (vc-backend file))
(vc-file-setprop file 'vc-state
(vc-call state-heuristic file)))))
@@ -520,7 +531,7 @@ Return non-nil if FILE is unchanged."
(zerop (condition-case err
;; If the implementation supports it, let the output
;; go to *vc*, not *vc-diff*, since this is an internal call.
- (vc-call diff file nil nil "*vc*")
+ (vc-call diff (list file) nil nil "*vc*")
(wrong-number-of-arguments
;; If this error came from the above call to vc-BACKEND-diff,
;; try again without the optional buffer argument (for
@@ -531,10 +542,10 @@ Return non-nil if FILE is unchanged."
'diff))))
(not (eq (caddr err) 4)))
(signal (car err) (cdr err))
- (vc-call diff file))))))
+ (vc-call diff (list file)))))))
(defun vc-workfile-version (file)
- "Return the version level of the current workfile FILE.
+ "Return the repository version from which FILE was checked out.
If FILE is not registered, this function always returns nil."
(or (vc-file-getprop file 'vc-workfile-version)
(if (vc-backend file)
@@ -705,6 +716,11 @@ Before doing that, check if there are any old backups and get rid of them."
;; any VC Dired buffer to synchronize.
(vc-dired-resynch-file file)))))
+(defconst vc-mode-line-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mode-line down-mouse-1] 'vc-menu-map)
+ map))
+
(defun vc-mode-line (file)
"Set `vc-mode' to display type of version control for FILE.
The value is set in the current buffer, which should be the buffer
@@ -713,9 +729,22 @@ visiting FILE."
(let ((backend (vc-backend file)))
(if (not backend)
(setq vc-mode nil)
- (setq vc-mode (concat " " (if vc-display-status
- (vc-call mode-line-string file)
- (symbol-name backend))))
+ (let* ((ml-string (vc-call mode-line-string file))
+ (ml-echo (get-text-property 0 'help-echo ml-string)))
+ (setq vc-mode
+ (concat
+ " "
+ (if (null vc-display-status)
+ (symbol-name backend)
+ (propertize
+ ml-string
+ 'mouse-face 'mode-line-highlight
+ 'help-echo
+ (concat (or ml-echo
+ (format "File under the %s version control system"
+ backend))
+ "\nmouse-1: Version Control menu")
+ 'local-map vc-mode-line-map)))))
;; If the file is locked by some other user, make
;; the buffer read-only. Like this, even root
;; cannot modify a file that someone else has locked.
@@ -745,17 +774,24 @@ Format:
This function assumes that the file is registered."
(setq backend (symbol-name backend))
(let ((state (vc-state file))
+ (state-echo nil)
(rev (vc-workfile-version file)))
- (cond ((or (eq state 'up-to-date)
- (eq state 'needs-patch))
- (concat backend "-" rev))
- ((stringp state)
- (concat backend ":" state ":" rev))
- (t
- ;; Not just for the 'edited state, but also a fallback
- ;; for all other states. Think about different symbols
- ;; for 'needs-patch and 'needs-merge.
- (concat backend ":" rev)))))
+ (propertize
+ (cond ((or (eq state 'up-to-date)
+ (eq state 'needs-patch))
+ (setq state-echo "Up to date file")
+ (concat backend "-" rev))
+ ((stringp state)
+ (setq state-echo (concat "File locked by" state))
+ (concat backend ":" state ":" rev))
+ (t
+ ;; Not just for the 'edited state, but also a fallback
+ ;; for all other states. Think about different symbols
+ ;; for 'needs-patch and 'needs-merge.
+ (setq state-echo "Locally modified file")
+ (concat backend ":" rev)))
+ 'help-echo (concat state-echo " under the " backend
+ " version control system"))))
(defun vc-follow-link ()
"If current buffer visits a symbolic link, visit the real file.
@@ -786,7 +822,7 @@ current, and kill the buffer that visits the link."
(when buffer-file-name
(vc-file-clearprops buffer-file-name)
(cond
- ((vc-backend buffer-file-name)
+ ((with-demoted-errors (vc-backend buffer-file-name))
;; Compute the state and put it in the modeline.
(vc-mode-line buffer-file-name)
(unless vc-make-backup-files
@@ -865,7 +901,7 @@ Used in `find-file-not-found-functions'."
(let ((map (make-sparse-keymap)))
(define-key map "a" 'vc-update-change-log)
(define-key map "b" 'vc-switch-backend)
- (define-key map "c" 'vc-cancel-version)
+ (define-key map "c" 'vc-rollback)
(define-key map "d" 'vc-directory)
(define-key map "g" 'vc-annotate)
(define-key map "h" 'vc-insert-headers)
@@ -874,8 +910,9 @@ Used in `find-file-not-found-functions'."
(define-key map "m" 'vc-merge)
(define-key map "r" 'vc-retrieve-snapshot)
(define-key map "s" 'vc-create-snapshot)
- (define-key map "u" 'vc-revert-buffer)
+ (define-key map "u" 'vc-revert)
(define-key map "v" 'vc-next-action)
+ (define-key map "+" 'vc-update)
(define-key map "=" 'vc-diff)
(define-key map "~" 'vc-version-other-window)
map))
@@ -905,9 +942,9 @@ Used in `find-file-not-found-functions'."
(define-key vc-menu-map [separator2] '("----"))
(define-key vc-menu-map [vc-insert-header]
'("Insert Header" . vc-insert-headers))
- (define-key vc-menu-map [undo] '("Undo Last Check-In" . vc-cancel-version))
- (define-key vc-menu-map [vc-revert-buffer]
- '("Revert to Base Version" . vc-revert-buffer))
+ (define-key vc-menu-map [undo] '("Undo Last Check-In" . vc-rollback))
+ (define-key vc-menu-map [vc-revert]
+ '("Revert to Base Version" . vc-revert))
(define-key vc-menu-map [vc-update]
'("Update to Latest Version" . vc-update))
(define-key vc-menu-map [vc-next-action] '("Check In/Out" . vc-next-action))
@@ -924,8 +961,8 @@ Used in `find-file-not-found-functions'."
;;(put 'vc-update-change-log 'menu-enable
;; '(member (vc-buffer-backend) '(RCS CVS)))
;;(put 'vc-print-log 'menu-enable 'vc-mode)
-;;(put 'vc-cancel-version 'menu-enable 'vc-mode)
-;;(put 'vc-revert-buffer '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)))