]> code.delx.au - gnu-emacs/blobdiff - lisp/vc/pcvs.el
Merge from emacs-24; up to 2012-12-27T17:59:21Z!rgm@gnu.org
[gnu-emacs] / lisp / vc / pcvs.el
index 1066ebc7f816ec66972af8c44776bfc20c795f75..208b93d9670524d3e037daeaaf54b18f20ebb8a3 100644 (file)
@@ -1,6 +1,6 @@
 ;;; pcvs.el --- a front-end to CVS
 
-;; Copyright (C) 1991-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2013 Free Software Foundation, Inc.
 
 ;; Author: (The PCL-CVS Trust) pcl-cvs@cyclic.com
 ;;     (Per Cederqvist) ceder@lysator.liu.se
 
 ;;; Commentary:
 
-;; PCL-CVS is a front-end to the CVS version control system.  For people
-;; familiar with VC, it is somewhat like VC-dired: it presents the status of
-;; all the files in your working area and allows you to commit/update several
-;; of them at a time.  Compared to VC-dired, it is considerably better and
-;; faster (but only for CVS).
+;; PCL-CVS is a front-end to the CVS version control system.
+;; It presents the status of all the files in your working area and
+;; allows you to commit/update several of them at a time.
+;; Compare with the general Emacs utility vc-dir, which tries
+;; to be VCS-agnostic.  You may find PCL-CVS better/faster for CVS.
 
 ;; PCL-CVS was originally written by Per Cederqvist many years ago.  This
 ;; version derives from the XEmacs-21 version, itself based on the 2.0b2
 ;; version (last release from Per).  It is a thorough rework.
 
