diff options
| author | André Spiegel | 1995-08-25 18:30:11 +0000 |
|---|---|---|
| committer | André Spiegel | 1995-08-25 18:30:11 +0000 |
| commit | b0c9bc8c219872ae1533934ddd62c38e8a4d37b0 (patch) | |
| tree | 1849df9aaa33fbc2095d994652669cde65ae6b5c | |
| parent | f042d383859e631c3f81bed06b7415a49f1db164 (diff) | |
| download | emacs-b0c9bc8c219872ae1533934ddd62c38e8a4d37b0.tar.gz emacs-b0c9bc8c219872ae1533934ddd62c38e8a4d37b0.zip | |
(vc-directory): Kill existing vc-dired buffers for this directory.
Provide a better header. Corrected the check whether any files were
found at all (don't display a listing in this case). Under CVS,
display cvs-status rather than vc-locking-user.
(vc-next-action-on-file): When doing a check-in in vc-dired-mode, find
the file in another window.
(vc-next-action-dired): Update dired listing while processing the
files.
(vc-next-action): Check whether a check-in comment is really needed
for this mass operation.
(vc-checkout): Resynch the buffer, even if it's not current.
(vc-dired-state-info, vc-dired-update-line): New functions.
(vc-dired-prefix-map): Added local definition for `g' and `='.
(vc-dired-reformat-line): Simplified. Erase the hardlink count from
the listing, because it doesn't relate to version control.
(vc-rcs-release, vc-cvs-release, vc-sccs-release): New variables, may
be set by the user.
(vc-backend-release, vc-release-greater-or-equal, vc-backend-release-p):
New Functions.
(vc-do-command): Allow FILE to be nil.
(vc-backend-checkin): When creating a branch, don't bother to unlock
the old version if this is RCS 5.6.2 or higher.
(vc-next-action-on-file): Allow lock-stealing only if RCS 5.6.2 or
higher.
(vc-backend-admin, vc-backend-checkin): If available, use ci -i and -j.
Updated Developer's Notes.
| -rw-r--r-- | lisp/vc.el | 314 |
1 files changed, 231 insertions, 83 deletions
diff --git a/lisp/vc.el b/lisp/vc.el index 7d2d6092576..eda2225c1bf 100644 --- a/lisp/vc.el +++ b/lisp/vc.el | |||
| @@ -35,8 +35,11 @@ | |||
| 35 | ;; in Jan-Feb 1994. | 35 | ;; in Jan-Feb 1994. |
| 36 | ;; | 36 | ;; |
| 37 | ;; Supported version-control systems presently include SCCS, RCS, and CVS. | 37 | ;; Supported version-control systems presently include SCCS, RCS, and CVS. |
| 38 | ;; The RCS lock-stealing code doesn't work right unless you use RCS 5.6.2 | 38 | ;; |
| 39 | ;; or newer. Currently (January 1994) that is only a beta test release. | 39 | ;; Some features will not work with old RCS versions. Where |
| 40 | ;; appropriate, VC finds out which version you have, and allows or | ||
| 41 | ;; disallows those features (stealing locks, for example, works only | ||
| 42 | ;; from 5.6.2 onwards). | ||
| 40 | ;; Even initial checkins will fail if your RCS version is so old that ci | 43 | ;; Even initial checkins will fail if your RCS version is so old that ci |
| 41 | ;; doesn't understand -t-; this has been known to happen to people running | 44 | ;; doesn't understand -t-; this has been known to happen to people running |
| 42 | ;; NExTSTEP 3.0. | 45 | ;; NExTSTEP 3.0. |
| @@ -149,6 +152,18 @@ is sensitive to blank lines.") | |||
| 149 | Verify that the file really is not locked | 152 | Verify that the file really is not locked |
| 150 | and that its contents match what the master file says.") | 153 | and that its contents match what the master file says.") |
| 151 | 154 | ||
| 155 | (defvar vc-rcs-release nil | ||
| 156 | "*The release number of your RCS installation, as a string. | ||
| 157 | If nil, VC itself computes this value when it is first needed.") | ||
| 158 | |||
| 159 | (defvar vc-sccs-release nil | ||
| 160 | "*The release number of your SCCS installation, as a string. | ||
| 161 | If nil, VC itself computes this value when it is first needed.") | ||
| 162 | |||
| 163 | (defvar vc-cvs-release nil | ||
| 164 | "*The release number of your SCCS installation, as a string. | ||
| 165 | If nil, VC itself computes this value when it is first needed.") | ||
| 166 | |||
| 152 | ;; Variables the user doesn't need to know about. | 167 | ;; Variables the user doesn't need to know about. |
| 153 | (defvar vc-log-entry-mode nil) | 168 | (defvar vc-log-entry-mode nil) |
| 154 | (defvar vc-log-operation nil) | 169 | (defvar vc-log-operation nil) |
| @@ -193,6 +208,70 @@ and that its contents match what the master file says.") | |||
| 193 | (if (not (fboundp 'file-regular-p)) | 208 | (if (not (fboundp 'file-regular-p)) |
| 194 | (fset 'file-regular-p 'file-regular-p-18)) | 209 | (fset 'file-regular-p 'file-regular-p-18)) |
| 195 | 210 | ||
| 211 | ;;; Find and compare backend releases | ||
| 212 | |||
| 213 | (defun vc-backend-release (backend) | ||
| 214 | ;; Returns which backend release is installed on this system. | ||
| 215 | (cond | ||
| 216 | ((eq backend 'RCS) | ||
| 217 | (or vc-rcs-release | ||
| 218 | (and (zerop (vc-do-command nil 2 "rcs" nil nil "-V")) | ||
| 219 | (save-excursion | ||
| 220 | (set-buffer (get-buffer "*vc*")) | ||
| 221 | (setq vc-rcs-release | ||
| 222 | (car (vc-parse-buffer | ||
| 223 | '(("^RCS version \\([0-9.]+ *.*\\)" 1))))))) | ||
| 224 | (setq vc-rcs-release 'unknown))) | ||
| 225 | ((eq backend 'CVS) | ||
| 226 | (or vc-cvs-release | ||
| 227 | (and (zerop (vc-do-command nil 1 "cvs" nil nil "-v")) | ||
| 228 | (save-excursion | ||
| 229 | (set-buffer (get-buffer "*vc*")) | ||
| 230 | (setq vc-cvs-release | ||
| 231 | (car (vc-parse-buffer | ||
| 232 | '(("^Concurrent Versions System (CVS) \\([0-9.]+\\)" | ||
| 233 | 1))))))) | ||
| 234 | (setq vc-cvs-release 'unknown))) | ||
| 235 | ((eq backend 'SCCS) | ||
| 236 | vc-sccs-release))) | ||
| 237 | |||
| 238 | (defun vc-release-greater-or-equal (r1 r2) | ||
| 239 | ;; Compare release numbers, represented as strings. | ||
| 240 | ;; Release components are assumed cardinal numbers, not decimal | ||
| 241 | ;; fractions (5.10 is a higher release than 5.9). Omitted fields | ||
| 242 | ;; are considered lower (5.6.7 is earlier than 5.6.7.1). | ||
| 243 | ;; Comparison runs till the end of the string is found, or a | ||
| 244 | ;; non-numeric component shows up (5.6.7 is earlier than "5.6.7 beta", | ||
| 245 | ;; which is probably not what you want in some cases). | ||
| 246 | ;; This code is suitable for existing RCS release numbers. | ||
| 247 | ;; CVS releases are handled reasonably, too (1.3 < 1.4* < 1.5). | ||
| 248 | (let (v1 v2 i1 i2) | ||
| 249 | (catch 'done | ||
| 250 | (or (and (string-match "^\\.?\\([0-9]+\\)" r1) | ||
| 251 | (setq i1 (match-end 0)) | ||
| 252 | (setq v1 (string-to-number (match-string 1 r1))) | ||
| 253 | (or (and (string-match "^\\.?\\([0-9]+\\)" r2) | ||
| 254 | (setq i2 (match-end 0)) | ||
| 255 | (setq v2 (string-to-number (match-string 1 r2))) | ||
| 256 | (if (> v1 v2) (throw 'done t) | ||
| 257 | (if (< v1 v2) (throw 'done nil) | ||
| 258 | (throw 'done | ||
| 259 | (vc-release-greater-or-equal | ||
| 260 | (substring r1 i1) | ||
| 261 | (substring r2 i2))))))) | ||
| 262 | (throw 'done t))) | ||
| 263 | (or (and (string-match "^\\.?\\([0-9]+\\)" r2) | ||
| 264 | (throw 'done nil)) | ||
| 265 | (throw 'done t))))) | ||
| 266 | |||
| 267 | (defun vc-backend-release-p (backend release) | ||
| 268 | ;; Return t if we have RELEASE of BACKEND or better | ||
| 269 | (let (i r (ri 0) (ii 0) is rs (installation (vc-backend-release backend))) | ||
| 270 | (if (not (eq installation 'unknown)) | ||
| 271 | (cond | ||
| 272 | ((or (eq backend 'RCS) (eq backend 'CVS)) | ||
| 273 | (vc-release-greater-or-equal installation release)))))) | ||
| 274 | |||
| 196 | ;;; functions that operate on RCS revision numbers | 275 | ;;; functions that operate on RCS revision numbers |
| 197 | 276 | ||
| 198 | (defun vc-trunk-p (rev) | 277 | (defun vc-trunk-p (rev) |
| @@ -300,7 +379,7 @@ The command is successful if its exit status does not exceed OKSTATUS. | |||
| 300 | The last argument of the command is the master name of FILE if LAST is | 379 | The last argument of the command is the master name of FILE if LAST is |
| 301 | `MASTER', or the workfile of FILE if LAST is `WORKFILE'; this is appended | 380 | `MASTER', or the workfile of FILE if LAST is `WORKFILE'; this is appended |
| 302 | to an optional list of FLAGS." | 381 | to an optional list of FLAGS." |
| 303 | (setq file (expand-file-name file)) | 382 | (and file (setq file (expand-file-name file))) |
| 304 | (if (not buffer) (setq buffer "*vc*")) | 383 | (if (not buffer) (setq buffer "*vc*")) |
| 305 | (if vc-command-messages | 384 | (if vc-command-messages |
| 306 | (message "Running %s on %s..." command file)) | 385 | (message "Running %s on %s..." command file)) |
| @@ -567,6 +646,9 @@ to an optional list of FLAGS." | |||
| 567 | (not (string-equal owner (user-login-name)))) | 646 | (not (string-equal owner (user-login-name)))) |
| 568 | (if comment | 647 | (if comment |
| 569 | (error "Sorry, you can't steal the lock on %s this way" file)) | 648 | (error "Sorry, you can't steal the lock on %s this way" file)) |
| 649 | (and (eq vc-type 'RCS) | ||
| 650 | (not (vc-backend-release-p 'RCS "5.6.2")) | ||
| 651 | (error "File is locked by %s." owner)) | ||
| 570 | (vc-steal-lock | 652 | (vc-steal-lock |
| 571 | file | 653 | file |
| 572 | (if verbose (read-string "Version to steal: ") | 654 | (if verbose (read-string "Version to steal: ") |
| @@ -575,7 +657,9 @@ to an optional list of FLAGS." | |||
| 575 | 657 | ||
| 576 | ;; OK, user owns the lock on the file | 658 | ;; OK, user owns the lock on the file |
| 577 | (t | 659 | (t |
| 578 | (find-file file) | 660 | (if vc-dired-mode |
| 661 | (find-file-other-window file) | ||
| 662 | (find-file file)) | ||
| 579 | 663 | ||
| 580 | ;; give luser a chance to save before checking in. | 664 | ;; give luser a chance to save before checking in. |
| 581 | (vc-buffer-sync) | 665 | (vc-buffer-sync) |
| @@ -602,18 +686,19 @@ to an optional list of FLAGS." | |||
| 602 | ))))) | 686 | ))))) |
| 603 | 687 | ||
| 604 | (defun vc-next-action-dired (file rev comment) | 688 | (defun vc-next-action-dired (file rev comment) |
| 605 | ;; We've accepted a log comment, now do a vc-next-action using it on all | 689 | ;; Do a vc-next-action-on-file on all the marked files, possibly |
| 606 | ;; marked files. | 690 | ;; passing on the log comment we've just entered. |
| 607 | (let ((configuration (current-window-configuration))) | 691 | (let ((configuration (current-window-configuration)) |
| 692 | (dired-buffer (current-buffer))) | ||
| 608 | (dired-map-over-marks | 693 | (dired-map-over-marks |
| 609 | (save-window-excursion | 694 | (let ((file (dired-get-filename)) p) |
| 610 | (let ((file (dired-get-filename))) | 695 | (message "Processing %s..." file) |
| 611 | (message "Processing %s..." file) | 696 | (vc-next-action-on-file file nil comment) |
| 612 | (vc-next-action-on-file file nil comment) | 697 | (set-buffer dired-buffer) |
| 613 | (message "Processing %s...done" file))) | 698 | (vc-dired-update-line file) |
| 614 | nil t) | 699 | (set-window-configuration configuration) |
| 615 | (set-window-configuration configuration)) | 700 | (message "Processing %s...done" file)) |
| 616 | ) | 701 | nil t))) |
| 617 | 702 | ||
| 618 | ;; Here's the major entry point. | 703 | ;; Here's the major entry point. |
| 619 | 704 | ||
| @@ -662,9 +747,18 @@ merge in the changes into your working copy." | |||
| 662 | (let ((files (dired-get-marked-files))) | 747 | (let ((files (dired-get-marked-files))) |
| 663 | (if (= (length files) 1) | 748 | (if (= (length files) 1) |
| 664 | (find-file-other-window (car files)) | 749 | (find-file-other-window (car files)) |
| 665 | (vc-start-entry nil nil nil | 750 | (if (string= "" |
| 666 | "Enter a change comment for the marked files." | 751 | (mapconcat |
| 667 | 'vc-next-action-dired) | 752 | (function (lambda (f) |
| 753 | (if (eq (vc-backend f) 'CVS) | ||
| 754 | (if (eq (vc-cvs-status f) 'locally-modified) | ||
| 755 | "@" "") | ||
| 756 | (if (vc-locking-user f) "@" "")))) | ||
| 757 | files "")) | ||
| 758 | (vc-next-action-dired nil nil "dummy") | ||
| 759 | (vc-start-entry nil nil nil | ||
| 760 | "Enter a change comment for the marked files." | ||
| 761 | 'vc-next-action-dired)) | ||
| 668 | (throw 'nogo nil)))) | 762 | (throw 'nogo nil)))) |
| 669 | (while vc-parent-buffer | 763 | (while vc-parent-buffer |
| 670 | (pop-to-buffer vc-parent-buffer)) | 764 | (pop-to-buffer vc-parent-buffer)) |
| @@ -728,7 +822,7 @@ merge in the changes into your working copy." | |||
| 728 | (kill-buffer (current-buffer))))) | 822 | (kill-buffer (current-buffer))))) |
| 729 | 823 | ||
| 730 | (defun vc-resynch-buffer (file &optional keep noquery) | 824 | (defun vc-resynch-buffer (file &optional keep noquery) |
| 731 | ;; if FILE is currently visited, resynch it's buffer | 825 | ;; if FILE is currently visited, resynch its buffer |
| 732 | (let ((buffer (get-file-buffer file))) | 826 | (let ((buffer (get-file-buffer file))) |
| 733 | (if buffer | 827 | (if buffer |
| 734 | (save-excursion | 828 | (save-excursion |
| @@ -781,9 +875,7 @@ level to check it in under. COMMENT, if specified, is the checkin comment." | |||
| 781 | (if (and (string-match "^/[^/:]+:" file) (vc-find-binary "ftp")) | 875 | (if (and (string-match "^/[^/:]+:" file) (vc-find-binary "ftp")) |
| 782 | (error "Sorry, you can't check out files over FTP")) | 876 | (error "Sorry, you can't check out files over FTP")) |
| 783 | (vc-backend-checkout file writable rev) | 877 | (vc-backend-checkout file writable rev) |
| 784 | (if (string-equal file buffer-file-name) | 878 | (vc-resynch-buffer file t t)) |
| 785 | (vc-resynch-window file t t)) | ||
| 786 | ) | ||
| 787 | 879 | ||
| 788 | (defun vc-steal-lock (file rev &optional owner) | 880 | (defun vc-steal-lock (file rev &optional owner) |
| 789 | "Steal the lock on the current workfile." | 881 | "Steal the lock on the current workfile." |
| @@ -1138,6 +1230,8 @@ the variable `vc-header-alist'." | |||
| 1138 | 1230 | ||
| 1139 | (defvar vc-dired-prefix-map (make-sparse-keymap)) | 1231 | (defvar vc-dired-prefix-map (make-sparse-keymap)) |
| 1140 | (define-key vc-dired-prefix-map "\C-xv" vc-prefix-map) | 1232 | (define-key vc-dired-prefix-map "\C-xv" vc-prefix-map) |
| 1233 | (define-key vc-dired-prefix-map "g" 'vc-directory) | ||
| 1234 | (define-key vc-dired-prefix-map "=" 'vc-diff) | ||
| 1141 | 1235 | ||
| 1142 | (or (not (boundp 'minor-mode-map-alist)) | 1236 | (or (not (boundp 'minor-mode-map-alist)) |
| 1143 | (assq 'vc-dired-mode minor-mode-map-alist) | 1237 | (assq 'vc-dired-mode minor-mode-map-alist) |
| @@ -1154,6 +1248,20 @@ on a buffer attached to the file named in the current Dired buffer line." | |||
| 1154 | (setq vc-dired-mode t) | 1248 | (setq vc-dired-mode t) |
| 1155 | (setq vc-mode " under VC")) | 1249 | (setq vc-mode " under VC")) |
| 1156 | 1250 | ||
| 1251 | (defun vc-dired-state-info (file) | ||
| 1252 | ;; Return the string that indicates the version control status | ||
| 1253 | ;; on a VC dired line. | ||
| 1254 | (let ((cvs-state (and (eq (vc-backend file) 'CVS) | ||
| 1255 | (vc-cvs-status file)))) | ||
| 1256 | (if cvs-state | ||
| 1257 | (cond ((eq cvs-state 'up-to-date) nil) | ||
| 1258 | ((eq cvs-state 'needs-checkout) "patch") | ||
| 1259 | ((eq cvs-state 'locally-modified) "modified") | ||
| 1260 | ((eq cvs-state 'needs-merge) "merge") | ||
| 1261 | ((eq cvs-state 'unresolved-conflict) "conflict") | ||
| 1262 | ((eq cvs-state 'locally-added) "added")) | ||
| 1263 | (vc-locking-user file)))) | ||
| 1264 | |||
| 1157 | (defun vc-dired-reformat-line (x) | 1265 | (defun vc-dired-reformat-line (x) |
| 1158 | ;; Hack a directory-listing line, plugging in locking-user info in | 1266 | ;; Hack a directory-listing line, plugging in locking-user info in |
| 1159 | ;; place of the user and group info. Should have the beneficial | 1267 | ;; place of the user and group info. Should have the beneficial |
| @@ -1165,26 +1273,22 @@ on a buffer attached to the file named in the current Dired buffer line." | |||
| 1165 | ;; (insert (concat x "\t"))) | 1273 | ;; (insert (concat x "\t"))) |
| 1166 | ;; | 1274 | ;; |
| 1167 | ;; This code, like dired, assumes UNIX -l format. | 1275 | ;; This code, like dired, assumes UNIX -l format. |
| 1168 | (forward-word 1) ;; skip over any extra field due to -ibs options | ||
| 1169 | (cond | 1276 | (cond |
| 1170 | ;; This hack is used by the CVS code. See vc-locking-user. | 1277 | ((re-search-forward |
| 1171 | ((numberp x) | 1278 | "\\([drwx-]+ \\) *[0-9]+ \\([^ ]+\\) +[0-9]+\\( .*\\)" |
| 1172 | (cond | 1279 | nil 0) |
| 1173 | ((re-search-forward "\\([0-9]+ \\)\\([^ ]+\\)\\( .*\\)" nil 0) | 1280 | (if (numberp x) (setq x (match-string 2))) |
| 1174 | (save-excursion | ||
| 1175 | (goto-char (match-beginning 2)) | ||
| 1176 | (insert "(") | ||
| 1177 | (goto-char (1+ (match-end 2))) | ||
| 1178 | (insert ")") | ||
| 1179 | (delete-char (- 17 (- (match-end 2) (match-beginning 2)))) | ||
| 1180 | (insert (substring " " 0 | ||
| 1181 | (- 7 (- (match-end 2) (match-beginning 2))))))))) | ||
| 1182 | (t | ||
| 1183 | (if x (setq x (concat "(" x ")"))) | 1281 | (if x (setq x (concat "(" x ")"))) |
| 1184 | (if (re-search-forward "\\([0-9]+ \\).................\\( .*\\)" nil 0) | 1282 | (let ((rep (substring (concat x " ") 0 10))) |
| 1185 | (let ((rep (substring (concat x " ") 0 10))) | 1283 | (replace-match (concat "\\1" rep "\\3")))))) |
| 1186 | (replace-match (concat "\\1" rep "\\2") t))) | 1284 | |
| 1187 | ))) | 1285 | (defun vc-dired-update-line (file) |
| 1286 | ;; Update the vc-dired listing line of file -- it is assumed | ||
| 1287 | ;; that point is already on this line. | ||
| 1288 | (dired-do-redisplay 1) | ||
| 1289 | (dired-previous-line 1) | ||
| 1290 | (beginning-of-line) | ||
| 1291 | (vc-dired-reformat-line (vc-dired-state-info file))) | ||
| 1188 | 1292 | ||
| 1189 | ;;; Note in Emacs 18 the following defun gets overridden | 1293 | ;;; Note in Emacs 18 the following defun gets overridden |
| 1190 | ;;; with the symbol 'vc-directory-18. See below. | 1294 | ;;; with the symbol 'vc-directory-18. See below. |
| @@ -1196,41 +1300,66 @@ in all these directories. With a prefix argument, it lists all files." | |||
| 1196 | (interactive "P") | 1300 | (interactive "P") |
| 1197 | (let (nonempty | 1301 | (let (nonempty |
| 1198 | (dl (length (expand-file-name default-directory))) | 1302 | (dl (length (expand-file-name default-directory))) |
| 1199 | (filelist nil) (userlist nil) | 1303 | (filelist nil) (statelist nil) |
| 1200 | dired-buf | 1304 | dired-buf |
| 1201 | dired-buf-mod-count) | 1305 | dired-buf-mod-count) |
| 1202 | (vc-file-tree-walk | 1306 | (vc-file-tree-walk |
| 1203 | (function (lambda (f) | 1307 | (function |
| 1204 | (if (vc-registered f) | 1308 | (lambda (f) |
| 1205 | (let ((user (vc-locking-user f))) | 1309 | (if (vc-registered f) |
| 1206 | (and (or verbose user) | 1310 | (let ((state (vc-dired-state-info f))) |
| 1207 | (setq filelist (cons (substring f dl) filelist)) | 1311 | (and (or verbose state) |
| 1208 | (setq userlist (cons user userlist)))))))) | 1312 | (setq filelist (cons (substring f dl) filelist)) |
| 1209 | (save-excursion | 1313 | (setq statelist (cons state statelist)))))))) |
| 1210 | ;; This uses a semi-documented feature of dired; giving a switch | 1314 | (save-window-excursion |
| 1211 | ;; argument forces the buffer to refresh each time. | 1315 | (save-excursion |
| 1212 | (dired | 1316 | ;; First, kill any existing vc-dired buffers of this directory. |
| 1213 | (cons default-directory (nreverse filelist)) | 1317 | ;; (Code much like dired-find-buffer-nocreate.) |
| 1214 | dired-listing-switches) | 1318 | (let ((buffers (buffer-list)) |
| 1215 | (setq dired-buf (current-buffer)) | 1319 | (dir (expand-file-name default-directory))) |
| 1216 | (setq nonempty (not (zerop (buffer-size))))) | 1320 | (while buffers |
| 1321 | (if (buffer-name (car buffers)) | ||
| 1322 | (progn (set-buffer (car buffers)) | ||
| 1323 | (if (and (eq major-mode 'dired-mode) | ||
| 1324 | (string= dir | ||
| 1325 | (expand-file-name default-directory)) | ||
| 1326 | vc-dired-mode) | ||
| 1327 | (kill-buffer (car buffers))))) | ||
| 1328 | (setq buffers (cdr buffers))) | ||
| 1329 | ;; This uses a semi-documented feature of dired; giving a switch | ||
| 1330 | ;; argument forces the buffer to refresh each time. | ||
| 1331 | (dired | ||
| 1332 | (cons dir (nreverse filelist)) | ||
| 1333 | dired-listing-switches) | ||
| 1334 | (setq dired-buf (current-buffer)) | ||
| 1335 | (setq nonempty (not (eq 2 (count-lines (point-min) | ||
| 1336 | (point-max)))))))) | ||
| 1217 | (if nonempty | 1337 | (if nonempty |
| 1218 | (progn | 1338 | (progn |
| 1219 | (pop-to-buffer dired-buf) | 1339 | (switch-to-buffer dired-buf) |
| 1220 | (vc-dired-mode) | 1340 | (vc-dired-mode) |
| 1221 | (goto-char (point-min)) | 1341 | ;; Make a few aesthetical modifications to the header |
| 1222 | (setq buffer-read-only nil) | 1342 | (setq buffer-read-only nil) |
| 1223 | (forward-line 1) ;; Skip header line | 1343 | (goto-char (point-min)) |
| 1344 | (insert "\n") ;; Insert a blank line | ||
| 1345 | (forward-line 1) ;; Skip header line | ||
| 1346 | (let ((start (point))) ;; Erase (but don't remove) the | ||
| 1347 | (end-of-line) ;; "wildcard" line. | ||
| 1348 | (delete-region start (point))) | ||
| 1349 | (beginning-of-line) | ||
| 1350 | ;; Now plug the version information into the individual lines | ||
| 1224 | (mapcar | 1351 | (mapcar |
| 1225 | (function | 1352 | (function |
| 1226 | (lambda (x) | 1353 | (lambda (x) |
| 1227 | (forward-char 2) ;; skip dired's mark area | 1354 | (forward-char 2) ;; skip dired's mark area |
| 1228 | (vc-dired-reformat-line x) | 1355 | (vc-dired-reformat-line x) |
| 1229 | (forward-line 1))) ;; go to next line | 1356 | (forward-line 1))) ;; go to next line |
| 1230 | (nreverse userlist)) | 1357 | (nreverse statelist)) |
| 1231 | (setq buffer-read-only t) | 1358 | (setq buffer-read-only t) |
| 1232 | (goto-char (point-min)) | 1359 | (goto-char (point-min)) |
| 1360 | (dired-next-line 3) | ||
| 1233 | ) | 1361 | ) |
| 1362 | (kill-buffer dired-buf) | ||
| 1234 | (message "No files are currently %s under %s" | 1363 | (message "No files are currently %s under %s" |
| 1235 | (if verbose "registered" "locked") default-directory)) | 1364 | (if verbose "registered" "locked") default-directory)) |
| 1236 | )) | 1365 | )) |
| @@ -1619,6 +1748,8 @@ From a program, any arguments are passed to the `rcs2log' script." | |||
| 1619 | (vc-do-command nil 0 "get" file 'MASTER))) | 1748 | (vc-do-command nil 0 "get" file 'MASTER))) |
| 1620 | ((eq backend 'RCS) | 1749 | ((eq backend 'RCS) |
| 1621 | (vc-do-command nil 0 "ci" file 'MASTER ;; RCS | 1750 | (vc-do-command nil 0 "ci" file 'MASTER ;; RCS |
| 1751 | ;; if available, use the secure registering option | ||
| 1752 | (and (vc-backend-release-p 'RCS "5.6.4") "-i") | ||
| 1622 | (concat (if vc-keep-workfiles "-u" "-r") rev) | 1753 | (concat (if vc-keep-workfiles "-u" "-r") rev) |
| 1623 | (and comment (concat "-t-" comment)) | 1754 | (and comment (concat "-t-" comment)) |
| 1624 | file)) | 1755 | file)) |
| @@ -1825,6 +1956,8 @@ From a program, any arguments are passed to the `rcs2log' script." | |||
| 1825 | ;; RCS | 1956 | ;; RCS |
| 1826 | (let ((old-version (vc-workfile-version file)) new-version) | 1957 | (let ((old-version (vc-workfile-version file)) new-version) |
| 1827 | (apply 'vc-do-command nil 0 "ci" file 'MASTER | 1958 | (apply 'vc-do-command nil 0 "ci" file 'MASTER |
| 1959 | ;; if available, use the secure check-in option | ||
| 1960 | (and (vc-backend-release-p 'RCS "5.6.4") "-j") | ||
| 1828 | (concat (if vc-keep-workfiles "-u" "-r") rev) | 1961 | (concat (if vc-keep-workfiles "-u" "-r") rev) |
| 1829 | (concat "-m" comment) | 1962 | (concat "-m" comment) |
| 1830 | vc-checkin-switches) | 1963 | vc-checkin-switches) |
| @@ -1843,8 +1976,7 @@ From a program, any arguments are passed to the `rcs2log' script." | |||
| 1843 | (vc-file-setprop file 'vc-workfile-version new-version))) | 1976 | (vc-file-setprop file 'vc-workfile-version new-version))) |
| 1844 | 1977 | ||
| 1845 | ;; if we got to a different branch, adjust the default | 1978 | ;; if we got to a different branch, adjust the default |
| 1846 | ;; branch accordingly, and remove any remaining | 1979 | ;; branch accordingly |
| 1847 | ;; lock on the old version. | ||
| 1848 | (cond | 1980 | (cond |
| 1849 | ((and old-version new-version | 1981 | ((and old-version new-version |
| 1850 | (not (string= (vc-branch-part old-version) | 1982 | (not (string= (vc-branch-part old-version) |
| @@ -1852,10 +1984,13 @@ From a program, any arguments are passed to the `rcs2log' script." | |||
| 1852 | (vc-do-command nil 0 "rcs" file 'MASTER | 1984 | (vc-do-command nil 0 "rcs" file 'MASTER |
| 1853 | (if (vc-trunk-p new-version) "-b" | 1985 | (if (vc-trunk-p new-version) "-b" |
| 1854 | (concat "-b" (vc-branch-part new-version)))) | 1986 | (concat "-b" (vc-branch-part new-version)))) |
| 1855 | ;; exit status of 1 is also accepted. | 1987 | ;; If this is an old RCS release, we might have |
| 1856 | ;; It means that the lock was removed before. | 1988 | ;; to remove a remaining lock. |
| 1857 | (vc-do-command nil 1 "rcs" file 'MASTER | 1989 | (if (not (vc-backend-release-p 'RCS "5.6.2")) |
| 1858 | (concat "-u" old-version))))) | 1990 | ;; exit status of 1 is also accepted. |
| 1991 | ;; It means that the lock was removed before. | ||
| 1992 | (vc-do-command nil 1 "rcs" file 'MASTER | ||
| 1993 | (concat "-u" old-version)))))) | ||
| 1859 | ;; CVS | 1994 | ;; CVS |
| 1860 | (progn | 1995 | (progn |
| 1861 | ;; explicit check-in to the trunk requires a | 1996 | ;; explicit check-in to the trunk requires a |
| @@ -1991,18 +2126,20 @@ From a program, any arguments are passed to the `rcs2log' script." | |||
| 1991 | (if cmp (cdr options) options)) | 2126 | (if cmp (cdr options) options)) |
| 1992 | status))) | 2127 | status))) |
| 1993 | ;; CVS is different. | 2128 | ;; CVS is different. |
| 1994 | ;; cmp is not yet implemented -- we always do a full diff. | ||
| 1995 | ((eq backend 'CVS) | 2129 | ((eq backend 'CVS) |
| 1996 | (if (string= (vc-workfile-version file) "0") ;CVS | 2130 | (if (string= (vc-workfile-version file) "0") ;CVS |
| 1997 | ;; This file is added but not yet committed; there is no master file. | 2131 | ;; This file is added but not yet committed; there is no master file. |
| 1998 | ;; diff it against /dev/null. | ||
| 1999 | (if (or oldvers newvers) | 2132 | (if (or oldvers newvers) |
| 2000 | (error "No revisions of %s exists" file) | 2133 | (error "No revisions of %s exist" file) |
| 2001 | (apply 'vc-do-command | 2134 | (if cmp 1 ;; file is added but not committed, |
| 2002 | "*vc-diff*" 1 "diff" file 'WORKFILE "/dev/null" | 2135 | ;; we regard this as "changed". |
| 2003 | (if (listp diff-switches) | 2136 | ;; diff it against /dev/null. |
| 2004 | diff-switches | 2137 | (apply 'vc-do-command |
| 2005 | (list diff-switches)))) | 2138 | "*vc-diff*" 1 "diff" file 'WORKFILE |
| 2139 | (append (if (listp diff-switches) | ||
| 2140 | diff-switches | ||
| 2141 | (list diff-switches)) '("/dev/null"))))) | ||
| 2142 | ;; cmp is not yet implemented -- we always do a full diff. | ||
| 2006 | (apply 'vc-do-command | 2143 | (apply 'vc-do-command |
| 2007 | "*vc-diff*" 1 "cvs" file 'WORKFILE "diff" | 2144 | "*vc-diff*" 1 "cvs" file 'WORKFILE "diff" |
| 2008 | (and oldvers (concat "-r" oldvers)) | 2145 | (and oldvers (concat "-r" oldvers)) |
| @@ -2232,7 +2369,7 @@ Invoke FUNC f ARGS on each non-directory file f underneath it." | |||
| 2232 | ;;; B 5 . 6 7 8 co -l get -e checkout | 2369 | ;;; B 5 . 6 7 8 co -l get -e checkout |
| 2233 | ;;; C 9 10 . 11 12 co -u unget; get revert | 2370 | ;;; C 9 10 . 11 12 co -u unget; get revert |
| 2234 | ;;; D 13 14 15 . 16 ci -u -m<comment> delta -y<comment>; get checkin | 2371 | ;;; D 13 14 15 . 16 ci -u -m<comment> delta -y<comment>; get checkin |
| 2235 | ;;; E 17 18 19 20 . rcs -u -M ; rcs -l unget -n ; get -g steal lock | 2372 | ;;; E 17 18 19 20 . rcs -u -M -l unget -n ; get -g steal lock |
| 2236 | ;;; | 2373 | ;;; |
| 2237 | ;;; All commands take the master file name as a last argument (not shown). | 2374 | ;;; All commands take the master file name as a last argument (not shown). |
| 2238 | ;;; | 2375 | ;;; |
| @@ -2290,7 +2427,9 @@ Invoke FUNC f ARGS on each non-directory file f underneath it." | |||
| 2290 | ;;; Potential cause: someone else's admin during window P, with | 2427 | ;;; Potential cause: someone else's admin during window P, with |
| 2291 | ;;; caller's admin happening before their checkout. | 2428 | ;;; caller's admin happening before their checkout. |
| 2292 | ;;; | 2429 | ;;; |
| 2293 | ;;; RCS: ci will fail with a "no lock set by <user>" message. | 2430 | ;;; RCS: Prior to version 5.6.4, ci fails with message |
| 2431 | ;;; "no lock set by <user>". From 5.6.4 onwards, VC uses the new | ||
| 2432 | ;;; ci -i option and the message is "<file>,v: already exists". | ||
| 2294 | ;;; SCCS: admin will fail with error (ad19). | 2433 | ;;; SCCS: admin will fail with error (ad19). |
| 2295 | ;;; | 2434 | ;;; |
| 2296 | ;;; We can let these errors be passed up to the user. | 2435 | ;;; We can let these errors be passed up to the user. |
| @@ -2299,7 +2438,9 @@ Invoke FUNC f ARGS on each non-directory file f underneath it." | |||
| 2299 | ;;; | 2438 | ;;; |
| 2300 | ;;; Potential cause: self-race during window P. | 2439 | ;;; Potential cause: self-race during window P. |
| 2301 | ;;; | 2440 | ;;; |
| 2302 | ;;; RCS: will revert the file to the last saved version and unlock it. | 2441 | ;;; RCS: Prior to version 5.6.4, reverts the file to the last saved |
| 2442 | ;;; version and unlocks it. From 5.6.4 onwards, VC uses the new | ||
| 2443 | ;;; ci -i option, failing with message "<file>,v: already exists". | ||
| 2303 | ;;; SCCS: will fail with error (ad19). | 2444 | ;;; SCCS: will fail with error (ad19). |
| 2304 | ;;; | 2445 | ;;; |
| 2305 | ;;; Either of these consequences is acceptable. | 2446 | ;;; Either of these consequences is acceptable. |
| @@ -2308,8 +2449,10 @@ Invoke FUNC f ARGS on each non-directory file f underneath it." | |||
| 2308 | ;;; | 2449 | ;;; |
| 2309 | ;;; Potential cause: self-race during window P. | 2450 | ;;; Potential cause: self-race during window P. |
| 2310 | ;;; | 2451 | ;;; |
| 2311 | ;;; RCS: will register the caller's workfile as a delta with a | 2452 | ;;; RCS: Prior to version 5.6.4, VC registers the caller's workfile as |
| 2312 | ;;; null change comment (the -t- switch will be ignored). | 2453 | ;;; a delta with a null change comment (the -t- switch will be |
| 2454 | ;;; ignored). From 5.6.4 onwards, VC uses the new ci -i option, | ||
| 2455 | ;;; failing with message "<file>,v: already exists". | ||
| 2313 | ;;; SCCS: will fail with error (ad19). | 2456 | ;;; SCCS: will fail with error (ad19). |
| 2314 | ;;; | 2457 | ;;; |
| 2315 | ;;; 4. File looked unregistered but is locked by someone else. | 2458 | ;;; 4. File looked unregistered but is locked by someone else. |
| @@ -2317,7 +2460,10 @@ Invoke FUNC f ARGS on each non-directory file f underneath it." | |||
| 2317 | ;;; Potential cause: someone else's admin during window P, with | 2460 | ;;; Potential cause: someone else's admin during window P, with |
| 2318 | ;;; caller's admin happening *after* their checkout. | 2461 | ;;; caller's admin happening *after* their checkout. |
| 2319 | ;;; | 2462 | ;;; |
| 2320 | ;;; RCS: will fail with a "no lock set by <user>" message. | 2463 | ;;; RCS: Prior to version 5.6.4, ci fails with a |
| 2464 | ;;; "no lock set by <user>" message. From 5.6.4 onwards, | ||
| 2465 | ;;; VC uses the new ci -i option, failing with message | ||
| 2466 | ;;; "<file>,v: already exists". | ||
| 2321 | ;;; SCCS: will fail with error (ad19). | 2467 | ;;; SCCS: will fail with error (ad19). |
| 2322 | ;;; | 2468 | ;;; |
| 2323 | ;;; We can let these errors be passed up to the user. | 2469 | ;;; We can let these errors be passed up to the user. |
| @@ -2405,11 +2551,13 @@ Invoke FUNC f ARGS on each non-directory file f underneath it." | |||
| 2405 | ;;; | 2551 | ;;; |
| 2406 | ;;; Potential cause: master file got nuked during window P. | 2552 | ;;; Potential cause: master file got nuked during window P. |
| 2407 | ;;; | 2553 | ;;; |
| 2408 | ;;; RCS: Checks in the user's version as an initial delta. | 2554 | ;;; RCS: Prior to version 5.6.4, checks in the user's version as an |
| 2555 | ;;; initial delta. From 5.6.4 onwards, VC uses the new ci -j | ||
| 2556 | ;;; option, failing with message "no such file or directory". | ||
| 2409 | ;;; SCCS: will fail with error ut4. | 2557 | ;;; SCCS: will fail with error ut4. |
| 2410 | ;;; | 2558 | ;;; |
| 2411 | ;;; This case is kind of nasty. It means VC may fail to detect the | 2559 | ;;; This case is kind of nasty. Under RCS prior to version 5.6.4, |
| 2412 | ;;; loss of previous version information. | 2560 | ;;; VC may fail to detect the loss of previous version information. |
| 2413 | ;;; | 2561 | ;;; |
| 2414 | ;;; 14. File looks like it's locked by the calling user and changed, but it's | 2562 | ;;; 14. File looks like it's locked by the calling user and changed, but it's |
| 2415 | ;;; actually unlocked. | 2563 | ;;; actually unlocked. |
| @@ -2476,7 +2624,7 @@ Invoke FUNC f ARGS on each non-directory file f underneath it." | |||
| 2476 | ;;; | 2624 | ;;; |
| 2477 | ;;; In order of decreasing severity: | 2625 | ;;; In order of decreasing severity: |
| 2478 | ;;; | 2626 | ;;; |
| 2479 | ;;; Cases 11 and 15 under RCS are the only one that potentially lose work. | 2627 | ;;; Cases 11 and 15 are the only ones that potentially lose work. |
| 2480 | ;;; They would require a self-race for this to happen. | 2628 | ;;; They would require a self-race for this to happen. |
| 2481 | ;;; | 2629 | ;;; |
| 2482 | ;;; Case 13 in RCS loses information about previous deltas, retaining | 2630 | ;;; Case 13 in RCS loses information about previous deltas, retaining |