Trailing whitespace deleted.
[bpt/emacs.git] / lisp / vc-sccs.el
index 79936a0..ac11190 100644 (file)
@@ -1,11 +1,11 @@
 ;;; vc-sccs.el --- support for SCCS version-control
 
-;; Copyright (C) 1992,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
+;; Copyright (C) 1992,93,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc.
 
 ;; Author:     FSF (see vc.el for full credits)
 ;; Maintainer: Andre Spiegel <spiegel@gnu.org>
 
-;; $Id: vc-sccs.el,v 1.1 2000/09/04 19:48:23 gerd Exp $
+;; $Id: vc-sccs.el,v 1.20 2002/12/26 14:07:15 spiegel Exp $
 
 ;; This file is part of GNU Emacs.
 
 
 ;;; Code:
 
+(eval-when-compile
+  (require 'vc))
+
+;;;
+;;; Customization options
+;;;
+
 (defcustom vc-sccs-register-switches nil
-  "*A string or list of strings; extra switches for registering a file
-in |SCCS.  These are passed to the checkin program by
+  "*Extra switches for registering a file in SCCS.
+A string or list of strings passed to the checkin program by
 \\[vc-sccs-register]."
   :type '(choice (const :tag "None" nil)
                 (string :tag "Argument String")
                 (repeat :tag "Argument List"
                         :value ("")
                         string))
+  :version "21.1"
+  :group 'vc)
+
+(defcustom vc-sccs-diff-switches nil
+  "*A string or list of strings specifying extra switches for `vcdiff',
+the diff utility used for SCCS under VC."
+    :type '(choice (const :tag "None" nil)
+                (string :tag "Argument String")
+                (repeat :tag "Argument List"
+                        :value ("")
+                        string))
+  :version "21.1"
   :group 'vc)
 
 (defcustom vc-sccs-header (or (cdr (assoc 'SCCS vc-header-alist)) '("%W%"))
   "*Header keywords to be inserted by `vc-insert-headers'."
-  :type 'string
+  :type '(repeat string)
   :group 'vc)
 
 ;;;###autoload
@@ -54,13 +73,28 @@ For a description of possible values, see `vc-check-master-templates'."
                 (repeat :tag "User-specified"
                         (choice string
                                 function)))
-  :version "20.5"
+  :version "21.1"
   :group 'vc)
 
+\f
+;;;
+;;; Internal variables
+;;;
+
 (defconst vc-sccs-name-assoc-file "VC-names")
 
-;;;###autoload
-(progn (defun vc-sccs-registered (f) (vc-default-registered 'SCCS f)))
+\f
+;;;
+;;; State-querying functions
+;;;
+
+;;; The autoload cookie below places vc-sccs-registered directly into
+;;; loaddefs.el, so that vc-sccs.el does not need to be loaded for
+;;; every file that is visited.  The definition is repeated below
+;;; so that Help and etags can find it.
+
+;;;###autoload (defun vc-sccs-registered(f) (vc-default-registered 'SCCS f))
+(defun vc-sccs-registered (f) (vc-default-registered 'SCCS f))
 
 (defun vc-sccs-state (file)
   "SCCS-specific function to compute the version control state."
@@ -96,7 +130,7 @@ For a description of possible values, see `vc-check-master-templates'."
               (if (file-ownership-preserved-p file)
                   'edited
                 (vc-user-login-name owner-uid))
-          ;; Strange permissions.  
+          ;; Strange permissions.
           ;; Fall through to real state computation.
           (vc-sccs-state file)))
     (vc-sccs-state file))))
