]> code.delx.au - gnu-emacs/blobdiff - lisp/vc/vc-rcs.el
Resurrect the ability to specify a revision in vc-next-action
[gnu-emacs] / lisp / vc / vc-rcs.el
index cb3d36f13fb2d93184d49fb7a6654d549f6123c1..ba1336424ea019a9674c279bb73bd96b4764513e 100644 (file)
@@ -1,6 +1,6 @@
 ;;; vc-rcs.el --- support for RCS version-control  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-2014 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2015 Free Software Foundation, Inc.
 
 ;; Author:     FSF (see vc.el for full credits)
 ;; Maintainer: Andre Spiegel <spiegel@gnu.org>
@@ -76,7 +76,7 @@ If nil, use the value of `vc-diff-switches'.  If t, use no switches."
   :version "21.1"
   :group 'vc-rcs)
 
-(defcustom vc-rcs-header '("\$Id\$")
+(defcustom vc-rcs-header '("$Id\ $")
   "Header keywords to be inserted by `vc-insert-headers'."
   :type '(repeat string)
   :version "24.1"     ; no longer consult the obsolete vc-header-alist
@@ -243,7 +243,9 @@ to the RCS command."
             ;; if available, use the secure registering option
             (and (vc-rcs-release-p "5.6.4") "-i")
             "-u"
