diff lisp/vc.el @ 10537:380605821cc9

(vc-do-command): Arrange for the default-directory variable in *vc* to be re-set each time this function uses it. Discard current dir from front of FILE later on, and only if last = `WORKFILE'. Undo Dec 10 change: (vc-directory, vc-dired-reformat-line): Changed back. (vc-directory-18): Old function restored. (vc-dir-all-files): Function deleted. (vc-next-action-on-file): If file is not registered, check file out after registering it. (vc-next-action-dired): Restore the window configuration after doing vc-next-action on each file in a VC-dired buffer. (file-regular-p-18): New function. (file-regular-p): Define, if not already defined.
author Richard M. Stallman <rms@gnu.org>
date Tue, 24 Jan 1995 06:33:41 +0000
parents 2d9590603a06
children 353416feba10
line wrap: on
line diff
--- a/lisp/vc.el	Tue Jan 24 05:27:32 1995 +0000
+++ b/lisp/vc.el	Tue Jan 24 06:33:41 1995 +0000
@@ -1,10 +1,10 @@
 ;;; vc.el --- drive a version-control system from within Emacs
 
-;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
 
 ;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
 ;; Maintainer: ttn@netcom.com
-;; Version: 5.5 + CVS hacks by ceder@lysator.liu.se made in Jan-Feb 1994.
+;; Version: 5.6
 
 ;; This file is part of GNU Emacs.
 
@@ -29,10 +29,15 @@
 ;; This was designed and implemented by Eric Raymond <esr@snark.thyrsus.com>.
 ;; Paul Eggert <eggert@twinsun.com>, Sebastian Kremer <sk@thp.uni-koeln.de>,
 ;; and Richard Stallman contributed valuable criticism, support, and testing.
+;; CVS support was added by Per Cederqvist <ceder@lysator.liu.se>
+;; in Jan-Feb 1994.
 ;;
-;; Supported version-control systems presently include SCCS and RCS;
-;; the RCS lock-stealing code doesn't work right unless you use RCS 5.6.2
+;; Supported version-control systems presently include SCCS, RCS, and CVS.
+;; The RCS lock-stealing code doesn't work right unless you use RCS 5.6.2
 ;; or newer.  Currently (January 1994) that is only a beta test release.
+;; Even initial checkins will fail if your RCS version is so old that ci
+;; doesn't understand -t-; this has been known to happen to people running
+;; NExTSTEP 3.0. 
 ;;
 ;; The RCS code assumes strict locking.  You can support the RCS -x option
 ;; by adding pairs to the vc-master-templates list.
@@ -93,6 +98,8 @@
   (if (file-exists-p "/usr/sccs")
       '("/usr/sccs") nil)
   "*List of extra directories to search for version control commands.")
+(defvar vc-directory-exclusion-list '("SCCS" "RCS")
+  "*Directory names ignored by functions that recursively walk file trees.")
 
 (defconst vc-maximum-comment-ring-size 32
   "Maximum number of saved comments in the comment ring.")
@@ -159,6 +166,27 @@
 (defvar vc-comment-ring-index nil)
 (defvar vc-last-comment-match nil)
 
+;; Back-portability to Emacs 18
+
+(defun file-executable-p-18 (f)
+  (let ((modes (file-modes f)))
+    (and modes (not (zerop (logand 292))))))
+
+(defun file-regular-p-18 (f)
+  (let ((attributes (file-attributes f)))
+    (and attributes (not (car attributes)))))
+
+; Conditionally rebind some things for Emacs 18 compatibility
+(if (not (boundp 'minor-mode-map-alist))
+    (progn
+      (setq compilation-old-error-list nil)
+      (fset 'file-executable-p 'file-executable-p-18)
+      (fset 'shrink-window-if-larger-than-buffer 'beginning-of-buffer)
+      ))
+
+(if (not (boundp 'file-regular-p))
+    (fset 'file-regular-p 'file-regular-p-18))
+
 ;; File property caching
 
 (defun vc-file-clearprops (file)
@@ -203,35 +231,37 @@
   "Execute a version-control command, notifying user and checking for errors.
 The command is successful if its exit status does not exceed OKSTATUS.
 Output from COMMAND goes to buffer *vc*.  The last argument of the command is
-the master name of FILE if LAST is 'MASTER, or the basename of FILE if LAST is
-'BASE; this is appended to an optional list of FLAGS."
+the master name of FILE if LAST is 'MASTER, or the workfile of FILE if LAST is
+'WORKFILE; this is appended to an optional list of FLAGS."
   (setq file (expand-file-name file))
   (if vc-command-messages
       (message "Running %s on %s..." command file))
   (let ((obuf (current-buffer)) (camefrom (current-buffer))
 	(squeezed nil)
 	(vc-file (and file (vc-name file)))
+	(olddir default-directory)
 	status)
     (set-buffer (get-buffer-create "*vc*"))
     (set (make-local-variable 'vc-parent-buffer) camefrom)
     (set (make-local-variable 'vc-parent-buffer-name)
 	 (concat " from " (buffer-name camefrom)))
+    (setq default-directory olddir)
     
     (erase-buffer)
 
-    ;; This is so that command arguments typed in the *vc* buffer will
-    ;; have reasonable defaults.
-    (setq default-directory (file-name-directory file))
-
     (mapcar
      (function (lambda (s) (and s (setq squeezed (append squeezed (list s))))))
      flags)
     (if (and vc-file (eq last 'MASTER))
 	(setq squeezed (append squeezed (list vc-file))))
-    (if (eq last 'BASE)
-	(setq squeezed (append squeezed (list (file-name-nondirectory file)))))
-    (let ((default-directory (file-name-directory (or file "./")))
-	  (exec-path (if vc-path (append exec-path vc-path) exec-path))
+    (if (eq last 'WORKFILE)
+	(progn
+	  (let* ((pwd (expand-file-name default-directory))
+		 (preflen (length pwd)))
+	    (if (string= (substring file 0 preflen) pwd)
+		(setq file (substring file preflen))))
+	  (setq squeezed (append squeezed (list file)))))
+    (let ((exec-path (if vc-path (append exec-path vc-path) exec-path))
 	  ;; Add vc-path to PATH for the execution of this command.
 	  (process-environment
 	   (cons (concat "PATH=" (getenv "PATH")
@@ -239,6 +269,7 @@
 		 process-environment)))
       (setq status (apply 'call-process command nil t nil squeezed)))
     (goto-char (point-max))
+    (set-buffer-modified-p nil)
     (forward-line -1)
     (if (or (not (integerp status)) (< okstatus status))
 	(progn
@@ -324,8 +355,16 @@
 				      (if buffer-error-marked-p buffer))))
 				  (buffer-list)))))))
 
-    ;; the actual revisit
-    (revert-buffer arg no-confirm)
+    (let ((in-font-lock-mode (and (boundp 'font-lock-fontified)
+                                font-lock-fontified)))
+      (if in-font-lock-mode
+	  (font-lock-mode 0))
+
+      ;; the actual revisit
+      (revert-buffer arg no-confirm)
+
+      (if in-font-lock-mode
+	  (font-lock-mode 1)))
 
     ;; Reparse affected compilation buffers.
     (while reparse
@@ -387,7 +426,11 @@
 
      ;; if there is no master file corresponding, create one
      ((not vc-file)
-      (vc-register verbose comment))
+      (vc-register verbose comment)
+      (if vc-initial-comment
+	  (setq vc-log-after-operation-hook
+		'vc-checkout-writable-buffer-hook)
+	(vc-checkout-writable-buffer file)))
 
      ;; if there is no lock on the file, assert one and get it
      ((and (not (eq vc-type 'CVS))	;There are no locks in CVS.
@@ -491,13 +534,15 @@
   ;; We've accepted a log comment, now do a vc-next-action using it on all
   ;; marked files.
   (set-buffer vc-parent-buffer)
-  (dired-map-over-marks
-   (save-window-excursion
-     (let ((file (dired-get-filename)))
-       (message "Processing %s..." file)
-       (vc-next-action-on-file file nil comment)
-       (message "Processing %s...done" file)))
-   nil t)
+  (let ((configuration (current-window-configuration)))
+    (dired-map-over-marks
+     (save-window-excursion
+       (let ((file (dired-get-filename)))
+	 (message "Processing %s..." file)
+	 (vc-next-action-on-file file nil comment)
+	 (message "Processing %s...done" file)))
+     nil t)
+    (set-window-configuration configuration))
   )
 
 ;; Here's the major entry point.
@@ -893,7 +938,7 @@
 	;; visited.  This plays hell with numerous assumptions in
 	;; the diff.el and compile.el machinery.
 	(pop-to-buffer "*vc*")
-	(pop-to-buffer "*vc*")
+	(setq default-directory (file-name-directory file))
 	(if (= 0 (buffer-size))
 	    (progn
 	      (setq unchanged t)
@@ -1034,51 +1079,45 @@
     (cond
      ((re-search-forward "\\([0-9]+ \\)\\([^ ]+\\)\\( .*\\)" nil 0)
       (save-excursion
-	(goto-char (match-beginning 2))
-	(insert "(")
-	(goto-char (1+ (match-end 2)))
-	(insert ")")
-	(delete-char (- 17 (- (match-end 2) (match-beginning 2))))
-	(insert (substring "      " 0
-			   (- 7 (- (match-end 2) (match-beginning 2)))))))))
+       (goto-char (match-beginning 2))
+       (insert "(")
+       (goto-char (1+ (match-end 2)))
+       (insert ")")
+       (delete-char (- 17 (- (match-end 2) (match-beginning 2))))
+       (insert (substring "      " 0
+                          (- 7 (- (match-end 2) (match-beginning 2)))))))))
    (t
     (if x (setq x (concat "(" x ")")))
     (if (re-search-forward "\\([0-9]+ \\).................\\( .*\\)" nil 0)
-	(let ((rep (substring (concat x "                 ") 0 9)))
-	  (replace-match (concat "\\1" rep "\\2") t)))
+       (let ((rep (substring (concat x "                 ") 0 9)))
+         (replace-match (concat "\\1" rep "\\2") t)))
     )))
 
+;;; Note in Emacs 18 the following defun gets overridden
+;;; with the symbol 'vc-directory-18.  See below.
 ;;;###autoload
-(defun vc-directory (dir verbose &optional nested)
-  "Show version-control status of all files in the directory DIR.
-If the second argument VERBOSE is non-nil, show all files;
-otherwise show only files that current locked in the version control system.
-Interactively, supply a prefix arg to make VERBOSE non-nil.
-
-If the optional third argument NESTED is non-nil,
-scan the entire tree of subdirectories of the current directory."
-  (interactive "DVC status of directory: \nP")
-  (let* (nonempty
-	 (dl (length dir))
-	 (filelist nil) (userlist nil)
-	 dired-buf
-	 dired-buf-mod-count
-	 (subfunction
-	  (function (lambda (f)
-		      (if (vc-registered f)
-			  (let ((user (vc-locking-user f)))
-			    (and (or verbose user)
-				 (setq filelist (cons (substring f dl) filelist))
-				 (setq userlist (cons user userlist)))))))))
-    (let ((default-directory dir))
-      (if nested
-	  (vc-file-tree-walk subfunction)
-	(vc-dir-all-files subfunction)))
+(defun vc-directory (verbose)
+  "Show version-control status of the current directory and subdirectories.
+Normally it creates a Dired buffer that lists only the locked files
+in all these directories.  With a prefix argument, it lists all files."
+  (interactive "P")
+  (let (nonempty
+	(dl (length default-directory))
+	(filelist nil) (userlist nil)
+	dired-buf
+	dired-buf-mod-count)
+    (vc-file-tree-walk
+     (function (lambda (f)
+		 (if (vc-registered f)
+		     (let ((user (vc-locking-user f)))
+		       (and (or verbose user)
+			    (setq filelist (cons (substring f dl) filelist))
+			    (setq userlist (cons user userlist))))))))
     (save-excursion
       ;; This uses a semi-documented feature of dired; giving a switch
       ;; argument forces the buffer to refresh each time.
       (dired
-       (cons dir (nreverse filelist))
+       (cons default-directory (nreverse filelist))
        dired-listing-switches)
       (setq dired-buf (current-buffer))
       (setq nonempty (not (zerop (buffer-size)))))
@@ -1103,9 +1142,35 @@
 	       (if verbose "registered" "locked") default-directory))
     ))
 
-; Emacs 18 also lacks these.
-(or (boundp 'compilation-old-error-list)
-    (setq compilation-old-error-list nil))
+;; Emacs 18 version
+(defun vc-directory-18 (verbose)
+  "Show version-control status of all files under the current directory."
+  (interactive "P")
+  (let (nonempty (dir default-directory))
+    (save-excursion
+      (set-buffer (get-buffer-create "*vc-status*"))
+      (erase-buffer)
+      (cd dir)
+      (vc-file-tree-walk
+       (function (lambda (f)
+		   (if (vc-registered f)
+		       (let ((user (vc-locking-user f)))
+			 (if (or user verbose)
+			     (insert (format
+				      "%s	%s\n"
+				      (concat user) f))))))))
+      (setq nonempty (not (zerop (buffer-size)))))
+    (if nonempty
+	(progn
+	  (pop-to-buffer "*vc-status*" t)
+	  (goto-char (point-min))
+	  (shrink-window-if-larger-than-buffer)))
+      (message "No files are currently %s under %s"
+	       (if verbose "registered" "locked") default-directory))
+    )
+
+(or (boundp 'minor-mode-map-alist)
+    (fset 'vc-directory 'vc-directory-18))
 
 ;; Named-configuration support for SCCS
 
@@ -1198,9 +1263,10 @@
   (while vc-parent-buffer
       (pop-to-buffer vc-parent-buffer))
   (if (and buffer-file-name (vc-name buffer-file-name))
-      (progn
-	(vc-backend-print-log buffer-file-name)
+      (let ((file buffer-file-name))
+	(vc-backend-print-log file)
 	(pop-to-buffer (get-buffer-create "*vc*"))
+	(setq default-directory (file-name-directory file))
 	(while (looking-at "=*\n")
 	  (delete-char (- (match-end 0) (match-beginning 0)))
 	  (forward-line -1))
@@ -1424,7 +1490,7 @@
 	  (setq buf (create-file-buffer file))
 	  (set-buffer buf))
 	(erase-buffer)
-	(insert-file-contents file nil)
+	(insert-file-contents file)
 	(set-buffer-modified-p nil)
 	(auto-save-mode nil)
 	(prog1
@@ -1602,7 +1668,7 @@
    ;; should always be nil anyhow.  Don't fetch vc-your-latest-version, since
    ;; that is done in vc-find-cvs-master.
    (vc-log-info
-    "cvs" file 'BASE '("status")
+    "cvs" file 'WORKFILE '("status")
     ;; CVS 1.3 says "RCS Version:", other releases "RCS Revision:",
     ;; and CVS 1.4a1 says "Repository revision:".  The regexp below
     ;; matches much more, but because of the way vc-log-info is
@@ -1654,7 +1720,7 @@
 			  (and comment (concat "-t-" comment))
 			  file))
 	  ((eq backend 'CVS)
-	   (vc-do-command 0 "cvs" file 'BASE ;; CVS
+	   (vc-do-command 0 "cvs" file 'WORKFILE ;; CVS
 			  "add"
 			  (and comment (not (string= comment ""))
 			       (concat "-m" comment)))
@@ -1737,7 +1803,7 @@
 	      (unwind-protect
 		  (progn
 		    (apply 'vc-do-command
-			   0 "/bin/sh" file 'BASE "-c"
+			   0 "/bin/sh" file 'WORKFILE "-c"
 			   "exec >\"$1\" || exit; shift; exec cvs update \"$@\""
 			   ""		; dummy argument for shell's $0
 			   workfile
@@ -1746,7 +1812,7 @@
 			   vc-checkout-switches)
 		    (setq failed nil))
 		(and failed (file-exists-p filename) (delete-file filename))))
-	  (apply 'vc-do-command 0 "cvs" file 'BASE
+	  (apply 'vc-do-command 0 "cvs" file 'WORKFILE
 		 (and rev (concat "-r" rev))
 		 file
 		 vc-checkout-switches))
@@ -1791,7 +1857,7 @@
 	     (concat "-m" comment)
 	     vc-checkin-switches)
       (progn
-	(apply 'vc-do-command 0 "cvs" file 'BASE 
+	(apply 'vc-do-command 0 "cvs" file 'WORKFILE 
 	       "ci" "-m" comment
 	       vc-checkin-switches)
 	(vc-file-setprop file 'vc-checkout-time 
@@ -1813,7 +1879,7 @@
 		  "-f" "-u")
    (progn				  ;; CVS
      (delete-file file)
-     (vc-do-command 0 "cvs" file 'BASE "update"))
+     (vc-do-command 0 "cvs" file 'WORKFILE "update"))
    )
   (vc-file-setprop file 'vc-locking-user nil)
   (message "Reverting %s...done" file)
@@ -1853,14 +1919,14 @@
    file
    (vc-do-command 0 "prs" file 'MASTER)
    (vc-do-command 0 "rlog" file 'MASTER)
-   (vc-do-command 0 "cvs" file 'BASE "rlog")))
+   (vc-do-command 0 "cvs" file 'WORKFILE "rlog")))
 
 (defun vc-backend-assign-name (file name)
   ;; Assign to a FILE's latest version a given NAME.
   (vc-backend-dispatch file
    (vc-add-triple name file (vc-latest-version file))   	;; SCCS
    (vc-do-command 0 "rcs" file 'MASTER (concat "-n" name ":"))	;; RCS
-   (vc-do-command 0 "cvs" file 'BASE "tag" name)	        ;; CVS
+   (vc-do-command 0 "cvs" file 'WORKFILE "tag" name)	        ;; CVS
    )
   )
 
@@ -1878,6 +1944,7 @@
       (let* ((command (if (eq backend 'SCCS)
 			  "vcdiff"
 			"rcsdiff"))
+	     (mode (if (eq backend 'RCS) 'WORKFILE 'MASTER))
 	     (options (append (list (and cmp "--brief")
 				    "-q"
 				    (and oldvers (concat "-r" oldvers))
@@ -1886,10 +1953,10 @@
 				   (if (listp diff-switches)
 				       diff-switches
 				     (list diff-switches)))))
-	     (status (apply 'vc-do-command 2 command file options)))
+	     (status (apply 'vc-do-command 2 command file mode options)))
 	;; Some RCS versions don't understand "--brief"; work around this.
 	(if (eq status 2)
-	    (apply 'vc-do-command 1 command file 'MASTER
+	    (apply 'vc-do-command 1 command file 'WORKFILE
 		   (if cmp (cdr options) options))
 	  status)))
      ;; CVS is different.  
@@ -1901,12 +1968,12 @@
 	  (if (or oldvers newvers)
 	      (error "No revisions of %s exists" file)
 	    (apply 'vc-do-command
-		   1 "diff" file 'BASE "/dev/null"
+		   1 "diff" file 'WORKFILE "/dev/null"
 		   (if (listp diff-switches)
 		       diff-switches
 		     (list diff-switches))))
 	(apply 'vc-do-command
-	       1 "cvs" file 'BASE "diff"
+	       1 "cvs" file 'WORKFILE "diff"
 	       (and oldvers (concat "-r" oldvers))
 	       (and newvers (concat "-r" newvers))
 	       (if (listp diff-switches)
@@ -1921,7 +1988,7 @@
    file
    (error "vc-backend-merge-news not meaningful for SCCS files") ;SCCS
    (error "vc-backend-merge-news not meaningful for RCS files")	;RCS
-   (vc-do-command 1 "cvs" file 'BASE "update") ;CVS
+   (vc-do-command 1 "cvs" file 'WORKFILE "update") ;CVS
    ))
 
 (defun vc-check-headers ()
@@ -2041,23 +2108,13 @@
 	(lambda (f) (or
 		     (string-equal f ".")
 		     (string-equal f "..")
+		     (member f vc-directory-exclusion-list)
 		     (let ((dirf (concat dir f)))
 			(or
 			 (file-symlink-p dirf) ;; Avoid possible loops
 			 (vc-file-tree-walk-internal dirf func args))))))
        (directory-files dir)))))
 
-(defun vc-dir-all-files (func &rest args)
-  "Invoke FUNC f ARGS on each regular file f in default directory."
-  (let ((dir default-directory))
-    (message "Scanning directory %s..." dir)
-    (mapcar (function (lambda (f)
-			(let ((dirf (expand-file-name f dir)))
-			  (if (file-regular-p dirf)
-			      (apply func dirf args)))))
-	    (directory-files dir))
-    (message "Scanning directory %s...done" dir)))
-
 (provide 'vc)
 
 ;;; DEVELOPER'S NOTES ON CONCURRENCY PROBLEMS IN THIS CODE