;;; pcvs.el --- a front-end to CVS
-;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;; 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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.
;; - 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
by appending the branch to ARG which defaults to \"-r\".
Since the `cvs-secondary-branch-prefix' is only active if the primary
prefix is active, it is important to read the secondary prefix before
-the primay since reading the primary can deactivate it."
+the primary since reading the primary can deactivate it."
(let ((branch (and (cvs-prefix-get 'cvs-branch-prefix 'read-only)
(cvs-prefix-get 'cvs-secondary-branch-prefix))))
(if branch (cons (concat (or arg "-r") branch) flags) flags)))
;; 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
;;(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))))
;; 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)
(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))
(str (car hf))
(done "")
(tin (ewoc-nth cvs-cookies 0)))
- ;; look for the first *real* fileinfo (to determine emptyness)
+ ;; look for the first *real* fileinfo (to determine emptiness)
(while
(and tin
(memq (cvs-fileinfo->type (ewoc-data tin))
(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))))
(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))
(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
(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))
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.
(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.
(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
(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
(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))))))
(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.
(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.
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 ()
(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'."
(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)
(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)
(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)
-;; arch-tag: 8e3a7494-0453-4389-9ab3-a557ce9fab61
;;; pcvs.el ends here