@@ -107,17 +141,204 @@ For a description of possible values, see `vc-check-master-templates'."
     (vc-insert-file (vc-name file) "^\001e")
     (vc-parse-buffer "^\001d D \\([^ ]+\\)" 1)))
 
-(defun vc-sccs-checkout-model (file) 
+(defun vc-sccs-checkout-model (file)
   "SCCS-specific version of `vc-checkout-model'."
   'locking)
 
 (defun vc-sccs-workfile-unchanged-p (file)
   "SCCS-specific implementation of vc-workfile-unchanged-p."
-  (apply 'vc-do-command nil 1 "vcdiff" (vc-name file)
-         (list "--brief" "-q" 
-               (concat "-r" (vc-workfile-version file)))))
+  (zerop (apply 'vc-do-command nil 1 "vcdiff" (vc-name file)
+                (list "--brief" "-q"
+                      (concat "-r" (vc-workfile-version file))))))
+
+\f
+;;;
+;;; State-changing functions
+;;;
+
+(defun vc-sccs-register (file &optional rev comment)
+  "Register FILE into the SCCS version-control system.
+REV is the optional revision number for the file.  COMMENT can be used
+to provide an initial description of FILE.
+
+`vc-register-switches' and `vc-sccs-register-switches' are passed to
+the SCCS command (in that order).
+
+Automatically retrieve a read-only version of the file with keywords
+expanded if `vc-keep-workfiles' is non-nil, otherwise, delete the workfile."
+    (let* ((switches (append
+                    (if (stringp vc-register-switches)
+                        (list vc-register-switches)
+                      vc-register-switches)
+                    (if (stringp vc-sccs-register-switches)
+                        (list vc-sccs-register-switches)
+                      vc-sccs-register-switches)))
+          (dirname (or (file-name-directory file) ""))
+          (basename (file-name-nondirectory file))
+          (project-file (vc-sccs-search-project-dir dirname basename)))
+      (let ((vc-name
+            (or project-file
+                (format (car vc-sccs-master-templates) dirname basename)))|)
+       (apply 'vc-do-command nil 0 "admin" vc-name
+              (and rev (concat "-r" rev))
+              "-fb"
+              (concat "-i" (file-relative-name file))
+              (and comment (concat "-y" comment))
+              switches))
+      (delete-file file)
+      (if vc-keep-workfiles
+         (vc-do-command nil 0 "get" (vc-name file)))))
+
+(defun vc-sccs-responsible-p (file)
+  "Return non-nil if SCCS thinks it would be responsible for registering FILE."
+  ;; TODO: check for all the patterns in vc-sccs-master-templates
+  (or (file-directory-p (expand-file-name "SCCS" (file-name-directory file)))
+      (stringp (vc-sccs-search-project-dir (or (file-name-directory file) "")
+                                          (file-name-nondirectory file)))))
+
+(defun vc-sccs-checkin (file rev comment)
+  "SCCS-specific version of `vc-backend-checkin'."
+  (let ((switches (if (stringp vc-checkin-switches)
+                     (list vc-checkin-switches)
+                   vc-checkin-switches)))
+    (apply 'vc-do-command nil 0 "delta" (vc-name file)
+          (if rev (concat "-r" rev))
+          (concat "-y" comment)
+          switches)
+    (if vc-keep-workfiles
+       (vc-do-command nil 0 "get" (vc-name file)))))
+
+(defun vc-sccs-find-version (file rev buffer)
+  (apply 'vc-do-command
+        buffer 0 "get" (vc-name file)
+        "-s" ;; suppress diagnostic output
+        "-p"
+        (and rev
+             (concat "-r"
+                     (vc-sccs-lookup-triple file rev)))
+        (if (stringp vc-checkout-switches)
+            (list vc-checkout-switches)
+          vc-checkout-switches)))
+
+(defun vc-sccs-checkout (file &optional editable rev)
+  "Retrieve a copy of a saved version of SCCS controlled FILE.
+EDITABLE non-nil means that the file should be writable and
+locked.  REV is the revision to check out."
+  (let ((file-buffer (get-file-buffer file))
+       switches)
+    (message "Checking out %s..." file)
+    (save-excursion
+      ;; Change buffers to get local value of vc-checkout-switches.
+      (if file-buffer (set-buffer file-buffer))
+      (setq switches (if (stringp vc-checkout-switches)
+                        (list vc-checkout-switches)
+                      vc-checkout-switches))
+      ;; Save this buffer's default-directory
+      ;; and use save-excursion to make sure it is restored
+      ;; in the same buffer it was saved in.
+      (let ((default-directory default-directory))
+       (save-excursion
+         ;; Adjust the default-directory so that the check-out creates
+         ;; the file in the right place.
+         (setq default-directory (file-name-directory file))
+
+         (and rev (or (string= rev "")
+                       (not (stringp rev)))
+               (setq rev nil))
+         (apply 'vc-do-command nil 0 "get" (vc-name file)
+                (if editable "-e")
+                (and rev (concat "-r" (vc-sccs-lookup-triple file rev)))
+                switches))))
+    (message "Checking out %s...done" file)))
+
+(defun vc-sccs-revert (file &optional contents-done)
+  "Revert FILE to the version it was based on."
+  (vc-do-command nil 0 "unget" (vc-name file))
+  (vc-do-command nil 0 "get" (vc-name file))
+  ;; Checking out explicit versions is not supported under SCCS, yet.
+  ;; We always "revert" to the latest version; therefore
+  ;; vc-workfile-version is cleared here so that it gets recomputed.
+  (vc-file-setprop file 'vc-workfile-version nil))
+
+(defun vc-sccs-cancel-version (file editable)
+  "Undo the most recent checkin of FILE.
+EDITABLE non-nil means previous version should be locked."
+  (vc-do-command nil 0 "rmdel"
+                (vc-name file)
+                (concat "-r" (vc-workfile-version file)))
+  (vc-do-command nil 0 "get"
+                (vc-name file)
+                (if editable "-e")))
+
+(defun vc-sccs-steal-lock (file &optional rev)
+  "Steal the lock on the current workfile for FILE and revision REV."
+  (vc-do-command nil 0 "unget" (vc-name file) "-n" (if rev (concat "-r" rev)))
+  (vc-do-command nil 0 "get" (vc-name file) "-g" (if rev (concat "-r" rev))))
+
+\f
+;;;
+;;; History functions
+;;;
+
+(defun vc-sccs-print-log (file)
+  "Get change log associated with FILE."
+  (vc-do-command nil 0 "prs" (vc-name file)))
+
+(defun vc-sccs-logentry-check ()
+  "Check that the log entry in the current buffer is acceptable for SCCS."
+  (when (>= (buffer-size) 512)
+    (goto-char 512)
+    (error "Log must be less than 512 characters; point is now at pos 512")))
+
+(defun vc-sccs-diff (file &optional oldvers newvers)
+  "Get a difference report using SCCS between two versions of FILE."
+  (setq oldvers (vc-sccs-lookup-triple file oldvers))
+  (setq newvers (vc-sccs-lookup-triple file newvers))
+  (apply 'vc-do-command "*vc-diff*" 1 "vcdiff" (vc-name file)
+         (append (list "-q"
+                       (and oldvers (concat "-r" oldvers))
+                       (and newvers (concat "-r" newvers)))
+                 (vc-diff-switches-list 'SCCS))))
+
+\f
+;;;
+;;; Snapshot system
+;;;
+
+(defun vc-sccs-assign-name (file name)
+  "Assign to FILE's latest version a given NAME."
+  (vc-sccs-add-triple name file (vc-workfile-version file)))
+
+\f
+;;;
+;;; Miscellaneous
+;;;
+
+(defun vc-sccs-check-headers ()
+  "Check if the current file has any headers in it."
+  (save-excursion
+    (goto-char (point-min))
+    (re-search-forward  "%[A-Z]%" nil t)))
+
+(defun vc-sccs-rename-file (old new)
+  ;; Move the master file (using vc-rcs-master-templates).
+  (vc-rename-master (vc-name old) new vc-sccs-master-templates)
+  ;; Update the snapshot file.
+  (with-current-buffer
+      (find-file-noselect
+       (expand-file-name vc-sccs-name-assoc-file
+                        (file-name-directory (vc-name old))))
+    (goto-char (point-min))
+    ;; (replace-regexp (concat ":" (regexp-quote old) "$") (concat ":" new))
+    (while (re-search-forward (concat ":" (regexp-quote old) "$") nil t)
+      (replace-match (concat ":" new) nil nil))
+    (basic-save-buffer)
+    (kill-buffer (current-buffer))))
 
-;; internal code
+\f
+;;;
+;;; Internal functions
+;;;
 
 ;; This function is wrapped with `progn' so that the autoload cookie
 ;; copies the whole function itself into loaddefs.el rather than just placing
@@ -160,16 +381,6 @@ The result is a list of the form ((VERSION . USER) (VERSION . USER) ...)."
            (cons (cons (match-string 1) (match-string 2)) master-locks)))
     ;; FIXME: is it really necessary to reverse ?
     (nreverse master-locks)))
-\f
-(defun vc-sccs-print-log (file)
-  "Get change log associated with FILE."
-  (vc-do-command t 0 "prs" (vc-name file)))
-
-(defun vc-sccs-assign-name (file name)
-  "Assign to FILE's latest version a given NAME."
-  (vc-sccs-add-triple name file (vc-workfile-version file)))
-\f
-;; Named-configuration support
 
 (defun vc-sccs-add-triple (name file rev)
   (with-current-buffer
@@ -181,25 +392,10 @@ The result is a list of the form ((VERSION . USER) (VERSION . USER) ...)."
     (basic-save-buffer)
     (kill-buffer (current-buffer))))
 
-(defun vc-sccs-rename-file (old new)
-  ;; Move the master file (using vc-rcs-master-templates).
-  (vc-rename-master (vc-name old) new vc-sccs-master-templates)
-  ;; Update the snapshot file.
-  (with-current-buffer
-      (find-file-noselect
-       (expand-file-name vc-sccs-name-assoc-file
-                        (file-name-directory (vc-name old))))
-    (goto-char (point-min))
-    ;; (replace-regexp (concat ":" (regexp-quote old) "$") (concat ":" new))
-    (while (re-search-forward (concat ":" (regexp-quote old) "$") nil t)
-      (replace-match (concat ":" new) nil nil))
-    (basic-save-buffer)
-    (kill-buffer (current-buffer))))
-
 (defun vc-sccs-lookup-triple (file name)
   "Return the numeric version corresponding to a named snapshot of FILE.
 If NAME is nil or a version number string it's just passed through."
-  (if (or (null name) 
+  (if (or (null name)
          (let ((firstchar (aref name 0)))
            (and (>= firstchar ?0) (<= firstchar ?9))))
       name
@@ -209,180 +405,6 @@ If NAME is nil or a version number string it's just passed through."
                         (file-name-directory (vc-name file))))
       (vc-parse-buffer (concat name "\t:\t" file "\t\\(.+\\)") 1))))
 
-(defun vc-sccs-merge (file first-version &optional second-version)
-  (error "Merging not implemented for SCCS"))
-
-(defun vc-sccs-check-headers ()
-  "Check if the current file has any headers in it."
-  (save-excursion
-    (goto-char (point-min))
-    (re-search-forward  "%[A-Z]%" nil t)))
-
-(defun vc-sccs-steal-lock (file &optional rev)
-  "Steal the lock on the current workfile for FILE and revision REV."
-  (vc-do-command nil 0 "unget" (vc-name file) "-n" (if rev (concat "-r" rev)))
-  (vc-do-command nil 0 "get" (vc-name file) "-g" (if rev (concat "-r" rev))))
-
-(defun vc-sccs-cancel-version (file writable)
-  "Undo the most recent checkin of FILE.  
-WRITABLE non-nil means previous version should be locked."
-  (vc-do-command nil 0 "rmdel" 
-                (vc-name file) 
-                (concat "-r" (vc-workfile-version file)))
-  (vc-do-command nil 0 "get"
-                (vc-name file)
-                (if writable "-e")))
-
-(defun vc-sccs-revert (file)
-  "Revert FILE to the version it was based on."
-  (vc-do-command nil 0 "unget" (vc-name file))
-  (vc-do-command nil 0 "get" (vc-name file))
-  ;; Checking out explicit versions is not supported under SCCS, yet.
-  ;; We always "revert" to the latest version; therefore
-  ;; vc-workfile-version is cleared here so that it gets recomputed.
-  (vc-file-setprop file 'vc-workfile-version nil))
-
-(defun vc-sccs-checkin (file rev comment)
-  "SCCS-specific version of `vc-backend-checkin'."
-  (let ((switches (if (stringp vc-checkin-switches)
-                     (list vc-checkin-switches)
-                   vc-checkin-switches)))
-    (apply 'vc-do-command nil 0 "delta" (vc-name file)
-          (if rev (concat "-r" rev))
-          (concat "-y" comment)
-          switches)
-    (if vc-keep-workfiles
-       (vc-do-command nil 0 "get" (vc-name file)))))
-
-(defun vc-sccs-latest-on-branch-p (file)
-  "Return t iff the current workfile version of FILE is the latest on
-its branch."
-  ;; Always return t; we do not support previous versions in the workfile
-  ;; under SCCS.
-  t)
-
-(defun vc-sccs-logentry-check ()
-  "Check that the log entry in the current buffer is acceptable for SCCS."
-  (when (>= (buffer-size) 512)
-    (goto-char 512)
-    (error "Log must be less than 512 characters; point is now at pos 512")))
-
-(defun vc-sccs-diff (file &optional oldvers newvers)
-  "Get a difference report using SCCS between two versions of FILE."
-  (setq oldvers (vc-sccs-lookup-triple file oldvers))
-  (setq newvers (vc-sccs-lookup-triple file newvers))
-  (let* ((diff-switches-list (if (listp diff-switches)
-                                diff-switches
-                              (list diff-switches)))
-        (options (append (list "-q"
-                               (and oldvers (concat "-r" oldvers))
-                               (and newvers (concat "-r" newvers)))
-                         diff-switches-list)))
-    (apply 'vc-do-command t 1 "vcdiff" (vc-name file) options)))
-
-(defun vc-sccs-responsible-p (file)
-  "Return non-nil if SCCS thinks it would be responsible for registering FILE."
-  ;; TODO: check for all the patterns in vc-sccs-master-templates
-  (or (file-directory-p (expand-file-name "SCCS" (file-name-directory file)))
-      (stringp (vc-sccs-search-project-dir (or (file-name-directory file) "")
-                                          (file-name-nondirectory file)))))
-
-(defun vc-sccs-register (file &optional rev comment)
-  "Register FILE into the SCCS version-control system.
-REV is the optional revision number for the file.  COMMENT can be used
-to provide an initial description of FILE.
-
-`vc-register-switches' and `vc-sccs-register-switches' are passed to
-the SCCS command (in that order).
-
-Automatically retrieve a read-only version of the file with keywords
-expanded if `vc-keep-workfiles' is non-nil, otherwise, delete the workfile."
-    (vc-file-clearprops file)
-    (let* ((switches (list
-                    (if (stringp vc-register-switches)
-                        (list vc-register-switches)
-                      vc-register-switches)
-                    (if (stringp vc-sccs-register-switches)
-                        (list vc-sccs-register-switches)
-                      vc-sccs-register-switches)))
-          (dirname (or (file-name-directory file) ""))
-          (basename (file-name-nondirectory file))
-          (project-file (vc-sccs-search-project-dir dirname basename)))
-      (let ((vc-name
-            (or project-file
-                (format (car vc-sccs-master-templates) dirname basename)))|)
-       (apply 'vc-do-command nil 0 "admin" nil 
-              (and rev (concat "-r" rev))
-              "-fb"
-              (concat "-i" file)
-              (and comment (concat "-y" comment))
-              vc-name
-              switches))
-      (delete-file file)
-      (if vc-keep-workfiles
-         (vc-do-command nil 0 "get" (vc-name file)))))
-
-(defun vc-sccs-checkout (file &optional writable rev workfile)
-  "Retrieve a copy of a saved version of an SCCS controlled FILE into
-a WORKFILE.  WRITABLE non-nil means that the file should be writable.
-REV is the revision to check out into WORKFILE."
-  (let ((filename (or workfile file))
-       (file-buffer (get-file-buffer file))
-       switches)
-    (message "Checking out %s..." filename)
-    (save-excursion
-      ;; Change buffers to get local value of vc-checkout-switches.
-      (if file-buffer (set-buffer file-buffer))
-      (setq switches (if (stringp vc-checkout-switches)
-                        (list vc-checkout-switches)
-                      vc-checkout-switches))
-      ;; Save this buffer's default-directory
-      ;; and use save-excursion to make sure it is restored
-      ;; in the same buffer it was saved in.
-      (let ((default-directory default-directory))
-       (save-excursion
-         ;; Adjust the default-directory so that the check-out creates
-         ;; the file in the right place.
-         (setq default-directory (file-name-directory filename))
-
-         (and rev (string= rev "") (setq rev nil))
-         (if workfile
-             ;; Some SCCS implementations allow checking out directly to a
-             ;; file using the -G option, but then some don't so use the
-             ;; least common denominator approach and use the -p option
-             ;; ala RCS.
-             (let ((vc-modes (logior (file-modes (vc-name file))
-                                     (if writable 128 0)))
-                   (failed t))
-               (unwind-protect
-                   (progn
-                      (let ((coding-system-for-read 'no-conversion)
-                            (coding-system-for-write 'no-conversion))
-                        (with-temp-file filename
-                          (apply 'vc-do-command
-                                 (current-buffer) 0 "get" (vc-name file)
-                                 "-s" ;; suppress diagnostic output
-                                 (if writable "-e")
-                                 "-p" 
-                                 (and rev
-                                      (concat "-r" 
-                                              (vc-sccs-lookup-triple file rev)))
-                                 switches)))
-                      (set-file-modes filename
-                                      (logior (file-modes (vc-name file))
-                                              (if writable 128 0)))
-                     (setq failed nil))
-                 (and failed (file-exists-p filename)
-                      (delete-file filename))))
-           (apply 'vc-do-command nil 0 "get" (vc-name file)
-                  (if writable "-e")
-                  (and rev (concat "-r" (vc-sccs-lookup-triple file rev)))
-                  switches)))))
-    (message "Checking out %s...done" filename)))
-
-(defun vc-sccs-update-changelog (files)
-  (error "Sorry, generating ChangeLog entries is not implemented for SCCS."))
-
 (provide 'vc-sccs)
 
 ;;; vc-sccs.el ends here