diff options
| author | Richard M. Stallman | 1995-04-26 10:15:03 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1995-04-26 10:15:03 +0000 |
| commit | f2ee419195f831face5b6ac90860b6ac03c85ecd (patch) | |
| tree | d59b9ed1d76010c97e937ab9eea08eb18637a42a | |
| parent | c6d4f6288af8068b414c2e54371f0d69b55aeeac (diff) | |
| download | emacs-f2ee419195f831face5b6ac90860b6ac03c85ecd.tar.gz emacs-f2ee419195f831face5b6ac90860b6ac03c85ecd.zip | |
(vc-buffer-backend): New function.
Also new variable, local in all buffers.
(vc-kill-buffer-hook): Kill local vc-buffer-backend.
(vc-kill-buffer-hook): Don't put it on kill-buffer-hook.
(vc-file-clearprops): Function moved here.
(vc-workfile-version): Function moved here.
(vc-mode-line): Don't call vc-locking-user.
Add branch support for RCS; treat CVS more like RCS and SCCS.
(vc-occurences, vc-trunk-p, vc-branch-p, vc-minor-revision)
(vc-branch-part): new functions that operate on RCS revision numbers.
(vc-status): Use the new property vc-workfile-version
and vc-locking-user (see vc.el). Display "locking state" for CVS.
(vc-find-cvs-master): Search for file name case-sensitively, store
version number into the new property vc-workfile-version.
(vc-find-file-hook): kill any remaining properties. Like this,
when re-finding a file (for example because it has changed on disk),
the version control state gets re-computed.
(vc-mode-line): CVS case: make the buffer read-only if the file
is unmodified.
(vc-kill-buffer-hook): Clear file's vc props when buffer is killed.
| -rw-r--r-- | lisp/vc-hooks.el | 155 |
1 files changed, 111 insertions, 44 deletions
diff --git a/lisp/vc-hooks.el b/lisp/vc-hooks.el index 6780f3ad703..c3ca8c57c8b 100644 --- a/lisp/vc-hooks.el +++ b/lisp/vc-hooks.el | |||
| @@ -3,8 +3,9 @@ | |||
| 3 | ;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> | 5 | ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> |
| 6 | ;; Maintainer: ttn@netcom.com | 6 | ;; Modified by: |
| 7 | ;; Version: 5.3 + CVS hacks by ceder@lysator.liu.se made in Jan-Feb 1994. | 7 | ;; Per Cederqvist <ceder@lysator.liu.se> |
| 8 | ;; Andre Spiegel <spiegel@berlin.informatik.uni-stuttgart.de> | ||
| 8 | 9 | ||
| 9 | ;; This file is part of GNU Emacs. | 10 | ;; This file is part of GNU Emacs. |
| 10 | 11 | ||
| @@ -24,6 +25,9 @@ | |||
| 24 | 25 | ||
| 25 | ;;; Commentary: | 26 | ;;; Commentary: |
| 26 | 27 | ||
| 28 | ;; This is the always-loaded portion of VC. | ||
| 29 | ;; It takes care VC-related activities that are done when you visit a file, | ||
| 30 | ;; so that vc.el itself is loaded only when you use a VC command. | ||
| 27 | ;; See the commentary of vc.el. | 31 | ;; See the commentary of vc.el. |
| 28 | 32 | ||
| 29 | ;;; Code: | 33 | ;;; Code: |
| @@ -53,8 +57,10 @@ Otherwise, not displayed.") | |||
| 53 | (put 'vc-mode 'permanent-local t) | 57 | (put 'vc-mode 'permanent-local t) |
| 54 | 58 | ||
| 55 | ;; We need a notion of per-file properties because the version | 59 | ;; We need a notion of per-file properties because the version |
| 56 | ;; control state of a file is expensive to derive --- we don't | 60 | ;; control state of a file is expensive to derive --- we compute |
| 57 | ;; want to recompute it even on every find. | 61 | ;; them when the file is initially found, keep them up to date |
| 62 | ;; during any subsequent VC operations, and forget them when | ||
| 63 | ;; the buffer is killed. | ||
| 58 | 64 | ||
| 59 | (defmacro vc-error-occurred (&rest body) | 65 | (defmacro vc-error-occurred (&rest body) |
| 60 | (list 'condition-case nil (cons 'progn (append body '(nil))) '(error t))) | 66 | (list 'condition-case nil (cons 'progn (append body '(nil))) '(error t))) |
| @@ -62,6 +68,9 @@ Otherwise, not displayed.") | |||
| 62 | (defvar vc-file-prop-obarray [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] | 68 | (defvar vc-file-prop-obarray [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] |
| 63 | "Obarray for per-file properties.") | 69 | "Obarray for per-file properties.") |
| 64 | 70 | ||
| 71 | (defvar vc-buffer-backend t) | ||
| 72 | (make-variable-buffer-local 'vc-buffer-backend) | ||
| 73 | |||
| 65 | (defun vc-file-setprop (file property value) | 74 | (defun vc-file-setprop (file property value) |
| 66 | ;; set per-file property | 75 | ;; set per-file property |
| 67 | (put (intern file vc-file-prop-obarray) property value)) | 76 | (put (intern file vc-file-prop-obarray) property value)) |
| @@ -70,6 +79,36 @@ Otherwise, not displayed.") | |||
| 70 | ;; get per-file property | 79 | ;; get per-file property |
| 71 | (get (intern file vc-file-prop-obarray) property)) | 80 | (get (intern file vc-file-prop-obarray) property)) |
| 72 | 81 | ||
| 82 | ;;; functions that operate on RCS revision numbers | ||
| 83 | |||
| 84 | (defun vc-occurrences (object sequence) | ||
| 85 | ;; return the number of occurences of OBJECT in SEQUENCE | ||
| 86 | ;; (is it really true that Emacs Lisp doesn't provide such a function?) | ||
| 87 | (let ((len (length sequence)) (index 0) (occ 0)) | ||
| 88 | (while (< index len) | ||
| 89 | (if (eq object (elt sequence index)) | ||
| 90 | (setq occ (1+ occ))) | ||
| 91 | (setq index (1+ index))) | ||
| 92 | occ)) | ||
| 93 | |||
| 94 | (defun vc-trunk-p (rev) | ||
| 95 | ;; return t if REV is a revision on the trunk | ||
| 96 | (not (eq nil (string-match "\\`[0-9]+\\.[0-9]+\\'" rev)))) | ||
| 97 | |||
| 98 | (defun vc-branch-p (rev) | ||
| 99 | ;; return t if REV is the branch part of a revision, | ||
| 100 | ;; i.e. a revision without a minor number | ||
| 101 | (eq 0 (% (vc-occurrences ?. rev) 2))) | ||
| 102 | |||
| 103 | (defun vc-minor-revision (rev) | ||
| 104 | ;; return the minor revision number of REV, | ||
| 105 | ;; i.e. the number after the last dot. | ||
| 106 | (substring rev (1+ (string-match "\\.[0-9]+\\'" rev)))) | ||
| 107 | |||
| 108 | (defun vc-branch-part (rev) | ||
| 109 | ;; return the branch part of a revision number REV | ||
| 110 | (substring rev 0 (string-match "\\.[0-9]+\\'" rev))) | ||
| 111 | |||
| 73 | ;;; actual version-control code starts here | 112 | ;;; actual version-control code starts here |
| 74 | 113 | ||
| 75 | (defun vc-registered (file) | 114 | (defun vc-registered (file) |
| @@ -108,25 +147,29 @@ Otherwise, not displayed.") | |||
| 108 | ;; If it is, do a (throw 'found (cons MASTER 'CVS)). | 147 | ;; If it is, do a (throw 'found (cons MASTER 'CVS)). |
| 109 | ;; Note: If the file is ``cvs add''ed but not yet ``cvs commit''ed | 148 | ;; Note: If the file is ``cvs add''ed but not yet ``cvs commit''ed |
| 110 | ;; the MASTER will not actually exist yet. The other parts of VC | 149 | ;; the MASTER will not actually exist yet. The other parts of VC |
| 111 | ;; checks for this condition. This function returns something random if | 150 | ;; checks for this condition. This function returns nil if |
| 112 | ;; DIRNAME/BASENAME is not handled by CVS. | 151 | ;; DIRNAME/BASENAME is not handled by CVS. |
| 113 | (if (and (file-directory-p (concat dirname "CVS/")) | 152 | (if (and (file-directory-p (concat dirname "CVS/")) |
| 114 | (file-readable-p (concat dirname "CVS/Entries"))) | 153 | (file-readable-p (concat dirname "CVS/Entries"))) |
| 115 | (let ((bufs nil)) | 154 | (let ((bufs nil) (fold case-fold-search)) |
| 116 | (unwind-protect | 155 | (unwind-protect |
| 117 | (save-excursion | 156 | (save-excursion |
| 118 | (setq bufs (list | 157 | (setq bufs (list |
| 119 | (find-file-noselect (concat dirname "CVS/Entries")))) | 158 | (find-file-noselect (concat dirname "CVS/Entries")))) |
| 120 | (set-buffer (car bufs)) | 159 | (set-buffer (car bufs)) |
| 121 | (goto-char (point-min)) | 160 | (goto-char (point-min)) |
| 161 | ;; make sure the file name is searched | ||
| 162 | ;; case-sensitively | ||
| 163 | (setq case-fold-search nil) | ||
| 122 | (cond | 164 | (cond |
| 123 | ((re-search-forward | 165 | ((re-search-forward |
| 124 | (concat "^/" (regexp-quote basename) "/\\([^/]*\\)/") | 166 | (concat "^/" (regexp-quote basename) "/\\([^/]*\\)/") |
| 125 | nil t) | 167 | nil t) |
| 168 | (setq case-fold-search fold) ;; restore the old value | ||
| 126 | ;; We found it. Store away version number, now | 169 | ;; We found it. Store away version number, now |
| 127 | ;; that we are anyhow so close to finding it. | 170 | ;; that we are anyhow so close to finding it. |
| 128 | (vc-file-setprop (concat dirname basename) | 171 | (vc-file-setprop (concat dirname basename) |
| 129 | 'vc-your-latest-version | 172 | 'vc-workfile-version |
| 130 | (buffer-substring (match-beginning 1) | 173 | (buffer-substring (match-beginning 1) |
| 131 | (match-end 1))) | 174 | (match-end 1))) |
| 132 | (setq bufs (cons (find-file-noselect | 175 | (setq bufs (cons (find-file-noselect |
| @@ -139,7 +182,9 @@ Otherwise, not displayed.") | |||
| 139 | (1- (point-max)))) | 182 | (1- (point-max)))) |
| 140 | basename | 183 | basename |
| 141 | ",v"))) | 184 | ",v"))) |
| 142 | (throw 'found (cons master 'CVS)))))) | 185 | (throw 'found (cons master 'CVS)))) |
| 186 | (t (setq case-fold-search fold) ;; restore the old value | ||
| 187 | nil))) | ||
| 143 | (mapcar (function kill-buffer) bufs))))) | 188 | (mapcar (function kill-buffer) bufs))))) |
| 144 | 189 | ||
| 145 | (defun vc-name (file) | 190 | (defun vc-name (file) |
| @@ -161,12 +206,17 @@ Otherwise, not displayed.") | |||
| 161 | (vc-file-setprop file 'vc-name (car name-and-type)) | 206 | (vc-file-setprop file 'vc-name (car name-and-type)) |
| 162 | (vc-file-setprop file 'vc-backend (cdr name-and-type)))))))) | 207 | (vc-file-setprop file 'vc-backend (cdr name-and-type)))))))) |
| 163 | 208 | ||
| 209 | (defun vc-buffer-backend () | ||
| 210 | "Return the version-control type of the visited file, or nil if none." | ||
| 211 | (if (eq vc-buffer-backend t) | ||
| 212 | (setq vc-buffer-backend (vc-backend-deduce (buffer-file-name))) | ||
| 213 | vc-buffer-backend)) | ||
| 214 | |||
| 164 | (defun vc-toggle-read-only (&optional verbose) | 215 | (defun vc-toggle-read-only (&optional verbose) |
| 165 | "Change read-only status of current buffer, perhaps via version control. | 216 | "Change read-only status of current buffer, perhaps via version control. |
| 166 | If the buffer is visiting a file registered with version control, | 217 | If the buffer is visiting a file registered with version control, |
| 167 | then check the file in or out. Otherwise, just change the read-only flag | 218 | then check the file in or out. Otherwise, just change the read-only flag |
| 168 | of the buffer. | 219 | of the buffer. With prefix argument, ask for version number." |
| 169 | If you provide a prefix argument, we pass it on to `vc-next-action'." | ||
| 170 | (interactive "P") | 220 | (interactive "P") |
| 171 | (if (vc-backend-deduce (buffer-file-name)) | 221 | (if (vc-backend-deduce (buffer-file-name)) |
| 172 | (vc-next-action verbose) | 222 | (vc-next-action verbose) |
| @@ -179,31 +229,32 @@ The value is set in the current buffer, which should be the buffer | |||
| 179 | visiting FILE. Second optional arg LABEL is put in place of version | 229 | visiting FILE. Second optional arg LABEL is put in place of version |
| 180 | control system name." | 230 | control system name." |
| 181 | (interactive (list buffer-file-name nil)) | 231 | (interactive (list buffer-file-name nil)) |
| 182 | (if file | 232 | (let ((vc-type (vc-backend-deduce file))) |
| 183 | (let ((vc-type (vc-backend-deduce file))) | 233 | (setq vc-mode |
| 184 | (setq vc-mode | 234 | (concat " " (or label (symbol-name vc-type)) |
| 185 | (if vc-type | 235 | (if vc-display-status (vc-status file vc-type)))) |
| 186 | (concat " " (or label (symbol-name vc-type)) | 236 | ;;; ;; Make the buffer read-only if the file is not locked |
| 187 | (if vc-display-status | 237 | ;;; ;; (or unchanged, in the CVS case). |
| 188 | (vc-status file vc-type))))) | 238 | ;;; (if (not (vc-locking-user file)) |
| 189 | ;; Even root shouldn't modify a registered file without | 239 | ;;; (setq buffer-read-only t)) |
| 190 | ;; locking it first. | 240 | ;; Even root shouldn't modify a registered file without |
| 191 | (and vc-type | 241 | ;; locking it first. |
| 192 | (not buffer-read-only) | 242 | (and vc-type |
| 193 | (zerop (user-uid)) | 243 | (not buffer-read-only) |
| 194 | (require 'vc) | 244 | (zerop (user-uid)) |
| 195 | (not (equal (user-login-name) (vc-locking-user file))) | 245 | (require 'vc) |
| 196 | (setq buffer-read-only t)) | 246 | (not (equal (user-login-name) (vc-locking-user file))) |
| 197 | (and (null vc-type) | 247 | (setq buffer-read-only t)) |
| 198 | (file-symlink-p file) | 248 | (and (null vc-type) |
| 199 | (let ((link-type (vc-backend-deduce (file-symlink-p file)))) | 249 | (file-symlink-p file) |
| 200 | (if link-type | 250 | (let ((link-type (vc-backend-deduce (file-symlink-p file)))) |
| 201 | (message | 251 | (if link-type |
| 202 | "Warning: symbolic link to %s-controlled source file" | 252 | (message |
| 203 | link-type)))) | 253 | "Warning: symbolic link to %s-controlled source file" |
| 204 | (force-mode-line-update) | 254 | link-type)))) |
| 205 | ;;(set-buffer-modified-p (buffer-modified-p)) ;;use this if Emacs 18 | 255 | (force-mode-line-update) |
| 206 | vc-type))) | 256 | ;;(set-buffer-modified-p (buffer-modified-p)) ;;use this if Emacs 18 |
| 257 | vc-type)) | ||
| 207 | 258 | ||
| 208 | (defun vc-status (file vc-type) | 259 | (defun vc-status (file vc-type) |
| 209 | ;; Return string for placement in modeline by `vc-mode-line'. | 260 | ;; Return string for placement in modeline by `vc-mode-line'. |
| @@ -326,18 +377,25 @@ control system name." | |||
| 326 | (set-buffer-modified-p nil) | 377 | (set-buffer-modified-p nil) |
| 327 | status)))) | 378 | status)))) |
| 328 | 379 | ||
| 380 | (defun vc-file-clearprops (file) | ||
| 381 | ;; clear all properties of a given file | ||
| 382 | (setplist (intern file vc-file-prop-obarray) nil)) | ||
| 383 | |||
| 329 | ;;; install a call to the above as a find-file hook | 384 | ;;; install a call to the above as a find-file hook |
| 330 | (defun vc-find-file-hook () | 385 | (defun vc-find-file-hook () |
| 331 | ;; Recompute whether file is version controlled, | 386 | ;; Recompute whether file is version controlled, |
| 332 | ;; if user has killed the buffer and revisited. | 387 | ;; if user has killed the buffer and revisited. |
| 333 | (if buffer-file-name | 388 | (cond |
| 334 | (vc-file-setprop buffer-file-name 'vc-backend nil)) | 389 | (buffer-file-name |
| 335 | (if (and (vc-mode-line buffer-file-name) (not vc-make-backup-files)) | 390 | (vc-file-clearprops buffer-file-name) |
| 336 | (progn | 391 | (cond |
| 337 | ;; Use this variable, not make-backup-files, | 392 | ((vc-backend-deduce buffer-file-name) |
| 338 | ;; because this is for things that depend on the file name. | 393 | (vc-mode-line buffer-file-name) |
| 339 | (make-local-variable 'backup-inhibited) | 394 | (cond ((not vc-make-backup-files) |
| 340 | (setq backup-inhibited t)))) | 395 | ;; Use this variable, not make-backup-files, |
| 396 | ;; because this is for things that depend on the file name. | ||
| 397 | (make-local-variable 'backup-inhibited) | ||
| 398 | (setq backup-inhibited t)))))))) | ||
| 341 | 399 | ||
| 342 | (add-hook 'find-file-hooks 'vc-find-file-hook) | 400 | (add-hook 'find-file-hooks 'vc-find-file-hook) |
| 343 | 401 | ||
| @@ -352,6 +410,15 @@ Returns t if checkout was successful, nil otherwise." | |||
| 352 | 410 | ||
| 353 | (add-hook 'find-file-not-found-hooks 'vc-file-not-found-hook) | 411 | (add-hook 'find-file-not-found-hooks 'vc-file-not-found-hook) |
| 354 | 412 | ||
| 413 | ;; Discard info about a file when we kill its buffer. | ||
| 414 | (defun vc-kill-buffer-hook () | ||
| 415 | (if (stringp (buffer-file-name)) | ||
| 416 | (progn | ||
| 417 | (vc-file-clearprops (buffer-file-name)) | ||
| 418 | (kill-local-variable 'vc-buffer-backend)))) | ||
| 419 | |||
| 420 | ;;;(add-hook 'kill-buffer-hook 'vc-kill-buffer-hook) | ||
| 421 | |||
| 355 | ;;; Now arrange for bindings and autoloading of the main package. | 422 | ;;; Now arrange for bindings and autoloading of the main package. |
| 356 | ;;; Bindings for this have to go in the global map, as we'll often | 423 | ;;; Bindings for this have to go in the global map, as we'll often |
| 357 | ;;; want to call them from random buffers. | 424 | ;;; want to call them from random buffers. |
| @@ -402,7 +469,7 @@ Returns t if checkout was successful, nil otherwise." | |||
| 402 | (put 'vc-version-other-window 'menu-enable 'vc-mode) | 469 | (put 'vc-version-other-window 'menu-enable 'vc-mode) |
| 403 | (put 'vc-diff 'menu-enable 'vc-mode) | 470 | (put 'vc-diff 'menu-enable 'vc-mode) |
| 404 | (put 'vc-update-change-log 'menu-enable | 471 | (put 'vc-update-change-log 'menu-enable |
| 405 | '(eq (vc-backend-deduce (buffer-file-name)) 'RCS)) | 472 | '(eq (vc-buffer-backend) 'RCS)) |
| 406 | (put 'vc-print-log 'menu-enable 'vc-mode) | 473 | (put 'vc-print-log 'menu-enable 'vc-mode) |
| 407 | (put 'vc-cancel-version 'menu-enable 'vc-mode) | 474 | (put 'vc-cancel-version 'menu-enable 'vc-mode) |
| 408 | (put 'vc-revert-buffer 'menu-enable 'vc-mode) | 475 | (put 'vc-revert-buffer 'menu-enable 'vc-mode) |