-;; Contrary to what you'd expect, PCL-CVS is not a replacement for VC but only
-;; for VC-dired.  As such, I've tried to make PCL-CVS and VC interoperate
-;; seamlessly (I also use VC).
+;; PCL-CVS is not a replacement for VC, but adds extra functionality.
+;; As such, I've tried to make PCL-CVS and VC interoperate seamlessly
+;; (I also use VC).
 
 ;; To use PCL-CVS just use `M-x cvs-examine RET <dir> RET'.
 ;; There is a TeXinfo manual, which can be helpful to get started.
@@ -60,8 +60,6 @@
 ;; - rework the displaying of error messages.
 ;; - allow to flush messages only
 ;; - allow to protect files like ChangeLog from flushing
-;; - automatically cvs-mode-insert files from find-file-hook
-;;   (and don't flush them as long as they are visited)
 ;; - query the user for cvs-get-marked (for some cmds or if nothing's selected)
 ;; - don't return the first (resp last) FI if the cursor is before
 ;;   (resp after) it.
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(eval-when-compile (require 'cl-lib))
 (require 'ewoc)                                ;Ewoc was once cookie
 (require 'pcvs-defs)
 (require 'pcvs-util)
 (autoload 'cvs-status-get-tags "cvs-status")
 (defun cvs-tags-list ()
   "Return a list of acceptable tags, ready for completions."
-  (assert (cvs-buffer-p))
+  (cl-assert (cvs-buffer-p))
   (let ((marked (cvs-get-marked)))
-    (list* '("BASE") '("HEAD")
-          (when marked
-            (with-temp-buffer
-              (process-file cvs-program
-                            nil        ;no input
-                            t          ;output to current-buffer
-                            nil        ;don't update display while running
-                            "status"
-                            "-v"
-                            (cvs-fileinfo->full-name (car marked)))
-              (goto-char (point-min))
-              (let ((tags (cvs-status-get-tags)))
-                (when (listp tags) tags)))))))
+    `(("BASE") ("HEAD")
+      ,@(when marked
+          (with-temp-buffer
+            (process-file cvs-program
+                          nil           ;no input
+                          t            ;output to current-buffer
+                          nil           ;don't update display while running
+                          "status"
+                          "-v"
+                          (cvs-fileinfo->full-name (car marked)))
+            (goto-char (point-min))
+            (let ((tags (cvs-status-get-tags)))
+              (when (listp tags) tags)))))))
 
 (defvar cvs-tag-history nil)
 (defconst cvs-qtypedesc-tag
@@ -426,16 +424,16 @@ If non-nil, NEW means to create a new buffer no matter what."
              ;; look for another cvs buffer visiting the same directory
              (save-excursion
                (unless new
-                 (dolist (buffer (cons (current-buffer) (buffer-list)))
+                 (cl-dolist (buffer (cons (current-buffer) (buffer-list)))
                    (set-buffer buffer)
                    (and (cvs-buffer-p)
-                        (case cvs-reuse-cvs-buffer
-                          (always t)
-                          (subdir
-                           (or (cvs-string-prefix-p default-directory dir)
-                               (cvs-string-prefix-p dir default-directory)))
-                          (samedir (string= default-directory dir)))
-                        (return buffer)))))
+                        (pcase cvs-reuse-cvs-buffer
+                          (`always t)
+                          (`subdir
+                           (or (string-prefix-p default-directory dir)
+                               (string-prefix-p dir default-directory)))
+                          (`samedir (string= default-directory dir)))
+                        (cl-return buffer)))))
              ;; we really have to create a new buffer:
              ;; we temporarily bind cwd to "" to prevent
              ;; create-file-buffer from using directory info
@@ -478,7 +476,7 @@ If non-nil, NEW means to create a new buffer no matter what."
           ;;(set-buffer buf)
           buffer))))))
 
-(defun* cvs-cmd-do (cmd dir flags fis new
+(cl-defun cvs-cmd-do (cmd dir flags fis new
                        &key cvsargs noexist dont-change-disc noshow)
   (let* ((dir (file-name-as-directory
               (abbreviate-file-name (expand-file-name dir))))
@@ -501,7 +499,7 @@ If non-nil, NEW means to create a new buffer no matter what."
 ;;            cvsbuf))))
 
 (defun cvs-run-process (args fis postprocess &optional single-dir)
-  (assert (cvs-buffer-p cvs-buffer))
+  (cl-assert (cvs-buffer-p cvs-buffer))
   (save-current-buffer
     (let ((procbuf (current-buffer))
          (cvsbuf cvs-buffer)
@@ -521,9 +519,9 @@ If non-nil, NEW means to create a new buffer no matter what."
                  (let ((inhibit-read-only t))
                    (insert "pcl-cvs: descending directory " dir "\n"))
                  ;; loop to find the same-dir-elems
-                 (do* ((files () (cons (cvs-fileinfo->file fi) files))
-                       (fis fis (cdr fis))
-                       (fi (car fis) (car fis)))
+                 (cl-do* ((files () (cons (cvs-fileinfo->file fi) files))
+                           (fis fis (cdr fis))
+                           (fi (car fis) (car fis)))
                      ((not (and fis (string= dir (cvs-fileinfo->dir fi))))
                       (list dir files fis))))))
             (dir (nth 0 dir+files+rest))
@@ -813,7 +811,7 @@ TIN specifies an optional starting point."
   (while (and tin (cvs-fileinfo< fi (ewoc-data tin)))
     (setq tin (ewoc-prev c tin)))
   (if (null tin) (ewoc-enter-first c fi) ;empty collection
-    (assert (not (cvs-fileinfo< fi (ewoc-data tin))))
+    (cl-assert (not (cvs-fileinfo< fi (ewoc-data tin))))
     (let ((next-tin (ewoc-next c tin)))
       (while (not (or (null next-tin)
                      (cvs-fileinfo< fi (ewoc-data next-tin))))
@@ -858,7 +856,8 @@ the problem."
 (defun cvs-cleanup-collection (c rm-handled rm-dirs rm-msgs)
   "Remove undesired entries.
 C is the collection
-RM-HANDLED if non-nil means remove handled entries.
+RM-HANDLED if non-nil means remove handled entries (if file is currently
+  visited, only remove if value is `all').
 RM-DIRS behaves like `cvs-auto-remove-directories'.
 RM-MSGS if non-nil means remove messages."
   (let (last-fi first-dir (rerun t))
@@ -871,15 +870,19 @@ RM-MSGS if non-nil means remove messages."
           (let* ((type (cvs-fileinfo->type fi))
                  (subtype (cvs-fileinfo->subtype fi))
                  (keep
-                  (case type
-                    ;; remove temp messages and keep the others
-                    (MESSAGE (not (or rm-msgs (eq subtype 'TEMP))))
-                    ;; remove entries
-                    (DEAD nil)
-                    ;; handled also?
-                    (UP-TO-DATE (not rm-handled))
-                    ;; keep the rest
-                    (t (not (run-hook-with-args-until-success
+                  (pcase type
+                    ;; Remove temp messages and keep the others.
+                    (`MESSAGE (not (or rm-msgs (eq subtype 'TEMP))))
+                    ;; Remove dead entries.
+                    (`DEAD nil)
+                    ;; Handled also?
+                    (`UP-TO-DATE
+                      (not
+                       (if (find-buffer-visiting (cvs-fileinfo->full-name fi))
+                           (eq rm-handled 'all)
+                         rm-handled)))
+                    ;; Keep the rest.
+                    (_ (not (run-hook-with-args-until-success
                              'cvs-cleanup-functions fi))))))
 
             ;; mark dirs for removal
@@ -887,7 +890,7 @@ RM-MSGS if non-nil means remove messages."
                        (eq (cvs-fileinfo->type last-fi) 'DIRCHANGE)
                        (not (when first-dir (setq first-dir nil) t))
                        (or (eq rm-dirs 'all)
-                           (not (cvs-string-prefix-p
+                           (not (string-prefix-p
                                  (cvs-fileinfo->dir last-fi)
                                  (cvs-fileinfo->dir fi)))
                            (and (eq type 'DIRCHANGE) (eq rm-dirs 'empty))
@@ -1389,7 +1392,7 @@ an empty list if it doesn't point to a file at all."
                      fis))))
     (nreverse fis)))
 
-(defun* cvs-mode-marked (filter &optional cmd
+(cl-defun cvs-mode-marked (filter &optional cmd
                                &key read-only one file noquery)
   "Get the list of marked FIS.
 CMD is used to determine whether to use the marks or not.
@@ -1474,7 +1477,7 @@ The POSTPROC specified there (typically `log-edit') is then called,
   (let ((msg (buffer-substring-no-properties (point-min) (point-max))))
     (cvs-mode!)
     ;;(pop-to-buffer cvs-buffer)
-    (cvs-mode-do "commit" (list* "-m" msg flags) 'commit)))
+    (cvs-mode-do "commit" `("-m" ,msg ,@flags) 'commit)))
 
 
 ;;;; Editing existing commit log messages.
@@ -1604,7 +1607,7 @@ With prefix argument, prompt for cvs flags."
                         (or current-prefix-arg (not cvs-add-default-message)))
                    (read-from-minibuffer "Enter description: ")
                  (or cvs-add-default-message "")))
-          (flags (list* "-m" msg flags))
+          (flags `("-m" ,msg ,@flags))
           (postproc
            ;; setup postprocessing for the directory entries
            (when dirs
@@ -1617,7 +1620,8 @@ With prefix argument, prompt for cvs flags."
 (defun-cvs-mode (cvs-mode-diff . DOUBLE) (flags)
   "Diff the selected files against the repository.
 This command compares the files in your working area against the
-revision which they are based upon."
+revision which they are based upon.
+See also `cvs-diff-ignore-marks'."
   (interactive
    (list (cvs-add-branch-prefix
          (cvs-add-secondary-branch-prefix
@@ -1758,7 +1762,7 @@ Signal an error if there is no backup file."
            (set-buffer-modified-p nil)
            (let ((buffer-file-name (expand-file-name file)))
              (after-find-file))
-           (toggle-read-only 1)
+           (setq buffer-read-only t)
            (message "Retrieving revision %s... Done" rev)
            (current-buffer))))))
 
@@ -1839,13 +1843,13 @@ Signal an error if there is no backup file."
     (setq buffer-file-name (expand-file-name buffer-file-name))
     (let (ret)
       (dolist (fi (or fis (list (cvs-create-fileinfo 'DIRCHANGE "" "." ""))))
-       (when (cvs-string-prefix-p
+       (when (string-prefix-p
               (expand-file-name (cvs-fileinfo->full-name fi) dir)
               buffer-file-name)
          (setq ret t)))
       ret)))
 
-(defun* cvs-mode-run (cmd flags fis
+(cl-defun cvs-mode-run (cmd flags fis
                      &key (buf (cvs-temp-buffer))
                           dont-change-disc cvsargs postproc)
   "Generic cvs-mode-<foo> function.
@@ -1887,7 +1891,7 @@ POSTPROC is a list of expressions to be evaluated at the very end (after
       (cvs-run-process args fis postproc single-dir))))
 
 
-(defun* cvs-mode-do (cmd flags filter
+(cl-defun cvs-mode-do (cmd flags filter
                     &key show dont-change-disc cvsargs postproc)
   "Generic cvs-mode-<foo> function.
 Executes `cvs CVSARGS CMD FLAGS' on the selected files.
@@ -2119,7 +2123,7 @@ if you are convinced that the process that created the lock is dead."
 Empty directories are removed."
   (interactive)
   (cvs-cleanup-collection cvs-cookies
-                         t (or cvs-auto-remove-directories 'handled) t))
+                         'all (or cvs-auto-remove-directories 'handled) t))
 
 
 (defun-cvs-mode cvs-mode-acknowledge ()
@@ -2261,7 +2265,7 @@ With prefix argument, prompt for cvs flags."
 (defun cvs-dir-member-p (fileinfo dir)
   "Return true if FILEINFO represents a file in directory DIR."
   (and (not (eq (cvs-fileinfo->type fileinfo) 'DIRCHANGE))
-       (cvs-string-prefix-p dir (cvs-fileinfo->dir fileinfo))))
+       (string-prefix-p dir (cvs-fileinfo->dir fileinfo))))
 
 (defun cvs-execute-single-file (fi extractor program constant-args)
   "Internal function for `cvs-execute-single-file-list'."
@@ -2392,7 +2396,7 @@ The exact behavior is determined also by `cvs-dired-use-hook'."
          (set-buffer cvs-buf)
          ;; look for a corresponding pcl-cvs buffer
          (when (and (eq major-mode 'cvs-mode)
-                    (cvs-string-prefix-p default-directory dir))
+                    (string-prefix-p default-directory dir))
            (let ((subdir (substring dir (length default-directory))))
              (set-buffer buffer)
              (set (make-local-variable 'cvs-buffer) cvs-buf)
@@ -2423,7 +2427,7 @@ The exact behavior is determined also by `cvs-dired-use-hook'."
          (set-buffer cvs-buf)
          ;; look for a corresponding pcl-cvs buffer
          (when (and (eq major-mode 'cvs-mode)
-                    (cvs-string-prefix-p default-directory file))
+                    (string-prefix-p default-directory file))
            (let* ((file (substring file (length default-directory)))
                   (fi (cvs-create-fileinfo
                        (if (string= "0" version)
@@ -2435,6 +2439,21 @@ The exact behavior is determined also by `cvs-dired-use-hook'."
 
 (add-hook 'after-save-hook 'cvs-mark-buffer-changed)
 
+(defun cvs-insert-visited-file ()
+  (let* ((file (expand-file-name buffer-file-name))
+        (version (and (fboundp 'vc-backend)
+                      (eq (vc-backend file) 'CVS)
+                      (vc-working-revision file))))
+    (when version
+      (save-current-buffer
+       (dolist (cvs-buf (buffer-list))
+         (set-buffer cvs-buf)
+         ;; look for a corresponding pcl-cvs buffer
+         (when (and (eq major-mode 'cvs-mode)
+                    (string-prefix-p default-directory file))
+            (cvs-insert-file file)))))))
+
+(add-hook 'find-file-hook 'cvs-insert-visited-file 'append)
 \f
 (provide 'pcvs)