-            (and comment (concat "-t-" comment))
+             ;; Some old MS-Windows ports of RCS crash when "ci -i" is
+             ;; invoked without -t; indulge them.
+            (concat "-t-" (or comment ""))
             (vc-switches 'RCS 'register))
       ;; parse output to find master file name and workfile version
       (with-current-buffer "*vc*"
@@ -288,42 +290,39 @@ to the RCS command."
   "Unregister FILE from RCS.
 If this leaves the RCS subdirectory empty, ask the user
 whether to remove it."
-  (let* ((master (vc-master-name file))
-        (dir (file-name-directory master))
-        (backup-info (find-backup-file-name master)))
-    (if (not backup-info)
-       (delete-file master)
-      (rename-file master (car backup-info) 'ok-if-already-exists)
-      (dolist (f (cdr backup-info)) (ignore-errors (delete-file f))))
-    (and (string= (file-name-nondirectory (directory-file-name dir)) "RCS")
-        ;; check whether RCS dir is empty, i.e. it does not
-        ;; contain any files except "." and ".."
-        (not (directory-files dir nil
-                              "^\\([^.]\\|\\.[^.]\\|\\.\\.[^.]\\).*"))
-        (yes-or-no-p (format "Directory %s is empty; remove it? " dir))
-        (delete-directory dir))))
-
-;; It used to be possible to pass in a value for the variable rev, but
-;; nothing in the rest of VC used this capability.  Removing it makes the
-;; backend interface simpler for all modes.
-;;
-(defun vc-rcs-checkin (files comment)
+  (unless (memq (vc-state file) '(nil unregistered))
+    (let* ((master (vc-master-name file))
+          (dir (file-name-directory master))
+          (backup-info (find-backup-file-name master)))
+      (if (not backup-info)
+         (delete-file master)
+       (rename-file master (car backup-info) 'ok-if-already-exists)
+       (dolist (f (cdr backup-info)) (ignore-errors (delete-file f))))
+      (and (string= (file-name-nondirectory (directory-file-name dir)) "RCS")
+          ;; check whether RCS dir is empty, i.e. it does not
+          ;; contain any files except "." and ".."
+          (not (directory-files dir nil
+                                "^\\([^.]\\|\\.[^.]\\|\\.\\.[^.]\\).*"))
+          (yes-or-no-p (format "Directory %s is empty; remove it? " dir))
+          (delete-directory dir)))))
+
+(defun vc-rcs-checkin (files comment &optional rev)
   "RCS-specific version of `vc-backend-checkin'."
-  (let (rev (switches (vc-switches 'RCS 'checkin)))
+  (let ((switches (vc-switches 'RCS 'checkin)))
     ;; Now operate on the files
     (dolist (file (vc-expand-dirs files 'RCS))
       (let ((old-version (vc-working-revision file)) new-version
            (default-branch (vc-file-getprop file 'vc-rcs-default-branch)))
        ;; Force branch creation if an appropriate
        ;; default branch has been set.
-       (and default-branch
+       (and (not rev)
+             default-branch
             (string-match (concat "^" (regexp-quote old-version) "\\.")
                           default-branch)
             (setq rev default-branch)
             (setq switches (cons "-f" switches)))
-       (if old-version
-           (setq rev (vc-branch-part old-version))
-         (error "can't find current branch"))
+       (if (and (not rev) old-version)
+           (setq rev (vc-branch-part old-version)))
        (apply #'vc-do-command "*vc*" 0 "ci" (vc-master-name file)
               ;; if available, use the secure check-in option
               (and (vc-rcs-release-p "5.6.4") "-j")
@@ -757,7 +756,7 @@ Optional arg REVISION is a revision to annotate from."
       (insert (gethash (get-text-property (point) :vc-rcs-r/d/a) ht))
       (forward-line 1))))
 
-(declare-function vc-annotate-convert-time "vc-annotate" (time))
+(declare-function vc-annotate-convert-time "vc-annotate" (&optional time))
 
 (defun vc-rcs-annotate-current-time ()
   "Return the current time, based at midnight of the current day, and
@@ -971,74 +970,75 @@ otherwise determine the workfile version based on the master file.
 This function sets the properties `vc-working-revision' and
 `vc-checkout-model' to their correct values, based on the master
 file."
-  (with-temp-buffer
-    (if (or (not (vc-insert-file (vc-master-name file) "^[0-9]"))
-            (progn (goto-char (point-min))
-                   (not (looking-at "^head[ \t\n]+[^;]+;$"))))
-        (error "File %s is not an RCS master file" (vc-master-name file)))
-    (let ((workfile-is-latest nil)
-         (default-branch (vc-parse-buffer "^branch[ \t\n]+\\([^;]*\\);" 1)))
-      (vc-file-setprop file 'vc-rcs-default-branch default-branch)
-      (unless working-revision
-       ;; Workfile version not known yet.  Determine that first.  It
-       ;; is either the head of the trunk, the head of the default
-       ;; branch, or the "default branch" itself, if that is a full
-       ;; revision number.
-       (cond
-        ;; no default branch
-        ((or (not default-branch) (string= "" default-branch))
-         (setq working-revision
-               (vc-parse-buffer "^head[ \t\n]+\\([^;]+\\);" 1))
-         (setq workfile-is-latest t))
-        ;; default branch is actually a revision
-        ((string-match "^[0-9]+\\.[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*$"
-                       default-branch)
-         (setq working-revision default-branch))
-        ;; else, search for the head of the default branch
-        (t (vc-insert-file (vc-master-name file) "^desc")
+  (when (and (file-regular-p file) (vc-master-name file))
+    (with-temp-buffer
+      (if (or (not (vc-insert-file (vc-master-name file) "^[0-9]"))
+             (progn (goto-char (point-min))
+                    (not (looking-at "^head[ \t\n]+[^;]+;$"))))
+         (error "File %s is not an RCS master file" (vc-master-name file)))
+      (let ((workfile-is-latest nil)
+           (default-branch (vc-parse-buffer "^branch[ \t\n]+\\([^;]*\\);" 1)))
+       (vc-file-setprop file 'vc-rcs-default-branch default-branch)
+       (unless working-revision
+         ;; Workfile version not known yet.  Determine that first.  It
+         ;; is either the head of the trunk, the head of the default
+         ;; branch, or the "default branch" itself, if that is a full
+         ;; revision number.
+         (cond
+          ;; no default branch
+          ((or (not default-branch) (string= "" default-branch))
            (setq working-revision
-                 (vc-rcs-find-most-recent-rev default-branch))
-           (setq workfile-is-latest t)))
-       (vc-file-setprop file 'vc-working-revision working-revision))
-      ;; Check strict locking
-      (goto-char (point-min))
-      (vc-file-setprop file 'vc-checkout-model
-                      (if (re-search-forward ";[ \t\n]*strict;" nil t)
-                          'locking 'implicit))
-      ;; Compute state of workfile version
-      (goto-char (point-min))
-      (let ((locking-user
-            (vc-parse-buffer (concat "^locks[ \t\n]+[^;]*[ \t\n]+\\([^:]+\\):"
-                                     (regexp-quote working-revision)
-                                     "[^0-9.]")
-                             1)))
-       (cond
-        ;; not locked
-        ((not locking-user)
-          (if (or workfile-is-latest
-                  (vc-rcs-latest-on-branch-p file working-revision))
-              ;; workfile version is latest on branch
-              'up-to-date
-            ;; workfile version is not latest on branch
-            'needs-update))
-        ;; locked by the calling user
-        ((and (stringp locking-user)
-              (string= locking-user (vc-user-login-name file)))
-          ;; Don't call `vc-rcs-checkout-model' to avoid inf-looping.
-         (if (or (eq (vc-file-getprop file 'vc-checkout-model) 'locking)
-                 workfile-is-latest
-                 (vc-rcs-latest-on-branch-p file working-revision))
-             'edited
-           ;; Locking is not used for the file, but the owner does
-           ;; have a lock, and there is a higher version on the current
-           ;; branch.  Not sure if this can occur, and if it is right
-           ;; to use `needs-merge' in this case.
-           'needs-merge))
-        ;; locked by somebody else
-        ((stringp locking-user)
-         locking-user)
-        (t
-         (error "Error getting state of RCS file")))))))
+                 (vc-parse-buffer "^head[ \t\n]+\\([^;]+\\);" 1))
+           (setq workfile-is-latest t))
+          ;; default branch is actually a revision
+          ((string-match "^[0-9]+\\.[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*$"
+                         default-branch)
+           (setq working-revision default-branch))
+          ;; else, search for the head of the default branch
+          (t (vc-insert-file (vc-master-name file) "^desc")
+             (setq working-revision
+                   (vc-rcs-find-most-recent-rev default-branch))
+             (setq workfile-is-latest t)))
+         (vc-file-setprop file 'vc-working-revision working-revision))
+       ;; Check strict locking
+       (goto-char (point-min))
+       (vc-file-setprop file 'vc-checkout-model
+                        (if (re-search-forward ";[ \t\n]*strict;" nil t)
+                            'locking 'implicit))
+       ;; Compute state of workfile version
+       (goto-char (point-min))
+       (let ((locking-user
+              (vc-parse-buffer (concat "^locks[ \t\n]+[^;]*[ \t\n]+\\([^:]+\\):"
+                                       (regexp-quote working-revision)
+                                       "[^0-9.]")
+                               1)))
+         (cond
+          ;; not locked
+          ((not locking-user)
+           (if (or workfile-is-latest
+                   (vc-rcs-latest-on-branch-p file working-revision))
+               ;; workfile version is latest on branch
+               'up-to-date
+             ;; workfile version is not latest on branch
+             'needs-update))
+          ;; locked by the calling user
+          ((and (stringp locking-user)
+                (string= locking-user (vc-user-login-name file)))
+           ;; Don't call `vc-rcs-checkout-model' to avoid inf-looping.
+           (if (or (eq (vc-file-getprop file 'vc-checkout-model) 'locking)
+                   workfile-is-latest
+                   (vc-rcs-latest-on-branch-p file working-revision))
+               'edited
+             ;; Locking is not used for the file, but the owner does
+             ;; have a lock, and there is a higher version on the current
+             ;; branch.  Not sure if this can occur, and if it is right
+             ;; to use `needs-merge' in this case.
+             'needs-merge))
+          ;; locked by somebody else
+          ((stringp locking-user)
+           locking-user)
+          (t
+           (error "Error getting state of RCS file"))))))))
 
 (defun vc-rcs-consult-headers (file)
   "Search for RCS headers in FILE, and set properties accordingly.
@@ -1114,12 +1114,12 @@ Returns: nil            if no headers were found
 (defun vc-release-greater-or-equal (r1 r2)
   "Compare release numbers, represented as strings.
 Release components are assumed cardinal numbers, not decimal fractions
-\(5.10 is a higher release than 5.9\).  Omitted fields are considered
-lower \(5.6.7 is earlier than 5.6.7.1\).  Comparison runs till the end
+\(5.10 is a higher release than 5.9).  Omitted fields are considered
+lower \(5.6.7 is earlier than 5.6.7.1).  Comparison runs till the end
 of the string is found, or a non-numeric component shows up \(5.6.7 is
 earlier than \"5.6.7 beta\", which is probably not what you want in
-some cases\).  This code is suitable for existing RCS release numbers.
-CVS releases are handled reasonably, too \(1.3 < 1.4* < 1.5\)."
+some cases).  This code is suitable for existing RCS release numbers.
+CVS releases are handled reasonably, too \(1.3 < 1.4* < 1.5)."
   (let (v1 v2 i1 i2)
     (catch 'done
       (or (and (string-match "^\\.?\\([0-9]+\\)" r1)