Mercurial > hg > xemacs-beta
diff lisp/dired/dired-rcs.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/dired/dired-rcs.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,196 @@ +;;;; dired-rcs.el - RCS support for Tree Dired + +(defconst dired-rcs-version (substring "!Revision: 1.6 !" 11 -2) + "I don't speak RCS-ese") + +;; Originally written by Sebastian Kremer <sk@thp.uni-koeln.de> +;; Rewritten by Heiko Muenkel <muenkel@tnt.uni-hannover.de> + +;; Copyright (C) 1991 by Sebastian Kremer <sk@thp.uni-koeln.de> +;; Copyright (C) 1994 by Heiko Muenkel <muenkel@tnt.uni-hannover.de> + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 1, or (at your option) +;; any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +;; INSTALLATION ====================================================== +;; +;; This will not work with classic (18.xx) Dired, you'll need Tree Dired, +;; available via anonymous ftp from +;; +;; ftp.thp.Uni-Koeln.DE[134.95.64.1]:/pub/gnu/emacs/diredall.tar.Z +;; +;; Put this file into your load-path and the following in your ~/.emacs: +;; +;; (autoload 'dired-rcs-mark-rcs-locked-files "dired-rcs") +;; (autoload 'dired-rcs-mark-rcs-files "dired-rcs") +;; +;; Put this inside your dired-load-hook: +;; +;; (define-key dired-mode-map "," 'dired-rcs-mark-rcs-files) +;; (define-key dired-mode-map "\M-," 'dired-rcs-mark-rcs-locked-files) +;; + +(require 'dired) + +;;;###autoload +(defun dired-rcs-mark-rcs-locked-files (&optional unflag-p) + "Mark all files that are under RCS control and RCS-locked. +With prefix argument, unflag all those files. +Mentions RCS files for which a working file was not found in this buffer. +Type \\[dired-why] to see them again." + (interactive "P") + (dired-rcs-mark-rcs-files unflag-p t)) + +;;;###autoload +(defun dired-rcs-mark-rcs-files (&optional unflag-p locked) + "Mark all files that are under RCS control. +With prefix argument, unflag all those files. +Mentions RCS files for which a working file was not found in this buffer. +Type \\[dired-why] to see them again." + ;; Returns list of failures, or nil on success. + ;; Optional arg LOCKED means just mark RCS-locked files. + (interactive "P") + (message "%s %sRCS controlled files..." + (if unflag-p "Unmarking" "Marking") + (if locked "locked " "")) + (let ((dired-marker-char (if unflag-p ?\ dired-marker-char)) + rcs-files wf failures count total) + ;; Loop over subdirs to set `rcs-files' + (mapcar + (function + (lambda (dir) + (or (equal (file-name-nondirectory (directory-file-name dir)) + "RCS") + ;; skip inserted RCS subdirs + (setq rcs-files + (append (if locked + ;; these two functions from sk's rcs.el + (rcs-locked-files dir) + (rcs-files dir)) + rcs-files))))) + (mapcar (function car) dired-subdir-alist)) + (setq total (length rcs-files)) + (while rcs-files + (setq wf (rcs-working-file (car rcs-files)) + rcs-files (cdr rcs-files)) + (save-excursion (if (dired-goto-file wf) + (dired-mark-file 1) + (dired-log "RCS working file not found: %s\n" wf) + (setq failures (cons (dired-make-relative wf) + failures))))) + (if (null failures) + (message "%d %sRCS file%s %smarked." + total + (if locked "locked " "") + (dired-plural-s total) + (if unflag-p "un" "")) + (setq count (length failures)) + (dired-log-summary "RCS working file not found %s" failures) + (message "%d %sRCS file%s: %d %smarked - %d not found %s." + total + (if locked "locked " "") + (dired-plural-s total) (- total count) + (if unflag-p "un" "") count failures)) + failures)) + +(defun rcs-files (directory) + "Return list of RCS data files for all RCS controlled files in DIRECTORY." + (setq directory (file-name-as-directory directory)) + (let ((rcs-dir (file-name-as-directory (expand-file-name "RCS" directory))) + (rcs-files (directory-files directory t ",v$"))) + (if (file-directory-p rcs-dir) + (setq rcs-files + (append (directory-files rcs-dir t ",v$") + rcs-files))) + rcs-files)) + +(defvar rcs-output-buffer "*RCS-output*" + "If non-nil, buffer name used by function `rcs-get-output-buffer' (q.v.). +If nil, a new buffer is used each time.") + +(defun rcs-get-output-buffer (file) + ;; Get a buffer for RCS output for FILE, make it writable and clean + ;; it up. Return the buffer. + ;; The buffer used is named according to variable + ;; `rcs-output-buffer'. If the caller wants to be reentrant, it + ;; should let-bind this to nil: a new buffer will be chosen. + (let* ((default-major-mode 'fundamental-mode);; no frills! + (buf (get-buffer-create (or rcs-output-buffer "*RCS-output*")))) + (if rcs-output-buffer + nil + (setq buf (generate-new-buffer "*RCS-output*"))) + (save-excursion + (set-buffer buf) + (setq buffer-read-only nil + default-directory (file-name-directory (expand-file-name file))) + (erase-buffer)) + buf)) + +(defun rcs-locked-files (directory) + "Return list of RCS data file names of all RCS-locked files in DIRECTORY." + (let ((output-buffer (rcs-get-output-buffer directory)) + (rcs-files (rcs-files directory)) + result) + (and rcs-files + (save-excursion + (set-buffer output-buffer) + (apply (function call-process) "rlog" nil t nil "-L" "-R" rcs-files) + (goto-char (point-min)) + (while (not (eobp)) + (setq result (cons (buffer-substring (point) + (progn (forward-line 1) + (1- (point)))) + result))) + result)))) + +(defun rcs-working-file (filename) + "Convert an RCS file name to a working file name. +That is, convert `...foo,v' and `...RCS/foo,v' to `...foo'. +If FILENAME doesn't end in `,v' it is returned unchanged." + (if (not (string-match ",v$" filename)) + filename + (setq filename (substring filename 0 -2)) + (let ((dir (file-name-directory filename))) + (if (null dir) + filename + (let ((dir-file (directory-file-name dir))) + (if (equal "RCS" (file-name-nondirectory dir-file)) + ;; Working file for ./RCS/foo,v is ./foo. + ;; Don't use expand-file-name as this converts "" -> pwd + ;; and thus forces a relative FILENAME to be relative to + ;; the current value of default-directory, which may not + ;; what the caller wants. Besides, we want to change + ;; FILENAME only as much as necessary. + (concat (file-name-directory dir-file) + (file-name-nondirectory filename)) + filename)))))) + +(defun dired-do-vc-register (&optional arg) + "Register the marked (or next ARG) files under version control." + (interactive "P") + (dired-mark-map-check (function dired-vc-register) arg 'register t)) + +(defun dired-vc-register () + (let ((file (dired-get-filename)) failure) + (condition-case err + (save-window-excursion + (find-file file) + (vc-register)) + (error (setq failure err))) + (if (not failure) + nil + (dired-log "Register error for %s:\n%s\n" file failure) + (dired-make-relative file)))) + +(provide 'dired-rcs)