aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond2007-10-10 13:17:53 +0000
committerEric S. Raymond2007-10-10 13:17:53 +0000
commitd7b60083ce07eb9d4af2bdb97c1062e42445f395 (patch)
treed2f4e53f66b9423c908fb25c828f6fac24347352
parent84062ef1fea8e708c12a0e087c48b9e589690a99 (diff)
downloademacs-d7b60083ce07eb9d4af2bdb97c1062e42445f395.tar.gz
emacs-d7b60083ce07eb9d4af2bdb97c1062e42445f395.zip
Merge in new VC with filesets.
-rwxr-xr-xconfigure12
-rw-r--r--lisp/ChangeLog51
-rw-r--r--lisp/vc.el1092
3 files changed, 594 insertions, 561 deletions
diff --git a/configure b/configure
index e90fb524bb5..0a1a0cc97ed 100755
--- a/configure
+++ b/configure
@@ -18532,11 +18532,13 @@ _ACEOF
18532cat confdefs.h >>conftest.$ac_ext 18532cat confdefs.h >>conftest.$ac_ext
18533cat >>conftest.$ac_ext <<_ACEOF 18533cat >>conftest.$ac_ext <<_ACEOF
18534/* end confdefs.h. */ 18534/* end confdefs.h. */
18535#include <stdio.h> 18535#include <sys/types.h> /* for off_t */
18536 #include <stdio.h>
18536int 18537int
18537main () 18538main ()
18538{ 18539{
18539return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); 18540int (*fp) (FILE *, off_t, int) = fseeko;
18541 return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
18540 ; 18542 ;
18541 return 0; 18543 return 0;
18542} 18544}
@@ -18576,11 +18578,13 @@ cat confdefs.h >>conftest.$ac_ext
18576cat >>conftest.$ac_ext <<_ACEOF 18578cat >>conftest.$ac_ext <<_ACEOF
18577/* end confdefs.h. */ 18579/* end confdefs.h. */
18578#define _LARGEFILE_SOURCE 1 18580#define _LARGEFILE_SOURCE 1
18579#include <stdio.h> 18581#include <sys/types.h> /* for off_t */
18582 #include <stdio.h>
18580int 18583int
18581main () 18584main ()
18582{ 18585{
18583return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); 18586int (*fp) (FILE *, off_t, int) = fseeko;
18587 return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
18584 ; 18588 ;
18585 return 0; 18589 return 0;
18586} 18590}
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 8bf8c4a9342..77642d58232 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,54 @@
12007-10-10 Eric S. Raymond <esr@snark.thyrsus.com>
2
3 * vc.el (vc-next-action): Completely rewritten; this principal
4 entry point now operates on a current fileset selected either
5 explicitly via VC-Dired or implicitly by visiting a file buffer,
6 rather than always operating on the file of the current buffer as
7 in older versions. The rest of the mode has been rewritten to
8 match.
9 (with-vc-properties): Rewritten to operate on a file list.
10 (with-vc-file): vc-checkin takes a file list argument now.
11 (vc-post-command-functions): This hook now receives a file list.
12 (vc-do-command): Now takes a either a file or a file list as
13 argument.
14 (vc-deduce-fileset): New function for deducing a file list to
15 operate on.
16 (vc-next-action-on-file): This function is gone, it is merged into
17 vc-next-action.
18 (vc-next-action-dired): This function is gone, it is merged into
19 vc-next-action.
20 (vc-register): Adapted to the fact that vc-start-entry now takes a
21 file list.
22 (vc-register-with): New function.
23 (vc-start-entry): Now takes a file list argument rather than a
24 file argument.
25 (vc-checkout): Modified to cope with vc-start-entry taking a file
26 list.
27 (vc-steal-lock): Modified to cope with with-vc-properties taking a
28 file list.
29 (vc-checkin): Now takes a file list argument rather than a file
30 argument.
31 (vc-finish-logentry): Use the filelist passed by vc-start-entry.
32 (vc-diff-internal): Completely rewritten for filesets.
33 (vc-diff-sentinel): New function, tests whether changes were
34 written into a diff buffer.
35 (vc-diff): Completely rewritten for filesets.
36 (vc-version-diff): Completely rewritten for filesets.
37 (vc-print-log): Now takes a fileset argument.
38 (vc-revert): Now reverts the entire selected fileset, not just the
39 current buffer.
40 (vc-rollback): Now rolls back the entire selected fileset, if
41 possible. No longer accepts a prefix argument.
42 (vc-update): Now merges new changes for the entire selected
43 fileset, not just the current buffer.
44 (vc-revert-file): Modified to cope with with-vc-properties taking
45 a file list.
46 (vc-default-dired-state-info): Add + status suffix if the file is
47 modified.
48 (vc-annotate-warp-version): Use the new diff machinery.
49 (vc-log-edit): Now takes a file list argument rather than a file
50 argument.
51
12007-10-10 Michael Albinus <michael.albinus@gmx.de> 522007-10-10 Michael Albinus <michael.albinus@gmx.de>
2 53
3 Sync with Tramp 2.1.11. 54 Sync with Tramp 2.1.11.
diff --git a/lisp/vc.el b/lisp/vc.el
index bfcea833c9d..d88852eb8c8 100644
--- a/lisp/vc.el
+++ b/lisp/vc.el
@@ -7,6 +7,8 @@
7;; Maintainer: Andre Spiegel <spiegel@gnu.org> 7;; Maintainer: Andre Spiegel <spiegel@gnu.org>
8;; Keywords: tools 8;; Keywords: tools
9 9
10;; $Id: vc.el,v 1.139 2007/10/10 13:14:41 esr Exp $
11
10;; This file is part of GNU Emacs. 12;; This file is part of GNU Emacs.
11 13
12;; GNU Emacs is free software; you can redistribute it and/or modify 14;; GNU Emacs is free software; you can redistribute it and/or modify
@@ -360,17 +362,17 @@
360;; default implementation runs rcs2log, which handles RCS- and 362;; default implementation runs rcs2log, which handles RCS- and
361;; CVS-style logs. 363;; CVS-style logs.
362;; 364;;
363;; * diff (file &optional rev1 rev2 buffer) 365;; * diff (files &optional rev1 rev2 buffer)
364;; 366;;
365;; Insert the diff for FILE into BUFFER, or the *vc-diff* buffer if 367;; Insert the diff for FILE into BUFFER, or the *vc-diff* buffer if
366;; BUFFER is nil. If REV1 and REV2 are non-nil, report differences 368;; BUFFER is nil. If REV1 and REV2 are non-nil, report differences
367;; from REV1 to REV2. If REV1 is nil, use the focus version (as 369;; from REV1 to REV2. If REV1 is nil, use the current focus
368;; found in the repository) as the older version; if REV2 is nil, 370;; version (as found in the repository) as the older version; if
369;; use the current working-copy contents as the newer version. This 371;; REV2 is nil, use the current working-copy contents as the newer
370;; function should pass the value of (vc-switches BACKEND 'diff) to 372;; version. This function should pass the value of (vc-switches
371;; the backend command. It should return a status of either 0 (no 373;; BACKEND 'diff) to the backend command. It should return a status
372;; differences found), or 1 (either non-empty diff or the diff is 374;; of either 0 (no differences found), or 1 (either non-empty diff
373;; run asynchronously). 375;; or the diff is run asynchronously).
374;; 376;;
375;; - revision-completion-table (file) 377;; - revision-completion-table (file)
376;; 378;;
@@ -835,7 +837,7 @@ and that its contents match what the master file says."
835Backends that offer asynchronous diffs should respect this variable 837Backends that offer asynchronous diffs should respect this variable
836in their implementation of vc-BACKEND-diff.") 838in their implementation of vc-BACKEND-diff.")
837 839
838(defvar vc-log-file) 840(defvar vc-log-fileset)
839(defvar vc-log-version) 841(defvar vc-log-version)
840 842
841(defvar vc-dired-mode nil) 843(defvar vc-dired-mode nil)
@@ -848,20 +850,21 @@ in their implementation of vc-BACKEND-diff.")
848 (interactive) 850 (interactive)
849 (fillarray vc-file-prop-obarray 0)) 851 (fillarray vc-file-prop-obarray 0))
850 852
851(defmacro with-vc-properties (file form settings) 853(defmacro with-vc-properties (files form settings)
852 "Execute FORM, then maybe set per-file properties for FILE. 854 "Execute FORM, then maybe set per-file properties for FILES.
853SETTINGS is an association list of property/value pairs. After 855SETTINGS is an association list of property/value pairs. After
854executing FORM, set those properties from SETTINGS that have not yet 856executing FORM, set those properties from SETTINGS that have not yet
855been updated to their corresponding values." 857been updated to their corresponding values."
856 (declare (debug t)) 858 (declare (debug t))
857 `(let ((vc-touched-properties (list t))) 859 `(let ((vc-touched-properties (list t)))
858 ,form 860 ,form
859 (mapcar (lambda (setting) 861 (dolist (file ,files)
862 (mapc (lambda (setting)
860 (let ((property (car setting))) 863 (let ((property (car setting)))
861 (unless (memq property vc-touched-properties) 864 (unless (memq property vc-touched-properties)
862 (put (intern ,file vc-file-prop-obarray) 865 (put (intern ,file vc-file-prop-obarray)
863 property (cdr setting))))) 866 property (cdr setting)))))
864 ,settings))) 867 ,settings))))
865 868
866;; Two macros for elisp programming 869;; Two macros for elisp programming
867 870
@@ -885,7 +888,7 @@ somebody else, signal error."
885 (vc-checkout ,filevar t)))) 888 (vc-checkout ,filevar t))))
886 (save-excursion 889 (save-excursion
887 ,@body) 890 ,@body)
888 (vc-checkin ,filevar nil ,comment)))) 891 (vc-checkin (list ,filevar) nil ,comment))))
889 892
890;;;###autoload 893;;;###autoload
891(defmacro edit-vc-file (file comment &rest body) 894(defmacro edit-vc-file (file comment &rest body)
@@ -988,7 +991,7 @@ Else, add CODE to the process' sentinel."
988(defvar vc-post-command-functions nil 991(defvar vc-post-command-functions nil
989 "Hook run at the end of `vc-do-command'. 992 "Hook run at the end of `vc-do-command'.
990Each function is called inside the buffer in which the command was run 993Each function is called inside the buffer in which the command was run
991and is passed 3 arguments: the COMMAND, the FILE and the FLAGS.") 994and is passed 3 arguments: the COMMAND, the FILES and the FLAGS.")
992 995
993(defvar w32-quote-process-args) 996(defvar w32-quote-process-args)
994 997
@@ -1016,10 +1019,17 @@ that is inserted into the command line before the filename."
1016 (let* ((files 1019 (let* ((files
1017 (mapcar (lambda (f) (file-relative-name (expand-file-name f))) 1020 (mapcar (lambda (f) (file-relative-name (expand-file-name f)))
1018 (if (listp file-or-list) file-or-list (list file-or-list)))) 1021 (if (listp file-or-list) file-or-list (list file-or-list))))
1019 (full-command 1022 (full-command
1020 (concat command " " (vc-delistify flags) " " (vc-delistify files)))) 1023 ;; What we're doing here is preparing a version of the command
1021 (if vc-command-messages 1024 ;; for display in a debug-progess message. If it's fewer than
1022 (message "Running %s..." full-command)) 1025 ;; 20 characters display the entire command (without trailing
1026 ;; newline). Otherwise display the first 20 followed by an ellipsis.
1027 (concat (if (string= (substring command -1) "\n")
1028 (substring command 0 -1)
1029 command)
1030 " "
1031 (vc-delistify (mapcar (lambda (s) (if (> (length s) 20) (concat (substring s 0 2) "...") s)) flags))
1032 " " (vc-delistify files))))
1023 (save-current-buffer 1033 (save-current-buffer
1024 (unless (or (eq buffer t) 1034 (unless (or (eq buffer t)
1025 (and (stringp buffer) 1035 (and (stringp buffer)
@@ -1048,13 +1058,16 @@ that is inserted into the command line before the filename."
1048 (let ((process-connection-type nil)) 1058 (let ((process-connection-type nil))
1049 (apply 'start-process command (current-buffer) command 1059 (apply 'start-process command (current-buffer) command
1050 squeezed)))) 1060 squeezed))))
1051 (unless (active-minibuffer-window) 1061 (if vc-command-messages
1052 (message "Running %s in the background..." full-command)) 1062 (message "Running %s in background..." full-command))
1053 ;;(set-process-sentinel proc (lambda (p msg) (delete-process p))) 1063 ;;(set-process-sentinel proc (lambda (p msg) (delete-process p)))
1054 (set-process-filter proc 'vc-process-filter) 1064 (set-process-filter proc 'vc-process-filter)
1055 (vc-exec-after 1065 (vc-exec-after
1056 `(unless (active-minibuffer-window) 1066 `(if vc-command-messages
1057 (message "Running %s in the background... done" ',full-command)))) 1067 (message "Running %s in background... done" ',full-command))))
1068 ;; Run synchrously
1069 (if vc-command-messages
1070 (message "Running %s in foreground..." full-command))
1058 (let ((buffer-undo-list t)) 1071 (let ((buffer-undo-list t))
1059 (setq status (apply 'process-file command nil t nil squeezed))) 1072 (setq status (apply 'process-file command nil t nil squeezed)))
1060 (when (and (not (eq t okstatus)) 1073 (when (and (not (eq t okstatus))
@@ -1065,11 +1078,12 @@ that is inserted into the command line before the filename."
1065 (shrink-window-if-larger-than-buffer) 1078 (shrink-window-if-larger-than-buffer)
1066 (error "Running %s...FAILED (%s)" full-command 1079 (error "Running %s...FAILED (%s)" full-command
1067 (if (integerp status) (format "status %d" status) status)))) 1080 (if (integerp status) (format "status %d" status) status))))
1081 ;; We're done
1068 (if vc-command-messages 1082 (if vc-command-messages
1069 (message "Running %s...OK" full-command))) 1083 (message "Running %s...OK = %d" full-command status)))
1070 (vc-exec-after 1084 (vc-exec-after
1071 `(run-hook-with-args 'vc-post-command-functions 1085 `(run-hook-with-args 'vc-post-command-functions
1072 ',command ',file-or-list ',flags)) 1086 ',command ',file-or-list ',flags))
1073 status)))) 1087 status))))
1074 1088
1075(defun vc-position-context (posn) 1089(defun vc-position-context (posn)
@@ -1186,6 +1200,8 @@ CONTEXT is that which `vc-buffer-context' returns."
1186 (let ((new-mark (vc-find-position-by-context mark-context))) 1200 (let ((new-mark (vc-find-position-by-context mark-context)))
1187 (if new-mark (set-mark new-mark)))))) 1201 (if new-mark (set-mark new-mark))))))
1188 1202
1203;;; Code for deducing what fileset and backend to assume
1204
1189(defun vc-responsible-backend (file &optional register) 1205(defun vc-responsible-backend (file &optional register)
1190 "Return the name of a backend system that is responsible for FILE. 1206 "Return the name of a backend system that is responsible for FILE.
1191The optional argument REGISTER means that a backend suitable for 1207The optional argument REGISTER means that a backend suitable for
@@ -1234,6 +1250,50 @@ Only files already under version control are noticed."
1234 node (lambda (f) (if (vc-backend f) (push f flattened))))) 1250 node (lambda (f) (if (vc-backend f) (push f flattened)))))
1235 (nreverse flattened))) 1251 (nreverse flattened)))
1236 1252
1253(defun vc-deduce-fileset (&optional allow-directory-wildcard)
1254 "Deduce a set of files and a backend to apply an operation to.
1255
1256If we're in VC-dired-mode, the fileset is the list of marked
1257files. Otherwise, if we're looking at a buffer visiting a
1258version-controlled file. the fileset is a singleton containing
1259the relative filename, throw an error.
1260
1261If neither of these things is true, but allow-directory-wildcard is on,
1262select all files under version control at and below the current
1263directory.
1264
1265Otherwise, throw an error.
1266"
1267 (cond (vc-dired-mode
1268 (let ((regexp (dired-marker-regexp))
1269 (marked (dired-map-over-marks (dired-get-filename) nil)))
1270 (unless marked
1271 (error "No files have been selected."))
1272 ;; All members of the fileset must have the same backend
1273 (let ((firstbackend (vc-backend (car marked))))
1274 (mapc (lambda (f) (unless (eq (vc-backend f) firstbackend)
1275 (error "All members of a fileset must be under the same version-control system.")))
1276 (cdr marked)))
1277 marked))
1278 ((vc-backend buffer-file-name)
1279 (list buffer-file-name))
1280 ((and vc-parent-buffer (buffer-file-name vc-parent-buffer))
1281 (progn
1282 (set-buffer vc-parent-buffer)
1283 (vc-deduce-fileset)))
1284 ;; This is guarded by an enabling arg so users won't potentially
1285 ;; shoot themselves in the foot by modifying a fileset they can't
1286 ;; verify by eyeball. Allow it for nondestructive commands like
1287 ;; making diffs, or possibly for destructive ones that have
1288 ;; confirmation prompts.
1289 (allow-directory-wildcard
1290 (progn
1291 (setq marked (list default-directory))
1292 (message "All version-controlled files below %s selected."
1293 default-directory)
1294 (list default-directory)))
1295 (t (error "No fileset is available here."))))
1296
1237(defun vc-ensure-vc-buffer () 1297(defun vc-ensure-vc-buffer ()
1238 "Make sure that the current buffer visits a version-controlled file." 1298 "Make sure that the current buffer visits a version-controlled file."
1239 (if vc-dired-mode 1299 (if vc-dired-mode
@@ -1287,192 +1347,170 @@ NOT-URGENT means it is ok to continue if the user says not to save."
1287 1347
1288;;;###autoload 1348;;;###autoload
1289(defun vc-next-action (verbose) 1349(defun vc-next-action (verbose)
1290 "Do the next logical version control operation on the current file. 1350 "Do the next logical version control operation on the current fileset.
1291 1351This requires that all files in the fileset be in the same state.
1292If you call this from within a VC dired buffer with no files marked,
1293it will operate on the file in the current line.
1294 1352
1295If you call this from within a VC dired buffer, and one or more 1353For locking systems:
1296files are marked, it will accept a log message and then operate on 1354 If every file is not already registered, this registers each for version
1297each one. The log message will be used as a comment for any register
1298or checkin operations, but ignored when doing checkouts. Attempted
1299lock steals will raise an error.
1300
1301A prefix argument lets you specify the version number to use.
1302
1303For RCS and SCCS files:
1304 If the file is not already registered, this registers it for version
1305control. 1355control.
1306 If the file is registered and not locked by anyone, this checks out 1356 If every file is registered and not locked by anyone, this checks out
1307a writable and locked file ready for editing. 1357a writable and locked file of each ready for editing.
1308 If the file is checked out and locked by the calling user, this 1358 If every file is checked out and locked by the calling user, this
1309first checks to see if the file has changed since checkout. If not, 1359first checks to see if each file has changed since checkout. If not,
1310it performs a revert. 1360it performs a revert on that file.
1311 If the file has been changed, this pops up a buffer for entry 1361 If every file has been changed, this pops up a buffer for entry
1312of a log message; when the message has been entered, it checks in the 1362of a log message; when the message has been entered, it checks in the
1313resulting changes along with the log message as change commentary. If 1363resulting changes along with the log message as change commentary. If
1314the variable `vc-keep-workfiles' is non-nil (which is its default), a 1364the variable `vc-keep-workfiles' is non-nil (which is its default), a
1315read-only copy of the changed file is left in place afterwards. 1365read-only copy of each changed file is left in place afterwards.
1316 If the file is registered and locked by someone else, you are given 1366 If the affected file is registered and locked by someone else, you are
1317the option to steal the lock. 1367given the option to steal the lock(s).
1318 1368
1319For CVS files: 1369For merging systems:
1320 If the file is not already registered, this registers it for version 1370 If every file is not already registered, this registers each one for version
1321control. This does a \"cvs add\", but no \"cvs commit\". 1371control. This does an add, but not a commit.
1322 If the file is added but not committed, it is committed. 1372 If every file is added but not committed, each one is committed.
1323 If your working file is changed, but the repository file is 1373 If every working file is changed, but the corresponding repository file is
1324unchanged, this pops up a buffer for entry of a log message; when the 1374unchanged, this pops up a buffer for entry of a log message; when the
1325message has been entered, it checks in the resulting changes along 1375message has been entered, it checks in the resulting changes along
1326with the logmessage as change commentary. A writable file is retained. 1376with the logmessage as change commentary. A writable file is retained.
1327 If the repository file is changed, you are asked if you want to 1377 If the repository file is changed, you are asked if you want to
1328merge in the changes into your working copy." 1378merge in the changes into your working copy."
1329 (interactive "P") 1379 (interactive "P")
1330 (catch 'nogo 1380 (let* ((files (vc-deduce-fileset))
1331 (if vc-dired-mode 1381 (backend (vc-backend (car files)))
1332 (let ((files (dired-get-marked-files))) 1382 (state (vc-state (car files)))
1333 (set (make-local-variable 'vc-dired-window-configuration) 1383 (model (vc-checkout-model (car files)))
1334 (current-window-configuration)) 1384 version)
1335 (if (string= "" 1385 ;; Verify that the fileset is homogenous
1336 (mapconcat 1386 (dolist (file (cdr files))
1337 (lambda (f) 1387 (if (not (eq (vc-state file) state))
1338 (if (not (vc-up-to-date-p f)) "@" "")) 1388 (error "Fileset is in a mixed-up state"))
1339 files "")) 1389 (if (not (eq (vc-checkout-model file) model))
1340 (vc-next-action-dired nil nil "dummy") 1390 (error "Fileset has mixed checkout models")))
1341 (vc-start-entry nil nil nil nil 1391 ;; Check for buffers in the fileset not matching the on-disk contents.
1342 "Enter a change comment for the marked files." 1392 (dolist (file files)
1343 'vc-next-action-dired)) 1393 (let ((visited (get-file-buffer file)))
1344 (throw 'nogo nil))) 1394 (when visited
1345 (while vc-parent-buffer 1395 (if vc-dired-mode
1346 (pop-to-buffer vc-parent-buffer)) 1396 (switch-to-buffer-other-window visited)
1347 (if buffer-file-name 1397 (set-buffer visited))
1348 (vc-next-action-on-file buffer-file-name verbose) 1398 ;; Check relation of buffer and file, and make sure
1349 (error "Buffer %s is not associated with a file" (buffer-name))))) 1399 ;; user knows what he's doing. First, finding the file
1350 1400 ;; will check whether the file on disk is newer.
1351;; These functions help the vc-next-action entry point 1401 ;; Ignore buffer-read-only during this test, and
1352 1402 ;; preserve find-file-literally.
1353(defun vc-next-action-on-file (file verbose &optional comment) 1403 (let ((buffer-read-only (not (file-writable-p file))))
1354 "Do The Right Thing for a given FILE under version control. 1404 (find-file-noselect file nil find-file-literally))
1355If COMMENT is specified, it will be used as an admin or checkin comment. 1405 (if (not (verify-visited-file-modtime (current-buffer)))
1356If VERBOSE is non-nil, query the user rather than using default parameters." 1406 (if (yes-or-no-p (format "Replace %s on disk with buffer contents? " file))
1357 (let ((visited (get-file-buffer file)) 1407 (write-file buffer-file-name)
1358 state version) 1408 (error "Aborted"))
1359 (when visited 1409 ;; Now, check if we have unsaved changes.
1360 (if vc-dired-mode 1410 (vc-buffer-sync t)
1361 (switch-to-buffer-other-window visited) 1411 (if (buffer-modified-p)
1362 (set-buffer visited)) 1412 (or (y-or-n-p (message "Use %s on disk, keeping modified buffer? " file))
1363 ;; Check relation of buffer and file, and make sure 1413 (error "Aborted")))))))
1364 ;; user knows what he's doing. First, finding the file
1365 ;; will check whether the file on disk is newer.
1366 ;; Ignore buffer-read-only during this test, and
1367 ;; preserve find-file-literally.
1368 (let ((buffer-read-only (not (file-writable-p file))))
1369 (find-file-noselect file nil find-file-literally))
1370 (if (not (verify-visited-file-modtime (current-buffer)))
1371 (if (yes-or-no-p "Replace file on disk with buffer contents? ")
1372 (write-file buffer-file-name)
1373 (error "Aborted"))
1374 ;; Now, check if we have unsaved changes.
1375 (vc-buffer-sync t)
1376 (if (buffer-modified-p)
1377 (or (y-or-n-p "Operate on disk file, keeping modified buffer? ")
1378 (error "Aborted")))))
1379
1380 ;; Do the right thing 1414 ;; Do the right thing
1381 (if (not (vc-registered file)) 1415 (cond
1382 (vc-register verbose comment) 1416 ;; Files aren't registered
1383 (vc-recompute-state file) 1417 ((not state)
1384 (if visited (vc-mode-line file)) 1418 (mapc 'vc-register files))
1385 (setq state (vc-state file)) 1419 ;; Files are up-to-date, or need a merge and user specified a version
1420 ((or (eq state 'up-to-date) (and verbose (eq state 'needs-patch)))
1386 (cond 1421 (cond
1387 ;; up-to-date 1422 (verbose
1388 ((or (eq state 'up-to-date) 1423 ;; go to a different version
1389 (and verbose (eq state 'needs-patch))) 1424 (setq version (read-string "Branch, version, or backend to move to: "))
1390 (cond 1425 (let ((vsym (intern-soft (upcase version))))
1391 (verbose 1426 (if (member vsym vc-handled-backends)
1392 ;; go to a different version 1427 (mapc (lambda (file) vc-transfer-file file vsym) files)
1393 (setq version 1428 (mapc (lambda (file)
1394 (read-string "Branch, version, or backend to move to: ")) 1429 (vc-checkout file (eq model 'implicit) version))))))
1395 (let ((vsym (intern-soft (upcase version)))) 1430 ((not (eq model 'implicit))
1396 (if (member vsym vc-handled-backends) 1431 ;; check the files out
1397 (vc-transfer-file file vsym) 1432 (mapc (lambda (file) (vc-checkout file t)) files))
1398 (vc-checkout file (eq (vc-checkout-model file) 'implicit) 1433 (t
1399 version)))) 1434 ;; do nothing
1400 ((not (eq (vc-checkout-model file) 'implicit)) 1435 (message "Fileset is up-to-date"))))
1401 ;; check the file out 1436 ;; Files have local changes
1402 (vc-checkout file t)) 1437 ((eq state 'edited)
1403 (t 1438 (let ((ready-for-commit files))
1404 ;; do nothing 1439 ;; If files are edited but read-only, give user a chance to correct
1405 (message "%s is up-to-date" file)))) 1440 (dolist (file files)
1406 1441 (if (not (file-writable-p file))
1407 ;; Abnormal: edited but read-only 1442 (progn
1408 ((and visited (eq state 'edited) 1443 ;; Make the file+buffer read-write.
1409 buffer-read-only (not (file-writable-p file))) 1444 (unless (y-or-no-p (format "%s is edited but read-only; make it writable and continue?" file))
1410 ;; Make the file+buffer read-write. If the user really wanted to 1445 (error "Aborted"))
1411 ;; commit, he'll get a chance to do that next time around, anyway. 1446 (set-file-modes file (logior (file-modes file) 128))
1412 (message "File is edited but read-only; making it writable") 1447 (let ((visited (get-file-buffer file)))
1413 (set-file-modes buffer-file-name 1448 (if visited
1414 (logior (file-modes buffer-file-name) 128)) 1449 (save-excursion
1415 (toggle-read-only -1)) 1450 (set-buffer visited)
1416 1451 (toggle-read-only -1)))))))
1417 ;; edited 1452 ;; Allow user to revert files with no changes
1418 ((eq state 'edited) 1453 (save-excursion
1419 (cond 1454 (let ((revertlist '()))
1420 ;; For files with locking, if the file does not contain 1455 (dolist (file files)
1421 ;; any changes, just let go of the lock, i.e. revert. 1456 (let ((visited (get-file-buffer file)))
1422 ((and (not (eq (vc-checkout-model file) 'implicit)) 1457 ;; For files with locking, if the file does not contain
1423 (vc-workfile-unchanged-p file) 1458 ;; any changes, just let go of the lock, i.e. revert.
1424 ;; If buffer is modified, that means the user just 1459 (if (and (not (eq model 'implicit))
1425 ;; said no to saving it; in that case, don't revert, 1460 (vc-workfile-unchanged-p file)
1426 ;; because the user might intend to save after 1461 ;; If buffer is modified, that means the user just
1427 ;; finishing the log entry. 1462 ;; said no to saving it; in that case, don't revert,
1428 (not (and visited (buffer-modified-p)))) 1463 ;; because the user might intend to save after
1429 ;; DO NOT revert the file without asking the user! 1464 ;; finishing the log entry and committing.
1430 (if (not visited) (find-file-other-window file)) 1465 (not (and visited (buffer-modified-p))))
1431 (if (yes-or-no-p "Revert to master version? ") 1466 (progn
1432 (vc-revert))) 1467 (vc-revert-file file)
1433 (t ;; normal action 1468 (delete file ready-for-commit)))))))
1469 ;; Remaining files need to be committed
1470 (if (not ready-for-commit)
1471 (message "No files remain to be committed")
1434 (if (not verbose) 1472 (if (not verbose)
1435 (vc-checkin file nil comment) 1473 (vc-checkin ready-for-commit)
1436 (setq version (read-string "New version or backend: ")) 1474 (progn
1437 (let ((vsym (intern (upcase version)))) 1475 (setq version (read-string "New version or backend: "))
1438 (if (member vsym vc-handled-backends) 1476 (let ((vsym (intern (upcase version))))
1439 (vc-transfer-file file vsym) 1477 (if (member vsym vc-handled-backends)
1440 (vc-checkin file version comment))))))) 1478 (vc-transfer-file file vsym)
1441 1479 (vc-checkin ready-for-commit version))))))))
1442 ;; locked by somebody else 1480 ;; locked by somebody else (locking VCSes only)
1443 ((stringp state) 1481 ((stringp state)
1444 (if comment 1482 (let ((version
1445 (error "Sorry, you can't steal the lock on %s this way" 1483 (if verbose
1446 (file-name-nondirectory file))) 1484 (read-string "Version to steal: ")
1447 (vc-steal-lock file 1485 (vc-workfile-version file))))
1448 (if verbose (read-string "Version to steal: ") 1486 (mapc (lambda (file) (vc-steal-lock file version) state) files)))
1449 (vc-workfile-version file)) 1487 ;; needs-patch
1450 state)) 1488 ((eq state 'needs-patch)
1451 1489 (dolist (file files)
1452 ;; needs-patch
1453 ((eq state 'needs-patch)
1454 (if (yes-or-no-p (format 1490 (if (yes-or-no-p (format
1455 "%s is not up-to-date. Get latest version? " 1491 "%s is not up-to-date. Get latest version? "
1456 (file-name-nondirectory file))) 1492 (file-name-nondirectory file)))
1457 (vc-checkout file (eq (vc-checkout-model file) 'implicit) t) 1493 (vc-checkout file (eq model 'implicit) t)
1458 (if (and (not (eq (vc-checkout-model file) 'implicit)) 1494 (if (and (not (eq model 'implicit))
1459 (yes-or-no-p "Lock this version? ")) 1495 (yes-or-no-p "Lock this version? "))
1460 (vc-checkout file t) 1496 (vc-checkout file t)))))
1461 (error "Aborted")))) 1497 ;; needs-merge
1462 1498 ((eq state 'needs-merge)
1463 ;; needs-merge 1499 (dolist (file files)
1464 ((eq state 'needs-merge)
1465 (if (yes-or-no-p (format 1500 (if (yes-or-no-p (format
1466 "%s is not up-to-date. Merge in changes now? " 1501 "%s is not up-to-date. Merge in changes now? "
1467 (file-name-nondirectory file))) 1502 (file-name-nondirectory file)))
1468 (vc-maybe-resolve-conflicts file (vc-call merge-news file)) 1503 (vc-maybe-resolve-conflicts file (vc-call merge-news file)))))
1469 (error "Aborted")))
1470 1504
1471 ;; unlocked-changes 1505 ;; unlocked-changes
1472 ((eq state 'unlocked-changes) 1506 ((eq state 'unlocked-changes)
1473 (if (not visited) (find-file-other-window file)) 1507 (dolist (file files)
1508 (if (not (equal buffer-file-name file))
1509 (find-file-other-window file))
1474 (if (save-window-excursion 1510 (if (save-window-excursion
1475 (vc-version-diff file (vc-workfile-version file) nil) 1511 (vc-diff-internal
1512 (vc-backend file) nil (list file)
1513 (vc-workfile-version file) nil)
1476 (goto-char (point-min)) 1514 (goto-char (point-min))
1477 (let ((inhibit-read-only t)) 1515 (let ((inhibit-read-only t))
1478 (insert 1516 (insert
@@ -1493,20 +1531,6 @@ If VERBOSE is non-nil, query the user rather than using default parameters."
1493 (vc-revert-buffer-internal t t) 1531 (vc-revert-buffer-internal t t)
1494 (vc-checkout file t)))))))) 1532 (vc-checkout file t))))))))
1495 1533
1496(defun vc-next-action-dired (file rev comment)
1497 "Call `vc-next-action-on-file' on all the marked files.
1498Ignores FILE and REV, but passes on COMMENT."
1499 (let ((dired-buffer (current-buffer)))
1500 (dired-map-over-marks
1501 (let ((file (dired-get-filename)))
1502 (message "Processing %s..." file)
1503 (vc-next-action-on-file file nil comment)
1504 (set-buffer dired-buffer)
1505 (set-window-configuration vc-dired-window-configuration)
1506 (message "Processing %s...done" file))
1507 nil t))
1508 (dired-move-to-filename))
1509
1510(defun vc-create-repo (backend) 1534(defun vc-create-repo (backend)
1511 "Create an empty repository in the current directory." 1535 "Create an empty repository in the current directory."
1512 (interactive 1536 (interactive
@@ -1546,7 +1570,7 @@ first backend that could register the file is used."
1546 (set-buffer-modified-p t)) 1570 (set-buffer-modified-p t))
1547 (vc-buffer-sync) 1571 (vc-buffer-sync)
1548 1572
1549 (vc-start-entry buffer-file-name 1573 (vc-start-entry (list buffer-file-name)
1550 (if set-version 1574 (if set-version
1551 (read-string (format "Initial version level for %s: " 1575 (read-string (format "Initial version level for %s: "
1552 (buffer-name))) 1576 (buffer-name)))
@@ -1555,17 +1579,25 @@ first backend that could register the file is used."
1555 (or comment (not vc-initial-comment)) 1579 (or comment (not vc-initial-comment))
1556 nil 1580 nil
1557 "Enter initial comment." 1581 "Enter initial comment."
1558 (lambda (file rev comment) 1582 (lambda (files rev comment)
1559 (message "Registering %s... " file) 1583 (dolist (file files)
1560 (let ((backend (vc-responsible-backend file t))) 1584 (message "Registering %s... " file)
1561 (vc-file-clearprops file) 1585 (let ((backend (vc-responsible-backend file t)))
1562 (vc-call-backend backend 'register (list file) rev comment) 1586 (vc-file-clearprops file)
1563 (vc-file-setprop file 'vc-backend backend) 1587 (vc-call-backend backend 'register (list file) rev comment)
1564 (unless vc-make-backup-files 1588 (vc-file-setprop file 'vc-backend backend)
1565 (make-local-variable 'backup-inhibited) 1589 (unless vc-make-backup-files
1566 (setq backup-inhibited t))) 1590 (make-local-variable 'backup-inhibited)
1567 (message "Registering %s... done" file)))) 1591 (setq backup-inhibited t)))
1568 1592 (message "Registering %s... done" file)))))
1593
1594(defun vc-register-with (backend)
1595 "Register the current file with a specified back end."
1596 (interactive "SBackend: ")
1597 (if (not (member backend vc-handled-backends))
1598 (error "Unknown back end."))
1599 (let ((vc-handled-backends (list backend)))
1600 (call-interactively 'vc-register)))
1569 1601
1570(defun vc-resynch-window (file &optional keep noquery) 1602(defun vc-resynch-window (file &optional keep noquery)
1571 "If FILE is in the current buffer, either revert or unvisit it. 1603 "If FILE is in the current buffer, either revert or unvisit it.
@@ -1602,8 +1634,8 @@ rather than user editing!"
1602 (vc-resynch-window file keep noquery))))) 1634 (vc-resynch-window file keep noquery)))))
1603 (vc-dired-resynch-file file)) 1635 (vc-dired-resynch-file file))
1604 1636
1605(defun vc-start-entry (file rev comment initial-contents msg action &optional after-hook) 1637(defun vc-start-entry (files rev comment initial-contents msg action &optional after-hook)
1606 "Accept a comment for an operation on FILE revision REV. 1638 "Accept a comment for an operation on FILES revision REV.
1607If COMMENT is nil, pop up a VC-log buffer, emit MSG, and set the 1639If COMMENT is nil, pop up a VC-log buffer, emit MSG, and set the
1608action on close to ACTION. If COMMENT is a string and 1640action on close to ACTION. If COMMENT is a string and
1609INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial 1641INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial
@@ -1613,9 +1645,12 @@ entered COMMENT. If COMMENT is t, also do action immediately with an
1613empty comment. Remember the file's buffer in `vc-parent-buffer' 1645empty comment. Remember the file's buffer in `vc-parent-buffer'
1614\(current one if no file). AFTER-HOOK specifies the local value 1646\(current one if no file). AFTER-HOOK specifies the local value
1615for vc-log-operation-hook." 1647for vc-log-operation-hook."
1616 (let ((parent (or (and file (get-file-buffer file)) (current-buffer)))) 1648 (let ((parent
1649 (if (and files (equal (length files) 1))
1650 (get-file-buffer (car files))
1651 (current-buffer))))
1617 (if vc-before-checkin-hook 1652 (if vc-before-checkin-hook
1618 (if file 1653 (if files
1619 (with-current-buffer parent 1654 (with-current-buffer parent
1620 (run-hooks 'vc-before-checkin-hook)) 1655 (run-hooks 'vc-before-checkin-hook))
1621 (run-hooks 'vc-before-checkin-hook))) 1656 (run-hooks 'vc-before-checkin-hook)))
@@ -1625,8 +1660,8 @@ for vc-log-operation-hook."
1625 (set (make-local-variable 'vc-parent-buffer) parent) 1660 (set (make-local-variable 'vc-parent-buffer) parent)
1626 (set (make-local-variable 'vc-parent-buffer-name) 1661 (set (make-local-variable 'vc-parent-buffer-name)
1627 (concat " from " (buffer-name vc-parent-buffer))) 1662 (concat " from " (buffer-name vc-parent-buffer)))
1628 (if file (vc-mode-line file)) 1663 ;;(if file (vc-mode-line file))
1629 (vc-log-edit file) 1664 (vc-log-edit files)
1630 (make-local-variable 'vc-log-after-operation-hook) 1665 (make-local-variable 'vc-log-after-operation-hook)
1631 (if after-hook 1666 (if after-hook
1632 (setq vc-log-after-operation-hook after-hook)) 1667 (setq vc-log-after-operation-hook after-hook))
@@ -1651,7 +1686,7 @@ After check-out, runs the normal hook `vc-checkout-hook'."
1651 (vc-up-to-date-p file) 1686 (vc-up-to-date-p file)
1652 (vc-make-version-backup file)) 1687 (vc-make-version-backup file))
1653 (with-vc-properties 1688 (with-vc-properties
1654 file 1689 (list file)
1655 (condition-case err 1690 (condition-case err
1656 (vc-call checkout file writable rev) 1691 (vc-call checkout file writable rev)
1657 (file-error 1692 (file-error
@@ -1681,7 +1716,7 @@ After check-out, runs the normal hook `vc-checkout-hook'."
1681 (error "Steal canceled")) 1716 (error "Steal canceled"))
1682 (message "Stealing lock on %s..." file) 1717 (message "Stealing lock on %s..." file)
1683 (with-vc-properties 1718 (with-vc-properties
1684 file 1719 (list file)
1685 (vc-call steal-lock file rev) 1720 (vc-call steal-lock file rev)
1686 `((vc-state . edited))) 1721 `((vc-state . edited)))
1687 (vc-resynch-buffer file t t) 1722 (vc-resynch-buffer file t t)
@@ -1697,8 +1732,8 @@ After check-out, runs the normal hook `vc-checkout-hook'."
1697 ".\n") 1732 ".\n")
1698 (message "Please explain why you stole the lock. Type C-c C-c when done."))) 1733 (message "Please explain why you stole the lock. Type C-c C-c when done.")))
1699 1734
1700(defun vc-checkin (file &optional rev comment initial-contents) 1735(defun vc-checkin (files &optional rev comment initial-contents)
1701 "Check in FILE. 1736 "Check in FILES.
1702The optional argument REV may be a string specifying the new version 1737The optional argument REV may be a string specifying the new version
1703level (if nil increment the current level). COMMENT is a comment 1738level (if nil increment the current level). COMMENT is a comment
1704string; if omitted, a buffer is popped up to accept a comment. If 1739string; if omitted, a buffer is popped up to accept a comment. If
@@ -1710,29 +1745,27 @@ that the version control system supports this mode of operation.
1710 1745
1711Runs the normal hook `vc-checkin-hook'." 1746Runs the normal hook `vc-checkin-hook'."
1712 (vc-start-entry 1747 (vc-start-entry
1713 file rev comment initial-contents 1748 files rev comment initial-contents
1714 "Enter a change comment." 1749 "Enter a change comment."
1715 (lambda (file rev comment) 1750 (lambda (files rev comment)
1716 (message "Checking in %s..." file) 1751 (message "Checking in %s..." (vc-delistify files))
1717 ;; "This log message intentionally left almost blank". 1752 ;; "This log message intentionally left almost blank".
1718 ;; RCS 5.7 gripes about white-space-only comments too. 1753 ;; RCS 5.7 gripes about white-space-only comments too.
1719 (or (and comment (string-match "[^\t\n ]" comment)) 1754 (or (and comment (string-match "[^\t\n ]" comment))
1720 (setq comment "*** empty log message ***")) 1755 (setq comment "*** empty log message ***"))
1721 (with-vc-properties 1756 (with-vc-properties
1722 file 1757 files
1723 ;; Change buffers to get local value of vc-checkin-switches. 1758 ;; We used to change buffers to get local value of vc-checkin-switches,
1724 (with-current-buffer (or (get-file-buffer file) (current-buffer)) 1759 ;; but 'the' local buffer is not a well-defined concept for filesets.
1725 (progn 1760 (progn
1726 (vc-call checkin (list file) rev comment) 1761 (vc-call checkin files rev comment)
1727 (vc-delete-automatic-version-backups file))) 1762 (mapc 'vc-delete-automatic-version-backups files))
1728 `((vc-state . up-to-date) 1763 `((vc-state . up-to-date)
1729 (vc-checkout-time . ,(nth 5 (file-attributes file))) 1764 (vc-checkout-time . ,(nth 5 (file-attributes file)))
1730 (vc-workfile-version . nil))) 1765 (vc-workfile-version . nil)))
1731 (message "Checking in %s...done" file)) 1766 (message "Checking in %s...done" (vc-delistify files)))
1732 'vc-checkin-hook)) 1767 'vc-checkin-hook))
1733 1768
1734;; Code for access to the comment ring
1735
1736(defun vc-finish-logentry (&optional nocomment) 1769(defun vc-finish-logentry (&optional nocomment)
1737 "Complete the operation implied by the current log entry. 1770 "Complete the operation implied by the current log entry.
1738Use the contents of the current buffer as a check-in or registration 1771Use the contents of the current buffer as a check-in or registration
@@ -1742,7 +1775,7 @@ the buffer contents as a comment."
1742 ;; Check and record the comment, if any. 1775 ;; Check and record the comment, if any.
1743 (unless nocomment 1776 (unless nocomment
1744 ;; Comment too long? 1777 ;; Comment too long?
1745 (vc-call-backend (or (and vc-log-file (vc-backend vc-log-file)) 1778 (vc-call-backend (or (and vc-log-fileset (vc-backend (car vc-log-fileset)))
1746 (vc-responsible-backend default-directory)) 1779 (vc-responsible-backend default-directory))
1747 'logentry-check) 1780 'logentry-check)
1748 (run-hooks 'vc-logentry-check-hook)) 1781 (run-hooks 'vc-logentry-check-hook))
@@ -1754,7 +1787,7 @@ the buffer contents as a comment."
1754 (error "No log operation is pending")) 1787 (error "No log operation is pending"))
1755 ;; save the parameters held in buffer-local variables 1788 ;; save the parameters held in buffer-local variables
1756 (let ((log-operation vc-log-operation) 1789 (let ((log-operation vc-log-operation)
1757 (log-file vc-log-file) 1790 (log-fileset vc-log-fileset)
1758 (log-version vc-log-version) 1791 (log-version vc-log-version)
1759 (log-entry (buffer-string)) 1792 (log-entry (buffer-string))
1760 (after-hook vc-log-after-operation-hook) 1793 (after-hook vc-log-after-operation-hook)
@@ -1763,7 +1796,7 @@ the buffer contents as a comment."
1763 ;; OK, do it to it 1796 ;; OK, do it to it
1764 (save-excursion 1797 (save-excursion
1765 (funcall log-operation 1798 (funcall log-operation
1766 log-file 1799 log-fileset
1767 log-version 1800 log-version
1768 log-entry)) 1801 log-entry))
1769 ;; Remove checkin window (after the checkin so that if that fails 1802 ;; Remove checkin window (after the checkin so that if that fails
@@ -1777,8 +1810,10 @@ the buffer contents as a comment."
1777 (bury-buffer) 1810 (bury-buffer)
1778 (pop-to-buffer tmp-vc-parent-buffer)))) 1811 (pop-to-buffer tmp-vc-parent-buffer))))
1779 ;; Now make sure we see the expanded headers 1812 ;; Now make sure we see the expanded headers
1780 (if log-file 1813 (if log-fileset
1781 (vc-resynch-buffer log-file vc-keep-workfiles t)) 1814 (mapc
1815 (lambda (file) (vc-resynch-buffer file vc-keep-workfiles t))
1816 log-fileset))
1782 (if vc-dired-mode 1817 (if vc-dired-mode
1783 (dired-move-to-filename)) 1818 (dired-move-to-filename))
1784 (run-hooks after-hook 'vc-finish-logentry-hook))) 1819 (run-hooks after-hook 'vc-finish-logentry-hook)))
@@ -1838,101 +1873,96 @@ The meaning of REV1 and REV2 is the same as for `vc-version-diff'."
1838(defmacro vc-diff-switches-list (backend) `(vc-switches ',backend 'diff)) 1873(defmacro vc-diff-switches-list (backend) `(vc-switches ',backend 'diff))
1839(make-obsolete 'vc-diff-switches-list 'vc-switches "22.1") 1874(make-obsolete 'vc-diff-switches-list 'vc-switches "22.1")
1840 1875
1841(defun vc-diff-internal (file rev1 rev2) 1876(defun vc-diff-sentinel (verbose rev1-name rev2-name)
1842 "Run diff to compare FILE's revisions REV1 and REV2. 1877 ;; Did changes get generated into the buffer?
1843Diff output goes to the *vc-diff* buffer. The exit status of the diff 1878 (if (not (zerop (buffer-size (get-buffer "*vc-diff*"))))
1844command is returned. 1879 (progn
1845 1880 (pop-to-buffer "*vc-diff*")
1846This function takes care to set up a proper coding system for diff output. 1881 ;; Gnus-5.8.5 sets up an autoload for diff-mode, even if it's
1847If both revisions are available as local files, then it also does not 1882 ;; not available. Work around that.
1848actually call the backend, but performs a local diff." 1883 (if (require 'diff-mode nil t) (diff-mode))
1849 (if (or (not rev1) (string-equal rev1 "")) 1884 (goto-char (point-max))
1850 (setq rev1 (vc-workfile-version file))) 1885 (if verbose
1851 (if (string-equal rev2 "") 1886 (insert (format "\n\nDiffs between %s and %s end here." rev1-name rev2-name)))
1852 (setq rev2 nil)) 1887 (goto-char (point-min))
1853 (let ((file-rev1 (vc-version-backup-file file rev1)) 1888 (if verbose
1854 (file-rev2 (if (not rev2) 1889 (insert (format "Diffs between %s and %s:\n\n" rev1-name rev2-name)))
1855 file 1890 (shrink-window-if-larger-than-buffer)
1856 (vc-version-backup-file file rev2))) 1891 t)
1857 (coding-system-for-read (vc-coding-system-for-diff file))) 1892 (progn
1858 (if (and file-rev1 file-rev2) 1893 (message "No changes between %s and %s" rev1-name rev2-name)
1859 (let ((status 1894 nil)))
1860 (if (eq vc-diff-knows-L 'no) 1895
1861 (apply 'vc-do-command "*vc-diff*" 1 "diff" nil 1896(defun vc-diff-internal (backend async files rev1 rev2 &optional verbose)
1862 (append (vc-switches nil 'diff) 1897 "Report diffs between two revisions of a fileset.
1863 (list (file-relative-name file-rev1) 1898Diff output goes to the *vc-diff* buffer. The function
1864 (file-relative-name file-rev2)))) 1899returns t if the buffer had changes, nil otherwise."
1865 (apply 'vc-do-command "*vc-diff*" 2 "diff" nil 1900 (let* ((filenames (vc-delistify files))
1866 (append (vc-switches nil 'diff) 1901 (rev1-name (or rev1 "focus version"))
1867 ;; Provide explicit labels like RCS or 1902 (rev2-name (or rev2 "workfile"))
1868 ;; CVS would do so diff-mode refers to 1903 ;; Set coding system based on the first file. It's a kluge,
1869 ;; `file' rather than to `file-rev1' 1904 ;; but the only way to set it for each file included would
1870 ;; when trying to find/apply/undo 1905 ;; be to call the back end separately for each file.
1871 ;; hunks. 1906 (coding-system-for-read
1872 (list "-L" (vc-diff-label file file-rev1 rev1) 1907 (if files (vc-coding-system-for-diff (car files)) 'undecided)))
1873 "-L" (vc-diff-label file file-rev2 rev2) 1908 (vc-setup-buffer "*vc-diff*")
1874 (file-relative-name file-rev1) 1909 (message "Finding changes in..." filenames)
1875 (file-relative-name file-rev2))))))) 1910 ;; Many backends don't handle well the case of a file that has been
1876 (if (eq status 2) 1911 ;; added but not yet committed to the repo (notably CVS and Subversion).
1877 (if (not vc-diff-knows-L) 1912 ;; Do that work here so the backends don't have to futz with it.
1878 (setq vc-diff-knows-L 'no 1913 (let ((filtered '()))
1879 status (apply 'vc-do-command "*vc-diff*" 1 "diff" nil 1914 (dolist (file files)
1880 (append 1915 (cond ((and (not (file-directory-p file)) (string= (vc-workfile-version file) "0"))
1881 (vc-switches nil 'diff) 1916 (progn
1882 (list (file-relative-name file-rev1) 1917 ;; This file is added but not yet committed;
1883 (file-relative-name file-rev2))))) 1918 ;; there is no master file to diff against.
1884 (error "diff failed")) 1919 (if (or rev1 rev2)
1885 (if (not vc-diff-knows-L) (setq vc-diff-knows-L 'yes))) 1920 (error "No revisions of %s exist" file)
1886 status) 1921 ;; We regard this as "changed".
1887 (vc-call diff (list file) rev1 rev2 "*vc-diff*")))) 1922 ;; Diff it against /dev/null.
1923 (apply 'vc-do-command "*vc-diff*"
1924 1 "diff" file
1925 (append (vc-switches nil 'diff) '("/dev/null"))))))
1926 (t
1927 (add-to-list 'filtered file t))))
1928 (let ((vc-disable-async-diff (not async)))
1929 (vc-call-backend backend 'diff filtered rev1 rev2 "*vc-diff*")))
1930 (set-buffer "*vc-diff*")
1931 ;; This odd-looking code is because in the non-async case we
1932 ;; actually want to pass the return value from vc-diff-sentinel
1933 ;; back to the caller.
1934 (if async
1935 (vc-exec-after `(vc-diff-sentinel ,verbose ,rev1-name ,rev2-name))
1936 (vc-diff-sentinel verbose rev1-name rev2-name))))
1888 1937
1889;;;###autoload 1938;;;###autoload
1890(defun vc-diff (historic &optional not-urgent) 1939(defun vc-history-diff (backend files rev1 rev2)
1891 "Display diffs between file versions. 1940 "Report diffs between revisions of the fileset in the repository history."
1892Normally this compares the current file and buffer with the most
1893recent checked in version of that file. This uses no arguments. With
1894a prefix argument HISTORIC, it reads the file name to use and two
1895version designators specifying which versions to compare. The
1896optional argument NOT-URGENT non-nil means it is ok to say no to
1897saving the buffer."
1898 (interactive (list current-prefix-arg t))
1899 (if historic
1900 (call-interactively 'vc-version-diff)
1901 (vc-ensure-vc-buffer)
1902 (let ((file buffer-file-name))
1903 (vc-buffer-sync not-urgent)
1904 (if (vc-workfile-unchanged-p buffer-file-name)
1905 (message "No changes to %s since latest version" file)
1906 (vc-version-diff file nil nil)))))
1907
1908(defun vc-version-diff (file rev1 rev2)
1909 "List the differences between FILE's versions REV1 and REV2.
1910If REV1 is empty or nil it means to use the focus version;
1911REV2 empty or nil means the working-copy contents. FILE may also be
1912a directory, in that case, generate diffs between the correponding
1913versions of all registered files in or below it."
1914 (interactive 1941 (interactive
1915 (let* ((file (expand-file-name 1942 (let* ((files (vc-deduce-fileset t))
1916 (read-file-name (if buffer-file-name 1943 (first (car files))
1917 "File or dir to diff (default visited file): " 1944 (backend (vc-backend first))
1918 "File or dir to diff: ") 1945 (completion-table
1919 default-directory buffer-file-name t))) 1946 (vc-call-backend backend 'revision-completion-table first))
1920 (rev1-default nil) (rev2-default nil) 1947 (rev1-default nil)
1921 (completion-table (vc-call revision-completion-table file))) 1948 (rev2-default nil))
1922 ;; compute default versions based on the file state
1923 (cond 1949 (cond
1950 ;; someday we may be able to do version completion on non-singleton
1951 ;; filesets, but not yet.
1952 ((/= (length files) 1)
1953 nil)
1924 ;; if it's a directory, don't supply any version default 1954 ;; if it's a directory, don't supply any version default
1925 ((file-directory-p file) 1955 ((file-directory-p first)
1926 nil) 1956 nil)
1927 ;; if the file is not up-to-date, use current version as older version 1957 ;; if the file is not up-to-date, use current version as older version
1928 ((not (vc-up-to-date-p file)) 1958 ((not (vc-up-to-date-p first))
1929 (setq rev1-default (vc-workfile-version file))) 1959 (setq rev1-default (vc-workfile-version first)))
1930 ;; if the file is not locked, use last and previous version as default 1960 ;; if the file is not locked, use last and previous version as default
1931 (t 1961 (t
1932 (setq rev1-default (vc-call previous-version file 1962 (setq rev1-default (vc-call previous-version first
1933 (vc-workfile-version file))) 1963 (vc-workfile-version first)))
1934 (if (string= rev1-default "") (setq rev1-default nil)) 1964 (if (string= rev1-default "") (setq rev1-default nil))
1935 (setq rev2-default (vc-workfile-version file)))) 1965 (setq rev2-default (vc-workfile-version first))))
1936 ;; construct argument list 1966 ;; construct argument list
1937 (let* ((rev1-prompt (if rev1-default 1967 (let* ((rev1-prompt (if rev1-default
1938 (concat "Older version (default " 1968 (concat "Older version (default "
@@ -1942,60 +1972,37 @@ versions of all registered files in or below it."
1942 (or rev2-default "current source") "): ")) 1972 (or rev2-default "current source") "): "))
1943 (rev1 (if completion-table 1973 (rev1 (if completion-table
1944 (completing-read rev1-prompt completion-table 1974 (completing-read rev1-prompt completion-table
1945 nil nil nil nil rev1-default) 1975 nil nil nil nil rev1-default)
1946 (read-string rev1-prompt nil nil rev1-default))) 1976 (read-string rev1-prompt nil nil rev1-default)))
1947 (rev2 (if completion-table 1977 (rev2 (if completion-table
1948 (completing-read rev2-prompt completion-table 1978 (completing-read rev2-prompt completion-table
1949 nil nil nil nil rev2-default) 1979 nil nil nil nil rev2-default)
1950 (read-string rev2-prompt nil nil rev2-default)))) 1980 (read-string rev2-prompt nil nil rev2-default))))
1951 (list file rev1 rev2)))) 1981 (if (string= rev1 "") (setq rev1 nil))
1952 (if (file-directory-p file) 1982 (if (string= rev2 "") (setq rev2 nil))
1953 ;; recursive directory diff 1983 (list backend files rev1 rev2))))
1954 (progn 1984 (if (and (not rev1) rev2)
1955 (vc-setup-buffer "*vc-diff*") 1985 (error "Not a valid revision range."))
1956 (if (string-equal rev1 "") (setq rev1 nil)) 1986 (vc-diff-internal backend t files rev1 rev2 (interactive-p)))
1957 (if (string-equal rev2 "") (setq rev2 nil)) 1987
1958 (let ((inhibit-read-only t)) 1988;;;###autoload
1959 (insert "Diffs between " 1989(defun vc-diff (historic)
1960 (or rev1 "last version checked in") 1990 "Display diffs between file versions.
1961 " and " 1991Normally this compares the current file and buffer with the most
1962 (or rev2 "working copy") 1992recent checked in version of that file. This uses no arguments. With
1963 ":\n\n")) 1993a prefix argument HISTORIC, it reads the file name to use and two
1964 (let ((dir (file-name-as-directory file))) 1994version designators specifying which versions to compare."
1965 (vc-call-backend (vc-responsible-backend dir) 1995 (interactive "P")
1966 'diff-tree dir rev1 rev2)) 1996 (if historic
1967 (vc-exec-after `(let ((inhibit-read-only t)) 1997 (call-interactively 'vc-history-diff)
1968 (insert "\nEnd of diffs.\n")))) 1998 (let* ((files (vc-deduce-fileset t))
1969 ;; Single file diff. It is important that the vc-controlled buffer 1999 (first (car files))
1970 ;; is still current at this time, because any local settings in that 2000 (backend
1971 ;; buffer should affect the diff command. 2001 (cond ((file-directory-p first)
1972 (vc-diff-internal file rev1 rev2)) 2002 (vc-responsible-backend first))
1973 (set-buffer "*vc-diff*") 2003 (t
1974 (if (and (zerop (buffer-size)) 2004 (vc-backend first)))))
1975 (not (get-buffer-process (current-buffer)))) 2005 (vc-diff-internal backend t files nil nil (interactive-p)))))
1976 (progn
1977 (if rev1
1978 (if rev2
1979 (message "No changes to %s between %s and %s" file rev1 rev2)
1980 (message "No changes to %s since %s" file rev1))
1981 (message "No changes to %s since latest version" file))
1982 nil)
1983 (pop-to-buffer (current-buffer))
1984 ;; Gnus-5.8.5 sets up an autoload for diff-mode, even if it's
1985 ;; not available. Work around that.
1986 (if (require 'diff-mode nil t) (diff-mode))
1987 (vc-exec-after '(let ((inhibit-read-only t))
1988 (if (eq (buffer-size) 0)
1989 (insert "No differences found.\n"))
1990 (goto-char (point-min))
1991 (shrink-window-if-larger-than-buffer)))
1992 t))
1993
1994(defun vc-diff-label (file file-rev rev)
1995 (concat (file-relative-name file)
1996 (format-time-string "\t%d %b %Y %T %z\t"
1997 (nth 5 (file-attributes file-rev)))
1998 rev))
1999 2006
2000;;;###autoload 2007;;;###autoload
2001(defun vc-version-other-window (rev) 2008(defun vc-version-other-window (rev)
@@ -2455,36 +2462,20 @@ allowed and simply skipped)."
2455 2462
2456;;;###autoload 2463;;;###autoload
2457(defun vc-print-log (&optional focus-rev) 2464(defun vc-print-log (&optional focus-rev)
2458 "List the change log of the current buffer in a window. 2465 "List the change log of the current fileset in a window.
2459If FOCUS-REV is non-nil, leave the point at that revision." 2466If FOCUS-REV is non-nil, leave the point at that revision."
2460 (interactive) 2467 (interactive)
2461 (vc-ensure-vc-buffer) 2468 (let* ((files (vc-deduce-fileset))
2462 (let ((file buffer-file-name)) 2469 (backend (vc-backend (car files)))
2463 (or focus-rev (setq focus-rev (vc-workfile-version file))) 2470 (focus-rev (or focus-rev (vc-workfile-version (car files)))))
2464 ;; Don't switch to the output buffer before running the command, 2471 ;; Don't switch to the output buffer before running the command,
2465 ;; so that any buffer-local settings in the vc-controlled 2472 ;; so that any buffer-local settings in the vc-controlled
2466 ;; buffer can be accessed by the command. 2473 ;; buffer can be accessed by the command.
2467 (condition-case err 2474 (vc-call-backend backend 'print-log files "*vc-change-log*")
2468 (progn 2475 (pop-to-buffer "*vc-change-log*")
2469 (vc-call print-log (list file) "*vc-change-log*")
2470 (set-buffer "*vc-change-log*"))
2471 (wrong-number-of-arguments
2472 ;; If this error came from the above call to print-log, try again
2473 ;; without the optional buffer argument (for backward compatibility).
2474 ;; Otherwise, resignal.
2475 (if (or (not (eq (cadr err)
2476 (indirect-function
2477 (vc-find-backend-function (vc-backend file)
2478 'print-log))))
2479 (not (eq (caddr err) 2)))
2480 (signal (car err) (cdr err))
2481 ;; for backward compatibility
2482 (vc-call print-log (list file))
2483 (set-buffer "*vc*"))))
2484 (pop-to-buffer (current-buffer))
2485 (vc-exec-after 2476 (vc-exec-after
2486 `(let ((inhibit-read-only t)) 2477 `(let ((inhibit-read-only t))
2487 (vc-call-backend ',(vc-backend file) 'log-view-mode) 2478 (vc-call-backend ',backend 'log-view-mode)
2488 (goto-char (point-max)) (forward-line -1) 2479 (goto-char (point-max)) (forward-line -1)
2489 (while (looking-at "=*\n") 2480 (while (looking-at "=*\n")
2490 (delete-char (- (match-end 0) (match-beginning 0))) 2481 (delete-char (- (match-end 0) (match-beginning 0)))
@@ -2492,134 +2483,124 @@ If FOCUS-REV is non-nil, leave the point at that revision."
2492 (goto-char (point-min)) 2483 (goto-char (point-min))
2493 (if (looking-at "[\b\t\n\v\f\r ]+") 2484 (if (looking-at "[\b\t\n\v\f\r ]+")
2494 (delete-char (- (match-end 0) (match-beginning 0)))) 2485 (delete-char (- (match-end 0) (match-beginning 0))))
2495 ;; (shrink-window-if-larger-than-buffer) 2486 (shrink-window-if-larger-than-buffer)
2496 ;; move point to the log entry for the current version 2487 ;; move point to the log entry for the focus revision
2497 (vc-call-backend ',(vc-backend file) 2488 (vc-call-backend ',backend 'show-log-entry ',focus-rev)
2498 'show-log-entry
2499 ',focus-rev)
2500 (setq vc-sentinel-movepoint (point)) 2489 (setq vc-sentinel-movepoint (point))
2501 (set-buffer-modified-p nil))))) 2490 (set-buffer-modified-p nil)))))
2502 2491
2503;;;###autoload 2492;;;###autoload
2504(defun vc-revert () 2493(defun vc-revert ()
2505 "Revert the current buffer's file to the version it was based on. 2494 "Revert working copies of the selected fileset to their repository contents.
2506This asks for confirmation if the buffer contents are not identical 2495This asks for confirmation if the buffer contents are not identical
2507to that version. This function does not automatically pick up newer 2496to the repository version (except for keyword expansion)."
2508changes found in the master file; use \\[universal-argument] \\[vc-next-action] to do so."
2509 (interactive) 2497 (interactive)
2510 (vc-ensure-vc-buffer) 2498 (let* ((files (vc-deduce-fileset))
2511 ;; Make sure buffer is saved. If the user says `no', abort since 2499 (backend (vc-backend (car files))))
2512 ;; we cannot show the changes and ask for confirmation to discard them. 2500 ;; If any of the files is visited by the current buffer, make
2513 (vc-buffer-sync nil) 2501 ;; sure buffer is saved. If the user says `no', abort since
2514 (let ((file buffer-file-name) 2502 ;; we cannot show the changes and ask for confirmation to
2515 ;; This operation should always ask for confirmation. 2503 ;; discard them.
2516 (vc-suppress-confirm nil) 2504 (if (or (not files) (memq (buffer-file-name) files))
2517 (obuf (current-buffer)) 2505 (vc-buffer-sync nil))
2518 status) 2506 (dolist (file files)
2519 (if (vc-up-to-date-p file) 2507 (let (buf (get-file-buffer file))
2520 (unless (yes-or-no-p "File seems up-to-date. Revert anyway? ") 2508 (if (and buf (buffer-modified-p buf))
2521 (error "Revert canceled"))) 2509 (error "Please kill or save all modified buffers before reverting.")))
2522 (unless (vc-workfile-unchanged-p file) 2510 (if (vc-up-to-date-p file)
2523 (message "Finding changes...") 2511 (unless (yes-or-no-p (format "%s seems up-to-date. Revert anyway? " file))
2524 ;; vc-diff selects the new window, which is not what we want: 2512 (error "Revert canceled"))))
2525 ;; if the new window is on another frame, that'd require the user 2513 (if (vc-diff-internal backend vc-allow-async-revert files nil nil)
2526 ;; moving her mouse to answer the yes-or-no-p question. 2514 (progn
2527 (let* ((vc-disable-async-diff (not vc-allow-async-revert)) 2515 (unless (yes-or-no-p (format "Discard changes in %s? " (vc-delistify files)))
2528 (win (save-selected-window 2516 (error "Revert canceled"))
2529 (setq status (vc-diff nil t)) (selected-window)))) 2517 (delete-windows-on "*vc-diff*")
2530 (vc-exec-after `(message nil)) 2518 (kill-buffer "*vc-diff*")))
2531 (when status 2519 (dolist (file files)
2532 (unwind-protect 2520 (progn
2533 (unless (yes-or-no-p "Discard changes? ") 2521 (message "Reverting %s..." (vc-delistify files))
2534 (error "Revert canceled")) 2522 (vc-revert-file file)
2535 (select-window win) 2523 (message "Reverting %s...done" (vc-delistify files))))))
2536 (if (one-window-p t)
2537 (if (window-dedicated-p (selected-window))
2538 (make-frame-invisible))
2539 (delete-window))))))
2540 (set-buffer obuf)
2541 ;; Do the reverting
2542 (message "Reverting %s..." file)
2543 (vc-revert-file file)
2544 (message "Reverting %s...done" file)))
2545 2524
2546;;;###autoload 2525;;;###autoload
2547(defun vc-rollback (&optional norevert) 2526(defun vc-rollback ()
2548 "Get rid of most recently checked in version of this file. 2527 "Roll back (remove) the most recent changeset committed to the repository.
2549A prefix argument NOREVERT means do not revert the buffer afterwards." 2528This may be either a file-level or a repository-level operation,
2550 (interactive "P") 2529depending on the underlying version-control system."
2551 (vc-ensure-vc-buffer) 2530 (interactive)
2552 (let* ((file buffer-file-name) 2531 (let* ((files (vc-deduce-fileset))
2553 (backend (vc-backend file)) 2532 (backend (vc-backend (car files)))
2554 (target (vc-workfile-version file))) 2533 (granularity (vc-call-backend backend 'revision-granularity)))
2555 (cond 2534 (unless (vc-find-backend-function backend 'rollback)
2556 ((not (vc-find-backend-function backend 'rollback)) 2535 (error "Rollback is not supported in %s" backend))
2557 (error "Sorry, canceling versions is not supported under %s" backend)) 2536 (if (and (not (eq granularity 'repository)) (/= (length files) 1))
2558 ((not (vc-call latest-on-branch-p file)) 2537 (error "Rollback requires a singleton fileset or repository versioning"))
2559 (error "This is not the latest version; VC cannot cancel it")) 2538 (if (not (vc-call latest-on-branch-p (car files)))
2560 ((not (vc-up-to-date-p file)) 2539 (error "Rollback is only possible at the tip revision."))
2561 (error "%s" (substitute-command-keys "File is not up to date; use \\[vc-revert] to discard changes")))) 2540 ;; If any of the files is visited by the current buffer, make
2562 (if (null (yes-or-no-p (format "Remove version %s from master? " target))) 2541 ;; sure buffer is saved. If the user says `no', abort since
2563 (error "Aborted") 2542 ;; we cannot show the changes and ask for confirmation to
2564 (setq norevert (or norevert (not 2543 ;; discard them.
2565 (yes-or-no-p "Revert buffer to most recent remaining version? ")))) 2544 (if (or (not files) (memq (buffer-file-name) files))
2566 2545 (vc-buffer-sync nil))
2567 (message "Removing last change from %s..." file) 2546 (dolist (file files)
2568 (with-vc-properties 2547 (if (buffer-modified-p (get-file-buffer file))
2569 file 2548 (error "Please kill or save all modified buffers before rollback."))
2570 (vc-call rollback (list file)) 2549 (if (not (vc-up-to-date-p file))
2571 `((vc-state . ,(if norevert 'edited 'up-to-date)) 2550 (error "Please revert all modified workfiles before rollback.")))
2572 (vc-checkout-time . ,(if norevert 2551 ;; Accumulate changes associated with the fileset
2573 0 2552 (vc-setup-buffer "*vc-diff*")
2574 (nth 5 (file-attributes file)))) 2553 (not-modified)
2575 (vc-workfile-version . nil))) 2554 (message "Finding changes...")
2576 (message "Removing last change from %s...done" file) 2555 (let* ((tip (vc-workfile-version (car files)))
2577 2556 (previous (vc-call previous-version (car files) tip)))
2578 (cond 2557 (vc-diff-internal backend nil files previous tip))
2579 (norevert ;; clear version headers and mark the buffer modified 2558 ;; Display changes
2580 (set-visited-file-name file) 2559 (unless (yes-or-no-p "Discard these revisions? ")
2581 (when (not vc-make-backup-files) 2560 (error "Rollback canceled"))
2582 ;; inhibit backup for this buffer 2561 (delete-windows-on "*vc-diff*")
2583 (make-local-variable 'backup-inhibited) 2562 (kill-buffer"*vc-diff*")
2584 (setq backup-inhibited t)) 2563 ;; Do the actual reversions
2585 (setq buffer-read-only nil) 2564 (message "Rolling back %s..." (vc-delistify files))
2586 (vc-clear-headers) 2565 (with-vc-properties
2587 (vc-mode-line file) 2566 files
2588 (vc-dired-resynch-file file)) 2567 (vc-call-backend backend 'rollback files)
2589 (t ;; revert buffer to file on disk 2568 `((vc-state . ,'up-to-date)
2590 (vc-resynch-buffer file t t))) 2569 (vc-checkout-time . , (nth 5 (file-attributes file)))
2591 (message "Version %s has been removed from the master" target)))) 2570 (vc-workfile-version . nil)))
2571 (mapc (lambda (f) (vc-resynch-buffer f t t)) files)
2572 (message "Rolling back %s...done" (vc-delistify files))))
2592 2573
2593;;;###autoload 2574;;;###autoload
2594(define-obsolete-function-alias 'vc-revert-buffer 'vc-revert "23.1") 2575(define-obsolete-function-alias 'vc-revert-buffer 'vc-revert "23.1")
2595 2576
2596;;;###autoload 2577;;;###autoload
2597(defun vc-update () 2578(defun vc-update ()
2598 "Update the current buffer's file to the latest version on its branch. 2579 "Update the current fileset's files to their tip versions.
2599If the file contains no changes, and is not locked, then this simply replaces 2580For each one that contains no changes, and is not locked, then this simply
2600the working file with the latest version on its branch. If the file contains 2581replaces the work file with the latest version on its branch. If the file
2601changes, and the backend supports merging news, then any recent changes from 2582contains changes, and the backend supports merging news, then any recent
2602the current branch are merged into the working file." 2583changes from the current branch are merged into the working file."
2603 (interactive) 2584 (interactive)
2604 (vc-ensure-vc-buffer) 2585 (dolist (file (vc-deduce-fileset))
2605 (vc-buffer-sync nil) 2586 (if (buffer-modified-p (get-file-buffer file))
2606 (let ((file buffer-file-name)) 2587 (error "Please kill or save all modified buffers before updating."))
2607 (if (vc-up-to-date-p file) 2588 (if (vc-up-to-date-p file)
2608 (vc-checkout file nil "") 2589 (vc-checkout file nil "")
2609 (if (eq (vc-checkout-model file) 'locking) 2590 (if (eq (vc-checkout-model file) 'locking)
2610 (if (eq (vc-state file) 'edited) 2591 (if (eq (vc-state file) 'edited)
2611 (error 2592 (error
2612 (substitute-command-keys 2593 (substitute-command-keys
2613 "File is locked--type \\[vc-revert] to discard changes")) 2594 "File is locked--type \\[vc-revert] to discard changes"))
2614 (error 2595 (error
2615 (substitute-command-keys 2596 (substitute-command-keys
2616 "Unexpected file state (%s)--type \\[vc-next-action] to correct") 2597 "Unexpected file state (%s)--type \\[vc-next-action] to correct")
2617 (vc-state file))) 2598 (vc-state file)))
2618 (if (not (vc-find-backend-function (vc-backend file) 'merge-news)) 2599 (if (not (vc-find-backend-function (vc-backend file) 'merge-news))
2619 (error "Sorry, merging news is not implemented for %s" 2600 (error "Sorry, merging news is not implemented for %s"
2620 (vc-backend file)) 2601 (vc-backend file))
2621 (vc-call merge-news file) 2602 (vc-call merge-news file)
2622 (vc-resynch-window file t t)))))) 2603 (vc-resynch-buffer file t t))))))
2623 2604
2624(defun vc-version-backup-file (file &optional rev) 2605(defun vc-version-backup-file (file &optional rev)
2625 "Return name of backup file for revision REV of FILE. 2606 "Return name of backup file for revision REV of FILE.
@@ -2638,7 +2619,7 @@ its name; otherwise return nil."
2638(defun vc-revert-file (file) 2619(defun vc-revert-file (file)
2639 "Revert FILE back to the repository version it was based on." 2620 "Revert FILE back to the repository version it was based on."
2640 (with-vc-properties 2621 (with-vc-properties
2641 file 2622 (list file)
2642 (let ((backup-file (vc-version-backup-file file))) 2623 (let ((backup-file (vc-version-backup-file file)))
2643 (when backup-file 2624 (when backup-file
2644 (copy-file backup-file file 'ok-if-already-exists 'keep-date) 2625 (copy-file backup-file file 'ok-if-already-exists 'keep-date)
@@ -2662,32 +2643,25 @@ To get a prompt, use a prefix argument."
2662 (error "There is no version-controlled file in this buffer")) 2643 (error "There is no version-controlled file in this buffer"))
2663 (let ((backend (vc-backend buffer-file-name)) 2644 (let ((backend (vc-backend buffer-file-name))
2664 (backends nil)) 2645 (backends nil))
2665 (unwind-protect 2646 (unless backend
2666 (progn 2647 (error "File %s is not under version control" buffer-file-name))
2667 (unless backend 2648 ;; Find the registered backends.
2668 (error "File %s is not under version control" buffer-file-name)) 2649 (dolist (backend vc-handled-backends)
2669 ;; Find the registered backends. 2650 (when (vc-call-backend backend 'registered buffer-file-name)
2670 (dolist (backend vc-handled-backends) 2651 (push backend backends)))
2671 (when (vc-call-backend backend 'registered buffer-file-name) 2652 ;; Find the next backend.
2672 (push backend backends))) 2653 (let ((def (car (delq backend (append (memq backend backends) backends))))
2673 ;; Find the next backend. 2654 (others (delete backend backends)))
2674 (let ((def (car (delq backend 2655 (cond
2675 (append (memq backend backends) backends)))) 2656 ((null others) (error "No other backend to switch to"))
2676 (others (delete backend backends))) 2657 (current-prefix-arg
2677 (cond 2658 (intern
2678 ((null others) (error "No other backend to switch to")) 2659 (upcase
2679 (current-prefix-arg 2660 (completing-read
2680 (intern 2661 (format "Switch to backend [%s]: " def)
2681 (upcase 2662 (mapcar (lambda (b) (list (downcase (symbol-name b)))) backends)
2682 (completing-read 2663 nil t nil nil (downcase (symbol-name def))))))
2683 (format "Switch to backend [%s]: " def) 2664 (t def))))))
2684 (mapcar (lambda (b) (list (downcase (symbol-name b)))) backends)
2685 nil t nil nil (downcase (symbol-name def))))))
2686 (t def))))
2687 ;; Calling the `registered' method can mess up the file
2688 ;; properties, so we want to revert them to what they were.
2689 (if (and backend (delete backend backends))
2690 (vc-call-backend backend 'registered buffer-file-name))))))
2691 (unless (eq backend (vc-backend file)) 2665 (unless (eq backend (vc-backend file))
2692 (vc-file-clearprops file) 2666 (vc-file-clearprops file)
2693 (vc-file-setprop file 'vc-backend backend) 2667 (vc-file-setprop file 'vc-backend backend)
@@ -2953,7 +2927,7 @@ editing non-current versions is not supported by default."
2953(defalias 'vc-rcs-update-changelog 'vc-update-changelog-rcs2log) 2927(defalias 'vc-rcs-update-changelog 'vc-update-changelog-rcs2log)
2954;; FIXME: This should probably be moved to vc-rcs.el and replaced in 2928;; FIXME: This should probably be moved to vc-rcs.el and replaced in
2955;; vc-cvs.el by code using cvs2cl. 2929;; vc-cvs.el by code using cvs2cl.
2956(defun vc-update-changelog-rcs2log (files) 2930(defun vc-update-changelog-rcs2log (backend files)
2957 "Default implementation of update-changelog. 2931 "Default implementation of update-changelog.
2958Uses `rcs2log' which only works for RCS and CVS." 2932Uses `rcs2log' which only works for RCS and CVS."
2959 ;; FIXME: We (c|sh)ould add support for cvs2cl 2933 ;; FIXME: We (c|sh)ould add support for cvs2cl
@@ -2994,7 +2968,7 @@ Uses `rcs2log' which only works for RCS and CVS."
2994 (mapcar 2968 (mapcar
2995 (lambda (f) 2969 (lambda (f)
2996 (file-relative-name 2970 (file-relative-name
2997 (expand-file-name f odefault))) 2971 (expand-file-name f odefault)))
2998 files))) 2972 files)))
2999 "done" 2973 "done"
3000 (pop-to-buffer (get-buffer-create "*vc*")) 2974 (pop-to-buffer (get-buffer-create "*vc*"))
@@ -3017,13 +2991,19 @@ to provide the `find-version' operation instead."
3017 (delete-file tmpfile)))) 2991 (delete-file tmpfile))))
3018 2992
3019(defun vc-default-dired-state-info (backend file) 2993(defun vc-default-dired-state-info (backend file)
3020 (let ((state (vc-state file))) 2994 (let* ((state (vc-state file))
3021 (cond 2995 (statestring
3022 ((stringp state) (concat "(" state ")")) 2996 (cond
3023 ((eq state 'edited) (concat "(" (vc-user-login-name file) ")")) 2997 ((stringp state) (concat "(" state ")"))
3024 ((eq state 'needs-merge) "(merge)") 2998 ((eq state 'edited) (concat "(" (vc-user-login-name file) ")"))
3025 ((eq state 'needs-patch) "(patch)") 2999 ((eq state 'needs-merge) "(merge)")
3026 ((eq state 'unlocked-changes) "(stale)")))) 3000 ((eq state 'needs-patch) "(patch)")
3001 ((eq state 'unlocked-changes) "(stale)")))
3002 (buffer
3003 (get-file-buffer file))
3004 (modflag
3005 (if (and buffer (buffer-modified-p buffer)) "+" "")))
3006 (concat statestring modflag)))
3027 3007
3028(defun vc-default-rename-file (backend old new) 3008(defun vc-default-rename-file (backend old new)
3029 (condition-case nil 3009 (condition-case nil
@@ -3427,7 +3407,11 @@ versions after."
3427 (if (not prev-rev) 3407 (if (not prev-rev)
3428 (message "Cannot diff from any version prior to %s" rev-at-line) 3408 (message "Cannot diff from any version prior to %s" rev-at-line)
3429 (save-window-excursion 3409 (save-window-excursion
3430 (vc-version-diff vc-annotate-parent-file prev-rev rev-at-line)) 3410 (vc-diff-internal
3411 (vc-backend vc-annotate-parent-file)
3412 nil
3413 (list vc-annotate-parent-file)
3414 prev-rev rev-at-line))
3431 (switch-to-buffer "*vc-diff*")))))) 3415 (switch-to-buffer "*vc-diff*"))))))
3432 3416
3433(defun vc-annotate-warp-version (revspec) 3417(defun vc-annotate-warp-version (revspec)
@@ -3548,18 +3532,12 @@ The annotations are relative to the current time, unless overridden by OFFSET."
3548 3532
3549;; Set up key bindings for use while editing log messages 3533;; Set up key bindings for use while editing log messages
3550 3534
3551(defun vc-log-edit (file) 3535(defun vc-log-edit (fileset)
3552 "Set up `log-edit' for use with VC on FILE." 3536 "Set up `log-edit' for use with VC on FILE."
3553 (setq default-directory 3537 (setq default-directory
3554 (if file (file-name-directory file) 3538 (with-current-buffer vc-parent-buffer default-directory))
3555 (with-current-buffer vc-parent-buffer default-directory))) 3539 (log-edit 'vc-finish-logentry nil `(lambda () ',fileset))
3556 (log-edit 'vc-finish-logentry nil 3540 (set (make-local-variable 'vc-log-fileset) fileset)
3557 (if file `(lambda () ',(list (file-name-nondirectory file)))
3558 ;; If FILE is nil, we were called from vc-dired.
3559 (lambda ()
3560 (with-current-buffer vc-parent-buffer
3561 (dired-get-marked-files t)))))
3562 (set (make-local-variable 'vc-log-file) file)
3563 (make-local-variable 'vc-log-version) 3541 (make-local-variable 'vc-log-version)
3564 (set-buffer-modified-p nil) 3542 (set-buffer-modified-p nil)
3565 (setq buffer-file-name nil)) 3543 (setq buffer-file-name nil))