summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/tools
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-08-20 23:46:10 +0000
committerpeter <peter@FreeBSD.org>1996-08-20 23:46:10 +0000
commit8982e501c77217c860f79bba431f46a62b607a21 (patch)
tree70187fdf5be4cbefd0baf46bddac7e5e32c13c24 /contrib/cvs/tools
parent01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5 (diff)
downloadFreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.zip
FreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.tar.gz
Import of slightly trimmed cvs-1.8 distribution. Generated files
and non-unix code has been left out.
Diffstat (limited to 'contrib/cvs/tools')
-rw-r--r--contrib/cvs/tools/ChangeLog7
-rw-r--r--contrib/cvs/tools/Makefile.in76
-rw-r--r--contrib/cvs/tools/README5
-rw-r--r--contrib/cvs/tools/pcl-cvs/ChangeLog891
-rw-r--r--contrib/cvs/tools/pcl-cvs/INSTALL94
-rw-r--r--contrib/cvs/tools/pcl-cvs/Makefile.in238
-rw-r--r--contrib/cvs/tools/pcl-cvs/NEWS149
-rw-r--r--contrib/cvs/tools/pcl-cvs/README25
-rw-r--r--contrib/cvs/tools/pcl-cvs/pcl-cvs-lucid.el134
-rw-r--r--contrib/cvs/tools/pcl-cvs/pcl-cvs-startup.el17
-rw-r--r--contrib/cvs/tools/pcl-cvs/pcl-cvs.el3450
-rw-r--r--contrib/cvs/tools/pcl-cvs/pcl-cvs.texinfo1565
12 files changed, 6651 insertions, 0 deletions
diff --git a/contrib/cvs/tools/ChangeLog b/contrib/cvs/tools/ChangeLog
new file mode 100644
index 0000000..c6b6e1c7d
--- /dev/null
+++ b/contrib/cvs/tools/ChangeLog
@@ -0,0 +1,7 @@
+Sun Apr 14 11:07:43 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * .cvsignore: new file.
+
+ * Makefile.in (subdir): `tools', not `contrib'.
+
+ * Added ChangeLog (this file), and subdir `pcl-cvs'.
diff --git a/contrib/cvs/tools/Makefile.in b/contrib/cvs/tools/Makefile.in
new file mode 100644
index 0000000..c83d1a8
--- /dev/null
+++ b/contrib/cvs/tools/Makefile.in
@@ -0,0 +1,76 @@
+# Makefile for GNU CVS auxiliary tools.
+# Do not use this makefile directly, but only from `../Makefile'.
+# Copyright (C) 1986, 1988-1990 Free Software Foundation, Inc.
+
+# 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 2, 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.
+
+# $CVSid: @(#)Makefile.in 1.6 94/10/22 $
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+# Where to put the manual pages.
+mandir = $(prefix)/man
+
+# Use cp if you don't have install.
+INSTALL = @INSTALL@
+
+DISTFILES = ChangeLog README .cvsignore Makefile.in
+
+all: Makefile
+.PHONY: all
+
+install: all
+ @echo "pcl-cvs not installed"
+.PHONY: install
+
+tags:
+.PHONY: tags
+
+TAGS:
+.PHONY: TAGS
+
+ls:
+ @echo $(DISTFILES)
+.PHONY: ls
+
+clean:
+ /bin/rm -f *.o core
+.PHONY: clean
+
+distclean: clean
+ rm -f Makefile pcl-cvs/Makefile
+.PHONY: distclean
+
+realclean: distclean
+.PHONY: realclean
+
+dist-dir:
+ mkdir ${DISTDIR}
+ for i in ${DISTFILES}; do \
+ ln $(srcdir)/$${i} ${DISTDIR}; \
+ done
+ cd pcl-cvs; ${MAKE} dist-dir DISTDIR="../${DISTDIR}/pcl-cvs"
+.PHONY: dist-dir
+
+subdir = tools
+Makefile: ../config.status Makefile.in
+ cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
diff --git a/contrib/cvs/tools/README b/contrib/cvs/tools/README
new file mode 100644
index 0000000..af7bd7e
--- /dev/null
+++ b/contrib/cvs/tools/README
@@ -0,0 +1,5 @@
+ This subdirectory contains tools that can be used with CVS.
+Note that they will not necessarily be installed when you "make
+install" from the top-level of the CVS source tree.
+
+pcl-cvs ............................. an Emacs interface to CVS.
diff --git a/contrib/cvs/tools/pcl-cvs/ChangeLog b/contrib/cvs/tools/pcl-cvs/ChangeLog
new file mode 100644
index 0000000..0192b93
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/ChangeLog
@@ -0,0 +1,891 @@
+Mon Apr 15 01:34:27 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * Makefile: removed. Why was this in the repository in the first
+ place?
+
+ * Makefile.in (BATCHFLAGS): don't pass -q to Emacs when compiling,
+ because Emacs probably can't find Elib's cookie.el[c] if we do
+ that. (Actually, it still can't, but that may be due to a bug in
+ Emacs).
+
+ * INSTALL: reflect changed location of elib in the CVS dist.
+
+Sun Apr 14 12:18:12 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * pcl-cvs.el (cookie): Changed "(load \"cookie\")" to
+ "(require 'cookie)", since elib is now included again.
+ Moved "(provide 'pcl-cvs)" to the end of the file, so it's not
+ provided if the package didn't load successfully.
+
+ * Makefile.in (subdir): tools/pcl-cvs now, not contrib/pcl-cvs.
+ (BATCHFLAGS): removed "-n" from BATCHFLAGS. Emacs 19.30 does not
+ know about this flag.
+ (OBJDIR_DISTFILES): don't include .elc files here, add comment
+ explaining why.
+
+Thu Apr 11 20:22:34 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * pcl-cvs.el (cvs-mode-map): conform to Emacs 19 keybinding
+ conventions by not binding any regular letters under C-c.
+
+Fri Feb 9 14:29:07 1996 Jim Blandy <jimb@totoro.cyclic.com>
+
+ * Makefile.in (mostlyclean clean realclean): Remove 'realclean'
+ from this target list; it's already defined later in the file.
+
+Tue Jan 23 13:02:24 1996 Greg A. Woods <woods@most.weird.com>
+
+ * pcl-cvs.el (pcl-cvs-bugs-address): change the default address
+ as suggested by Per Cederqvist.
+ * pcl-cvs.el: removed comments refering to Signum, etc.
+
+Sun Jan 21 12:51:12 1996 Greg A. Woods <woods@most.weird.com>
+
+ * pcl-cvs.el (cvs-parse-stderr): fix typo (missing '\') that was
+ causing occasional un-reported, un-traced, failures that simply
+ said something like "RE missing '\(' or '\\('" -- hopefully this
+ is the last such bug!
+
+Tue Jan 16 13:57:16 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in: Rename "dist" target back to "dist-dir". The
+ latter is what actually gets used.
+ (pcl-cvs.dvi): Restore srcdir to pcl-cvs.texinfo. Fix typo
+ (pcl-cvs.texifo -> pcl-cvs.texinfo).
+ (TEXINDEX,TEX,SET_TEXINPUTS): New variables.
+ (.el.elc): Copy .el file to build dir so .elc file gets put there.
+ (dist-dir): Fix typo (cvs.info -> pcl-cvs.info).
+ * cookie.el: New file, copied from elib 1.0.
+ * README: Remove note about requiring elib; it claimed that CVS
+ contained a copy of elib, but it lied.
+ * pcl-cvs.el: Change (require 'cookie) to (load "cookie.el").
+ * pcl-cvs-lucid.el: Change (require 'pcl-cvs) to (load "pcl-cvs.el").
+
+Fri Jan 12 10:32:14 1996 Greg A. Woods <woods@most.weird.com>
+
+ * pcl-cvs.elc, pcl-cvs-lucid.elc: removed
+
+ * pcl-cvs.el: run through the spell checker...
+ - noted some free variables in comments
+ (cvs-inhibit-copyright-message): move this above
+ cvs-startup-message to keep the compiler quiet
+
+ * compile-all.el: removed (use make for dependency checking!)
+
+ * Makefile.in: tweak various comments and echo messages...
+ (elcfiles): removed this target.
+ (.SUFFIXES, .el.elc): added support for elisp files.
+ (CORE): new macro -- list of files all .elc depend on [still empty]
+ (BATCHFLAGS): new macro -- flags to pass to emacs
+ (OBJDIR_DISTFILES): added ELCFILES to be shipped in distribution
+
+ * README: fix the RCS Id.
+
+ * INSTALL: re-copy formatted makeinfo output from pcl-cvs.info,
+ just to keep everything in proper synchronisation.
+
+ * pcl-cvs.texinfo (Pcl-cvs installation): update to match Karl's
+ new wording from INSTALL.
+
+Wed Jan 10 22:04:35 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * INSTALL: make first item read a little more smoothly.
+
+ * README: note that pcl-cvs has been tested under 19.30.
+
+Wed Jan 10 17:59:00 1996 Greg A. Woods <woods@most.weird.com>
+
+ * ChangeLog.woods: these are changes integrated in from my
+ own pcl-cvs repository module, and based on the original PCL-CVS
+ Version 1.05 release. They include most, if not all, of the
+ changes from the Cygnus and Cyclic CVS contrib versions of
+ PCL-CVS (i.e. the changes noted below).
+
+Sat Dec 30 15:01:45 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * pcl-cvs.el (cvs-changelog-ours-p): check that
+ `add-log-full-name' and `add-log-mailing-address' are non-nil, in
+ addition to checking that they are boundp.
+
+Thu Dec 21 16:45:48 1995 Karl Fogel <kfogel@occs.cs.oberlin.edu>
+
+ * pcl-cvs.el (cvs-parse-stderr): ignore kerberos connection
+ failure, since CVS will automatically try rsh next. I think this
+ is okay because if a person needs to know that kerberos failed,
+ then chances are the rsh failed too, and *that* error message will
+ clue them in that something's afoot.
+
+Wed Nov 22 11:01:50 1995 Joshua Cowan <jcowan@hermit.reslife.okstate.edu>
+
+ * pcl-cvs.el (cvs-changelog-ours-p): use `user-full-name' if
+ `add-log-full-name' unbound, as not every uses the stuff in
+ add-log.el. Same with `add-log-mailing-address'.
+ (cvs-changelog-entries): change to `change-log-mode' unless
+ already in it.
+
+Sun Jul 9 20:57:11 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * "/bin/rmdir" as default, not "/usr/local/bin/rmdir".
+
+Fri Jun 16 15:24:34 1995 Jim Kingdon (kingdon@cyclic.com)
+
+ * pcl-cvs.elc, pcl-cvs-lucid.elc: Added.
+
+ * Makefile.in: Rename from Makefile and set srcdir.
+
+Thu May 18 17:10:27 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ Automatically guess CVS log entries from ChangeLog contents.
+ * pcl-cvs.el (cvs-mode-changelog-commit): New command.
+ (cvs-changelog-full-paragraphs): New variable.
+ (cvs-changelog-name, cvs-narrow-changelog,
+ cvs-changelog-paragraph, cvs-changelog-subparagraph,
+ cvs-changelog-entry, cvs-changelog-ours-p, cvs-relative-path,
+ cvs-changelog-entries, cvs-changelog-insert-entries, cvs-union,
+ cvs-insert-changelog-entries, cvs-edit-delete-common-indentation):
+ New functions.
+ (cvs-mode-map): Bind 'C' to cvs-mode-changelog-commit.
+ (cvs-mode): Mention cvs-mode-changelog-commit in docstring.
+
+ Give the info files names ending in ".info".
+ * Makefile (INFOFILES, install_info): Change pcl-cvs to
+ pcl-cvs.info.
+ (pcl-cvs.info): Target renamed from pcl-cvs.
+ (DISTFILES): pcl-cvs removed; we handle the info files explicitly
+ in the dist-dir target.
+ (dist-dir): Depend on pcl-cvs.info. Distribute pcl-cvs.info*.
+ * pcl-cvs.texinfo: Change @setfilename appropriately.
+ * INSTALL: Updated.
+ * .cvsignore: Correctly ignore the info files.
+
+ * README: Note that pcl-cvs has been tested under 19.28, and that
+ the "cookie" naming conflict was resolved in 19.11.
+
+ * Makefile (pcl-cvs-lucid.elc): Changed this target from
+ pcl-cvs-lucid.el. That's a source file, for goodness' sake!
+
+Tue May 9 13:56:50 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * Change references to "Cygnus's remote CVS" to "Cyclic CVS".
+
+Wed May 3 13:55:27 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * pcl-cvs.el (cvs-parse-stderr): Handle colons after both
+ "rcsmerge" and "warning".
+
+Fri Apr 28 22:38:14 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * Makefile (ELFILES): Include pcl-cvs-startup.el.
+ (info, pcl-cvs): Call makeinfo appropriately for modern versions.
+ (pcl-cvs.aux): List dependency on pcl-cvs.texinfo.
+ (pcl-cvs.ps): New target.
+ (DVIPS): New variable.
+ (dist-dir): Renamed from dist, updated to accept DISTDIR value
+ passed from parent.
+ (DISTFILES): New varible.
+ (pcl-cvs.elc, pcl-cvs-lucid.elc): Add targets to elcfiles target.
+
+Tue Apr 25 21:33:49 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * pcl-cvs.el: (cvs-parse-stderr): Recognize "conflicts" as well as
+ "overlaps" before "during merge."
+
+Thu Feb 16 12:17:20 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * pcl-cvs.el (cvs-parse-stderr): Recognize "conflicts found in..."
+ messages attributed to "cvs server", as well as "cvs update".
+
+Sat Feb 4 01:47:01 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * pcl-cvs.el: Deal with the 'P' action, produced by remote CVS.
+ (cvs-parse-stdout): Treat 'P' like 'U' --- file is updated.
+
+Tue Jan 31 23:31:39 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * pcl-cvs.el (cvs-cvsroot-required): New variable.
+ (cvs-do-update): If cvs-cvsroot-required is not set, don't complain if
+ CVSROOT and cvs-cvsroot are both unset.
+
+Sun Jan 22 21:22:22 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
+
+ * pcl-cvs.el (cvs-parse-stderr):
+ Some changes for Cygnus's Remote CVS. Treat
+ messages like "cvs server: Updating DIRECTORY" as we treat those like
+ "cvs update: Updating DIRECTORY". Ignore other messages starting with
+ "cvs server".
+
+ * pcl-cvs.el (cvs-parse-stderr): Re-indent.
+
+ * .cvsignore: Add ignore list for Texinfo litter.
+
+ * Makefile (lispdir): Set appropriately for totoro.
+ * pcl-cvs.el (cvs-program, cvs-diff-program, cvs-rmdir-program): Same.
+
+Tue Jun 1 00:00:03 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * Release 1.05. (This release was promised before the end of May,
+ but I didn't quite make it. No, I didn't fake the date above).
+
+Mon May 31 01:32:25 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * Removed the elib sub-directory. Users must now get the Elib
+ library separately.
+ * pcl-cvs.texinfo: Document it.
+
+ * pcl-cvs-lucid.el: A new version, supplied by Jamie Zawinsky,
+ added.
+
+ * pcl-cvs Id 68: Transform RCS keywords
+ * Makefile (pcl-cvs-$(VER)): Remove the $ signs in most files in
+ the distribution.
+
+ * pcl-cvs Id 76: Extra " in cvs-mode-add.
+ * pcl-cvs.el (cvs-mode-add): Don't add the extra level of quotes
+ around the log message, since it doesn't work with CVS.
+
+ * pcl-cvs Id 56: '-d <CVSROOT>' support in pcl-cvs
+ * pcl-cvs.el (cvs-change-cvsroot): New function.
+
+ * pcl-cvs Id 77: *cvs* isn't cleared properly
+ * pcl-cvs.el (cvs-do-update): Always erase the *cvs* buffer and
+ re-create the collection.
+
+ * pcl-cvs.el (cvs-do-update): Set mode-line-process in the *cvs*
+ buffer.
+ * pcl-cvs.el (cvs-mode): Reset mode-line-process.
+
+ * pcl-cvs Id 59: sort .cvsignore alphabetically!
+ * pcl-cvs.el (cvs-sort-ignore-file): New variable.
+ * pcl-cvs.el (cvs-mode-ignore): Use it.
+ * pcl-cvs.texinfo: Document it.
+
+ * pcl-cvs Id 75: Require final newline.
+ * pcl-cvs.el (cvs-commit-buffer-require-final-newline): New
+ variable.
+ * pcl-cvs.el (cvs-edit-done): Use it.
+ * pcl-cvs.texinfo: Document it.
+
+ * pcl-cvs Id 72: make clean deletes lucid-emacs.el
+ * dist-makefile (ELCFILES): Fixed a typo.
+
+ * pcl-cvs Id 46: "cvs remove f" "touch f" "cvs update f" -> parse err.
+ * pcl-cvs.el (cvs-fileinfo->type): New type: REM-EXIST.
+ * pcl-cvs.el (cvs-shadow-entry-p): A REMOVED that follows a
+ REM-EXIST is a shadow.
+ * pcl-cvs.el (cvs-parse-stderr): Recognize the "should be removed
+ and is still there" message.
+ * pcl-cvs.el (cvs-pp): Recognize REM-EXIST.
+ * pcl-cvs.el (cvs-mode-undo-local-changes): Recognize and complain
+ about REM-EXIST. Defensive test added: complain about unknown types.
+
+ * pcl-cvs.el (cvs-mode-add): Add an extra level of quotes around
+ the log message. This is apparently needed by RCVS. <This change
+ has been removed. --ceder>.
+
+ * pcl-cvs.el (cvs-parse-stderr): Ignore output from RCVS.
+
+Tue Apr 27 00:48:40 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * pcl-cvs.el (cvs-startup-message): Now a defconst instead of a
+ defvar.
+ * pcl-cvs.el (cvs-mode-commit): Add a defvar for it.
+
+ * dist-makefile (EMACS): Use $(EMACS) instead of hard-coding 'emacs'.
+
+Sat Apr 17 12:47:10 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * Release 1.04.
+
+ * pcl-cvs.texinfo: Updated the Contributors node.
+
+ * pcl-cvs Id 58: Lucid GNU Emacs support
+ * pcl-cvs-lucid.el: New file, contributed by the people at Lucid.
+ * pcl-cvs.el: Autoload pcl-cvs-lucid if running in an Lucid GNU
+ Emacs.
+ * compile-all.el: (files-to-compile): Add pcl-cvs-lucid.
+ * dist-makefile (ELFILES, ELCFILES): Dito.
+
+ * pcl-cvs Id 55: cvs-diff-backup swaps old and new version.
+ * pcl-cvs.el (cvs-diff-backup-extractor): Old version should be
+ first.
+ * pcl-cvs.el (cvs-mode-diff-backup): Call cvs-backup-diffable
+ correctly.
+
+ * pcl-cvs Id 64: elib substitute
+ * dist-makefile (install): Warn about Elib.
+ * pcl-cvs.texinfo: Talk about Elib.
+
+ * pcl-cvs Id 50: Committing the *commit* buffer twice.
+ * pcl-cvs.el (cvs-edit-done): Report an error if cvs-commit-list
+ is empty, and empty it when the commit is done.
+
+ * pcl-cvs Id 56: '-d <CVSROOT>' support.
+ * pcl-cvs.el (cvs-cvsroot): New variable.
+ * pcl-cvs.el (cvs-do-update, all callers of cvs-execute-list): Use
+ it everywhere CVS is called, to override CVSROOT.
+ * pcl-cvs.texinfo (Customization): Document it.
+
+Thu Apr 1 00:34:55 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * pcl-cvs.el (cvs-retrieve-revision-to-tmpfile): Exit status nil
+ from call-process means everything was successful in some Emacs
+ versions.
+
+ * pcl-cvs.el (cvs-mode-map): Bind "q" to bury-buffer.
+ * pcl-cvs.texinfo: Document it.
+
+Thu Mar 11 00:05:03 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * Release 1.03-Emerge (not released).
+
+ * Makefile (pcl-cvs-$(VER)): Don't includ elib-dll-debug.el in the
+ distribution. (It's included as elib/dll-debug.el).
+
+ * pcl-cvs.el (cvs-mode): Document the "e" key (cvs-mode-emerge).
+
+Tue Mar 9 00:02:57 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * pcl-cvs.texinfo (Emerge): New node.
+
+ * pcl-cvs.el (cvs-kill-buffer-visiting): New function.
+
+ * pcl-cvs.el (cvs-mode-emerge): Handle Conflict and Merged files.
+
+ * pcl-cvs.el (cvs-retrieve-revision-to-tmpfile): Handle any revision.
+
+ * pcl-cvs.el (cvs-fileinfo-*): Store base-revision instead of
+ backup-file.
+
+ * pcl-cvs.el (cvs-backup-diffable): The file is only diffable if
+ the backup file is readable.
+
+ * pcl-cvs.el (cvs-mode-map): Bind "e" to cvs-mode-emerge instead
+ of cvs-mode-find-file (which is anyhow bound to "f").
+
+Mon Mar 8 23:06:52 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * pcl-cvs.el (cvs-mode-emerge): New function. Currently only
+ handles emerge of Modified files.
+
+ * pcl-cvs.el (cvs-retrieve-revision-to-tmpfile): New function.
+
+Sun Jan 24 20:07:18 1993 Per Cederqvist (ceder@lysator.liu.se)
+
+ * elib-dll-debug.el: Moved to elib.
+
+Mon Jan 18 00:35:59 1993 Per Cederqvist (ceder@mauritz)
+
+ * pcl-cvs.el (cvs-do-update): Added a probably unnecessary sit-for.
+
+ * Release 1.03-Elib-0.05.1 (not released).
+
+ * Elib 0.05 compatibility:
+ * elib-dll-debug.el, pcl-cvs-buffer.el, test-dll.el: Fix the
+ require strings.
+ * pcl-cvs.el (cvs-pp): Insert the string.
+
+ * Release 1.03-Elib-0.05 (not released).
+
+ * elib: New directory, containing the parts of elib that are
+ required for pcl-cvs. Changes to the files in that directory
+ that are present in Elib are documented in the ChangeLog of
+ Elib, not here.
+ * Makefile (pcl-cvs-$(VER)): Copy the new dir to the distribution.
+ * dist-makefile (ELFILES, ELCFILES): Don't include the Elib files.
+
+Fri Jan 8 02:43:49 1993 Per Cederqvist (ceder@konrad)
+
+ * pcl-cvs.el (cvs-mode-map): Bind "e" to cvs-mode-find-file, like
+ in dired.
+
+Sun Jan 3 23:25:13 1993 Per Cederqvist (ceder@konrad)
+
+ * elib-dll.el, elib-node.el, cookie.el: Moved to the elib package.
+ Pcl-cvs now requires elib.
+
+Tue Dec 29 22:06:57 1992 Per Cederqvist (ceder@konrad)
+
+ * pcl-cvs.el: Tracked the latest (last?) rename of all functions
+ in cookie.el.
+
+Thu Sep 24 00:29:16 1992 Per Cederqvist (ceder@robert)
+
+ * pcl-cvs.texinfo (Archives): This version is not distributed with
+ CVS 1.3, so don't claim that it is.
+
+Fri Aug 21 15:17:08 1992 Per Cederqvist (ceder@maskros)
+
+ * pcl-cvs.el (cvs-parse-stderr): Fixed two "(set head" that should
+ be "(setq head".
+
+Thu Aug 20 05:53:58 1992 Per Cederqvist (ceder@robin)
+
+ * cookie.el: Changes to this file is documented in the ChangeLog
+ of elib in the future.
+
+Tue Aug 18 03:30:28 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el: Don't use cookie-last-tin (which no longer exists).
+
+ * cookie.el: Use prefix cookie:: for internal functions.
+
+ * cookie.el: (cookie:enter-after, cookie:enter-before,
+ cookie:nth-cookie): Implemented.
+ * cookie.el: No longer define (impl).
+
+ * cookie.el: More renames:
+ cookie:next-cookie -> cookie:goto-next-tin
+ cookie:previous-cookie -> cookie:goto-previous-tin
+ tin-next -> cookie:next-tin
+ tin-previous -> cookie:previous-tin
+ tin-nth -> cookie:nth-tin
+ tin-delete -> cookie:delete-tin
+ cookie:collect -> cookie:collect-cookies
+ cookie:tin-collect -> cookie:collect-tins
+ (new) -> cookie:tin-collect-cookies
+ (new) -> cookie:tin-collect-tins
+ cookie:refresh -> cookie:refresh-all
+ tin-invalidate-tins -> cookie:invalidate-tins
+
+Mon Aug 17 01:39:49 1992 Per Cederqvist (ceder@robin)
+
+ * cookie.el (cookie:set-buffer-bind-dll-let*): New macro. Used in
+ many places instead of cookie:set-buffer-bind-dll.
+ * cookie.el (cookie:set-buffer-bind-dll): Renamed the macro
+ cookie:set-buffer to this.
+
+ * pcl-cvs.el (cvs-use-temp-buffer): Set default-directory.
+
+Sun Aug 16 20:51:30 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-add-sub): Fixed call to cvs-add-file-update-buffer.
+
+Sat Aug 8 20:28:21 1992 Per Cederqvist (ceder@robin)
+
+ * Release 1.03-Cookie-II (not released).
+
+ * pcl-cvs.el (cvs-mode-diff-cvs): Don't care about the exit status
+ from ``cvs diff''.
+
+ * pcl-cvs.el (cvs-mode): Document cvs-mode-undo-local-changes.
+ * pcl-cvs.el (cvs-diffable): New function.
+
+ * pcl-cvs.el: Use the new cookie package.
+ * pcl-cvs.el (cvs-cookie-handle): New variable.
+ * pcl-cvs.el (cvs-do-update): User the new cookie:create
+ interface, and cookie:clear if the buffer already existed. Make
+ the buffer read-only.
+ * pcl-cvs.el (cvs-mode-next-line, cvs-mode-previous-line): New
+ functions (used instead of cookie:next-cookie and
+ cookie:previous-cookie).
+
+ * cookie.el: Major redesign. The handle that is passed to all
+ cookie functions is now a new datatype, and not the buffer that
+ the cookies resides in. This way it is possible to have more than
+ one set of cookies in a buffer. Things that used to be
+ buffer-local variables are now fields in the handle data type.
+ cookie-last-tin is no longer available.
+ * cookie.el (cookie:create): The buffer is not cleared, nor set to
+ be read-only.
+ * cookie.el (cookie:next-cookie, cookie:previous-cookie): Since
+ the first argument is now a handle and not a buffer, these can no
+ longer be called interactively. You have to write a small wrapper
+ about them.
+ * cookie.el (cookie:buffer): New function.
+
+Tue Aug 4 03:02:25 1992 Per Cederqvist (ceder@robert)
+
+ * pcl-cvs.texinfo (Bugs): Renamed "Reporting bugs and ideas" to
+ "Bugs" and added a table of known bugs/FAQ:s.
+
+Mon Aug 3 00:19:39 1992 Per Cederqvist (ceder@robert)
+
+ * pcl-cvs.el, pcl-cvs.texinfo: Big Renaming Time!
+ The commands that operate in the *cvs* buffer:
+ cvs-add-change-log-entry-other-window -> cvs-mode-add-change-log-entry-other-window
+ cvs-mark-all-files -> cvs-mode-mark-all-files
+ cvs-revert-updated-buffers -> cvs-mode-revert-updated-buffers
+ cvs-undo-local-changes -> cvs-mode-undo-local-changes
+ cvs-unmark-up -> cvs-mode-unmark-up
+ cvs-acknowledge -> cvs-mode-acknowledge
+ cvs-unmark-all-files -> cvs-mode-unmark-all-files
+ cvs-add -> cvs-mode-add
+ cvs-diff-backup -> cvs-mode-diff-backup
+ cvs-commit -> cvs-mode-commit
+ cvs-diff-cvs -> cvs-mode-diff-cvs
+ cvs-find-file -> cvs-mode-find-file
+ cvs-update-no-prompt -> cvs-mode-update-no-prompt
+ cvs-ignore -> cvs-mode-ignore
+ cvs-log -> cvs-mode-log
+ cvs-mark -> cvs-mode-mark
+ cvs-find-file-other-window -> cvs-mode-find-file-other-window
+ cvs-remove-file -> cvs-mode-remove-file
+ cvs-status -> cvs-mode-status
+ cvs-remove-handled -> cvs-mode-remove-handled
+ cvs-unmark -> cvs-mode-unmark
+
+ * pcl-cvs.el (cvs-cvs-diff-flags): Variable deleted.
+ * pcl-cvs.el (cvs-diff-cvs): Use cvs-diff-flags instead.
+ * pcl-cvs.texinfo (Customization): Update the doc.
+
+ * pcl-cvs.el (cvs-diff-cvs): Handle exit status 0 (no diffs), 1
+ (diffs) and other (error).
+ * pcl-cvs.el (cvs-execute-list): Add support for this kind of
+ thing.
+
+ * Revert buffers for committed files:
+ * pcl-cvs.el (cvs-auto-revert-after-commit): New variable.
+ * pcl-cvs.texinfo (Committing changes, Customization): Document
+ it.
+ * pcl-cvs.el (cvs-after-commit-function): New function.
+
+ * pcl-cvs.el (cvs-execute-list): Return the exit status or nil.
+ * pcl-cvs.el (cvs-edit-done, cvs-diff-cvs, cvs-remove-file,
+ cvs-undo-local-changes, cvs-add, cvs-status, cvs-log): Use the
+ exit status to generate an error message.
+
+
+ * pcl-cvs.el (cvs-do-update): It should be "cvs -n update -l", not
+ "cvs -l update -n". Put the -n and/or -l in the message that is
+ displayed in the *cvs* buffer during the update.
+
+Sat Aug 1 00:55:49 1992 Per Cederqvist (ceder@robert)
+
+ * cookie.el (cookie-sort): New function.
+
+ * cookie.el (cookie-clear): Rewritten. No longer clears all local
+ variables.
+
+Tue Jul 28 17:21:17 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-parse-stderr): Try to handle the output from RCS
+ when it is compiled without DIFF3_BIN and a conflict occurs.
+
+ * pcl-cvs.texinfo (Getting Started): Fixed typo.
+
+ * pcl-cvs-startup.el (cvs-update-other-window): Make the autoload
+ be interactive.
+
+Mon Jul 27 19:36:40 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-revert-updated-buffers, cvs-revert-fileinfo):
+ New functions.
+ * pcl-cvs.texinfo (Reverting your buffers): Document it.
+
+ * pcl-cvs.el (cvs-fileinfo->full-path): New function.
+ * pcl-cvs.el (cvs-full-path): Use it.
+
+ * cookie.el (cookie-map, cookie-map-reverse): Better doc-
+ string. Removed the unused local variable 'result'.
+
+ * compile-all.el: Renamed elib-files to files-to-compare.
+ * compile-all.el (compile-pcl-cvs): Bind load-path in a let
+ statement instead of globally.
+
+Thu Jul 23 19:02:41 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-do-update): Check that CVSROOT is set.
+ * pcl-cvs.el (cvs-diff-cvs): Check that cvs-cvs-diff-flags is a
+ list.
+ * pcl-cvs.el (cvs-diff-backup): Check that cvs-diff-flags is a
+ list.
+
+Tue Jul 21 11:27:39 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-parse-error): Make the *cvs* buffer writeable
+ before trying to write the email message. Require sendmail before
+ trying to switch to mail-mode.
+
+ * pcl-cvs.el (cvs-do-update): Check that cvs-program exists.
+
+ * pcl-cvs.el (cvs-skip-line): Fixed bracketing error.
+
+Mon Jul 20 10:31:51 1992 Per Cederqvist (ceder@robin)
+
+ * Release 1.03.
+
+ * pcl-cvs.el, cookie.el: Indentation fixes.
+
+ * Makefile (pcl-cvs-$(VER)): Include NEWS in the distribution.
+
+ * pcl-cvs.el (cvs-rm-program): Deleted.
+ * pcl-cvs.el (cvs-rmdir-program, cvs-lock-file): New variables.
+
+ * Handle lock files in a nicer way:
+ * pcl-cvs.el (cvs-update-filter, cvs-delete-lock,
+ cvs-lock-file-p): New functions.
+ * pcl-cvs.el (cvs-do-update, cvs-sentinel): Redirect stdout to the
+ temporary file, not stderr. Use cvs-update-filter.
+ * pcl-cvs.el (cvs-parse-update): New arguments.
+ * pcl-cvs.el (cvs-parse-buffer): Renamed to cvs-parse-update.
+ * pcl-cvs.el (cvs-stderr-file): Renamed to cvs-stdout-file.
+ * pcl-cvs.texinfo (Miscellaneous commands, Updating the
+ directory): Document cvs-delete-lock.
+
+ * pcl-cvs.el (cvs-mode): Don't reset buffer-read-only.
+
+ * pcl-cvs.el (cvs-find-file-other-window): Don't save-some-buffers.
+
+Thu Jul 16 00:19:58 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el, test-cookie-el: Use the new names from cookie.el.
+
+ * cookie.el: Big Renaming Time!
+ External functions:
+ cookie-next -> tin-next
+ cookie-previous -> tin-previous
+ cookie-nth -> tin-nth
+ cookie-delete -> tin-delete
+ cookie-filter-tins -> tin-filter
+ cookie-get-selection -> tin-get-selection
+ cookie-start-marker -> tin-start-marker
+ cookie-end-marker -> tin-end-marker
+ cookie-invalidate-tins -> tin-invalidate-tins
+ cookie-collect-tins -> tin-collect
+ cookie-collect-cookies -> cookie-collect
+ Internal functions:
+ cookie-create-tin -> cookie-create-wrapper
+ cookie-tin-start-marker -> cookie-wrapper-start-marker
+ cookie-tin-cookie-safe -> cookie-wrapper-cookie-safe
+ cookie-tin-cookie -> cookie-wrapper-cookie
+ set-cookie-tin-start-marker -> cookie-wrapper-set-start-marker
+ set-cookie-tin-cookie -> cookie-wrapper-set-cookie
+ cookie-tin-p -> cookie-wrapper-p
+ cookie-create-tin-and-insert -> cookie-create-wrapper-and-insert
+
+ * pcl-cvs.el (cvs-find-file, cvs-find-file-other-window): Signal
+ an appropriate error message if the *cvs* buffer is empty.
+
+ * cookie.el (cookie-create): Make the buffer read-only.
+ * cookie.el (cookie-create-tin-and-insert, cookie-refresh,
+ cookie-delete-tin-internal, cookie-refresh-tin): Bind
+ buffer-read-only to nil while changing the contents of
+ the buffer.
+
+ * pcl-cvs.el (cvs-byte-compile-files): New function.
+ * pcl-cvs.texinfo (Miscellaneous commands): Document it.
+
+ * pcl-cvs.el (cvs-diff-ignore-marks): New variable.
+ * pcl-cvs.el (cvs-diff-cvs, cvs-diff-backup): Don't consider
+ marked files to be selected if a prefix argument is given XOR the
+ variable cvs-diff-ignore-marks is non-nil.
+ * pcl-cvs.el (cvs-get-marked): New optional argument `ignore-marks'.
+ * pcl-cvs.texinfo (Customization, Viewing differences): Document
+ this behaviour.
+
+ * pcl-cvs.el (cvs-undo-local-changes): New function.
+ * pcl-cvs.texinfo (Undoing changes): Document
+ cvs-undo-local-changes.
+ * pcl-cvs.el (cvs-mode-map): cvs-unmark-all-files moved from "U"
+ to "ESC DEL". cvs-undo-local-changes bound to "U".
+ * pcl-cvs.texinfo (Marking files): Document ESC DEL.
+
+ * pcl-cvs.el (cvs-skip-line): New arguments. All callers updated.
+ Now calls cvs-parse-error if a parse error occurs.
+ * pcl-cvs.el (cvs-parse-error): New function that creates a bug
+ report.
+ * pcl-cvs.el (cvs-parse-stderr, cvs-parse-stdout): New arguments.
+ The only caller (cvs-parse-buffer) updated. Call cvs-parse-error
+ in case of parse error.
+
+ * pcl-cvs.el (pcl-cvs-version): New variable.
+
+ * cookie.el (cookie-create): Kill all local variables in the buffer.
+
+Fri Jul 10 11:17:40 1992 Per Cederqvist (ceder@robin)
+
+ * Release 1.03beta1.
+
+Thu Jul 9 03:12:00 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-update-running): New variable.
+ * pcl-cvs.el (cvs-do-update): Use it instead of the previous local
+ variable cvs-process (that no longer exists). Make sure that only
+ one `cvs update' runs at any given moment.
+ * pcl-cvs.el (cvs-sentinel): Reset cvs-update-running when the
+ update process exits.
+
+ * pcl-cvs.el (cvs-update): Switch to the *cvs* buffer.
+ * pcl-cvs.el (cvs-update-other-window): New function.
+ * pcl-cvs-startup.el (cvs-update-other-window): Added a autoload
+ for it.
+ * pcl-cvs.el (cvs-do-update): Don't pop up any buffer in a window
+ - let cvs-update or cvs-update-other-window handle that. Also
+ don't kill the *cvs* buffer, but rather insert a "Running cvs..."
+ message into it.
+ * pcl-cvs.el (cvs-parse-buffer): Don't change the window
+ configuration.
+
+ * pcl-cvs.el (cvs-create-fileinfo, cvs-pp, cvs-fileninfo->type):
+ New type for a fileinfo: MESSAGE.
+
+ * pcl-cvs.el (cvs-cvs-buffer): Deleted the variable. Use
+ cvs-buffer-name instead. (I no longer have any plans to allow more
+ than one cvs update to run at the same time - things only get
+ confusing). Changed all places where cvs-cvs-buffer was used.
+
+ * pcl-cvs.el: Take care of update programs (the -u option in the
+ modules file):
+ * pcl-cvs.el (cvs-update-prog-output-skip-regexp): New variable.
+ * pcl-cvs.el (cvs-parse-stdout): Skip output from the update
+ program (using cvs-update-prog-output-skip-regexp).
+ * pcl-cvs.texinfo (Future enhancements): Document that the
+ solution is not as good as it should be.
+ * pcl-cvs.texinfo (Customization): Document the variable.
+
+Wed Jul 8 20:29:44 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-do-update): Check that this-dir really exists
+ and is a directory, and that this-dir/CVS exists and is a
+ directory.
+
+Tue Jul 7 01:02:24 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.texinfo (Customization): Document TMPDIR.
+
+ * This chunk of modifications should make it possible to run
+ pcl-cvs on hosts that do not line-buffer stdout (such as
+ DECstation). They work by diverting stdout and stderr from
+ `cvs update' and later sorting them together.
+ * pcl-cvs.el (cvs-parse-stderr): Don't fail to parse conflict
+ data.
+ * pcl-cvs.el (cvs-remove-stdout-shadows, cvs-shadow-entry-p): New
+ functions.
+ * pcl-cvs.el (cvs-parse-buffer): Use it.
+ * pcl-cvs.el (cvs-remove-empty-directories): New function.
+ * pcl-cvs.el (cvs-remove-handled, cvs-parse-buffer): Use it.
+ * pcl-cvs.el (cvs-get-current-dir): New argument ROOT-DIR. All
+ calls to cvs-get-current-dir updated.
+ * pcl-cvs.el (cvs-do-update): Allocate a tmp file. Use cvs-shell
+ (typically /bin/sh) to redirect stderr from CVS to the tmp file.
+ * pcl-cvs.el (cvs-sentinel): Handle the tmp file. Remove it when
+ it is parsed.
+ * pcl-cvs.el (cvs-parse-buffer): New argument STDERR-BUFFER. All
+ calls to cvs-parse-buffer updated. Rewritten to handle the
+ separation of stderr and stdout.
+ * pcl-cvs.el (cvs-shell, cvs-stderr-file): New variables.
+ * pcl-cvs.el (cvs-compare-fileinfos, cvs-parse-stderr,
+ cvs-parse-stdout): New functions.
+
+ * pcl-cvs.el (cvs-parse-buffer): Some modifications for output
+ from RCS 5.6.
+
+Tue Apr 7 09:11:27 1992 Per Cederqvist (ceder@leopold)
+
+ * Release 1.02.
+
+ * pcl-cvs.el (cvs-diff-backup, cvs-edit-done, cvs-status): Call
+ save-some-buffers.
+
+ * pcl-cvs.el (cvs-diff-backup-extractor): Fixed syntax error.
+
+ * Makefile, README, compile-all.el, dist-makefile, pcl-cvs.el,
+ pcl-cvs.texinfo (XXRELEASEXX): A magic string that is substituted
+ for the current release number when a distribution is made.
+ (Release 1.01 says that it is release 1.00).
+
+ * pcl-cvs.el (cvs-find-file): Added missing pair of parenthesis.
+
+Mon Mar 30 14:25:26 1992 Per Cederqvist (ceder@leopold)
+
+ * Release 1.01.
+
+ * pcl-cvs.el (cvs-parse-buffer): The message when waiting for a
+ lock has been changed.
+
+Sun Mar 29 05:29:57 1992 Per Cederqvist (ceder@leopold)
+
+ * Release 1.00.
+
+ * pcl-cvs.el (cvs-do-update, cvs-sentinel, cvs-parse-buffer):
+ Major rewrite of buffer and window selection and handling.
+ The *cvs* buffer is now killed whenever a new "cvs update" is
+ initiated. The -update buffer is replaced with the *cvs*
+ buffer when the update is completed.
+
+Sat Mar 28 21:03:05 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-delete-unused-temporary-buffers): Fixed it.
+
+ * pcl-cvs.el (cvs-auto-remove-handled): New variable.
+ * pcl-cvs.el (cvs-edit-done): Use it.
+ * pcl-cvs.texinfo (Customization, Removing handled entries):
+ Document it.
+
+ * pcl-cvs.el (cvs-mode): Turn of the undo feature. It really
+ isn't useful in a cookie buffer...
+
+ * pcl-cvs.el (cvs-edit-done): Committing a file now looks more
+ like diffing a file. The window handling is better.
+ * pcl-cvs.el (cvs-use-temp-buffer): The &optional switch is no
+ longer needed.
+
+Mon Mar 23 00:20:33 1992 Per Cederqvist (ceder@robin)
+
+ * Release 0.97.
+
+ * pcl-cvs.el (default-directory): Make sure it always ends in a
+ slash. fileinfo->dir does NOT end in a slash, and I had forgotten
+ to call file-name-as-directory in various places.
+
+ * pcl-cvs.el (cvs-diff-backup-extractor): Signal an error if a
+ fileinfo without backup file is given.
+
+ * pcl-cvs.el (cvs-mode): Added documentation.
+
+ * pcl-cvs.el (cvs-execute-list): Fix the order of files in the
+ same directory.
+
+ * pcl-cvs.el (cvs-log-flags, cvs-status-flags): New variables.
+ * pcl-cvs.el (cvs-log, cvs-status): Use them.
+ * pcl-cvs.texinfo (Customization): Document them.
+
+ * pcl-cvs.el (cvs-diff-backup): Filter non-backup-diffable files
+ at an earlier stage, like cvs-commit does.
+
+ * pcl-cvs.el (cvs-diff-flags): New variable.
+ * pcl-cvs.el (cvs-diff-backup): Use it.
+ * pcl-cvs.texinfo (Customization): Document it.
+
+ * pcl-cvs.el (cvs-execute-single-file-list): Remove &rest before
+ last argument. No callers needed updating.
+
+ * pcl-cvs.el (cvs-execute-list): Remove the &rest before the last
+ argument (constant-args). Update all callers of cvs-execute-list
+ to use the new calling convention.
+ * pcl-cvs.el (cvs-cvs-diff-flags): Now a list of strings instead
+ of a string.
+ * pcl-cvs.texinfo (Customization): Document the change to
+ cvs-cvs-diff-flags.
+
+ * Release 0.96.
+
+ * pcl-cvs.el (cvs-cvs-diff-flags): New variable.
+ * pcl-cvs.el (cvs-diff-cvs): Use it.
+ * pcl-cvs.texinfo (Customization, Viewing differences): Document it.
+
+ * pcl-cvs.el (cvs-use-temp-buffe): Don't switch to the temporary
+ buffer. Use display-buffer and set-buffer instead. This way
+ cvs-log, cvs-status, cvs-diff-cvs and friends don't select the
+ temporary buffer. The cursor will remain in the *cvs* buffer.
+
+Sun Mar 22 21:50:18 1992 Per Cederqvist (ceder@robin)
+
+ * pcl-cvs.el (cvs-find-file, cvs-find-file-other-window): Don't
+ prompt when reading in a directory in dired.
+
+ * Makefile (pcl-cvs-$(VER)): Include pcl-cvs-startup.el in the
+ distribution.
+
+ * dist-makefile (pcl-cvs.dvi): Don't fail even if texindex does
+ not exist.
+
+ * pcl-cvs.texinfo (@setchapternewpage): Changed from 'off' to 'on'.
+ * pcl-cvs.texinfo (Variable index): Joined into function index.
+ * pcl-cvs.texinfo (Key index): add a description about the key.
+ * pcl-cvs.texinfo: Many other small changes.
+
+Wed Mar 18 01:58:38 1992 Per Cederqvist (ceder@leopold)
+
+ * Use GNU General Public License version 2.
+
diff --git a/contrib/cvs/tools/pcl-cvs/INSTALL b/contrib/cvs/tools/pcl-cvs/INSTALL
new file mode 100644
index 0000000..56ff80d
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/INSTALL
@@ -0,0 +1,94 @@
+This text is copied from the TeXinfo manual for pcl-cvs.
+
+Installation of the pcl-cvs program
+===================================
+
+ 1. Possibly edit the file `Makefile' to reflect the situation at your
+ site. We say "possibly" because the version of pcl-cvs included
+ with CVS uses a configuration mechanism integrated with the overall
+ mechanisms used by the CVS build and install procedures. Thus the
+ file `Makefile' will be generated automatically from the file
+ `Makefile.in', and it should not be necessary to edit it further.
+
+ If you do have to edit the `Makefile', the only things you have to
+ change is the definition of `lispdir' and `infodir'. The elisp
+ files will be copied to `lispdir', and the info file(s) to
+ `infodir'.
+
+ 2. Configure pcl-cvs.el
+
+ There are a couple of pathnames that you have to check to make
+ sure that they match your system. They appear early in the file
+ `pcl-cvs.el'.
+
+ *NOTE:* If your system is running emacs 18.57 or earlier you MUST
+ uncomment the line that says:
+ (setq delete-exited-processes nil)
+
+ Setting `delete-exited-processes' to `nil' works around a bug in
+ emacs that causes it to dump core. The bug was fixed in emacs
+ 18.58.
+
+ 3. Release 1.05 and later of pcl-cvs requires parts of the Elib
+ library, version 1.0 or later. Elib is available via anonymous
+ ftp from prep.ai.mit.edu in `pub/gnu/elib-1.0.tar.gz', and from a
+ lot of other sites that mirror prep. Get Elib, and install it,
+ before proceeding.
+
+ *NOTE:* The version of pcl-cvs included with CVS includes a copy
+ of Elib in the sub-directory `elib' under the `contrib/elib'
+ directory.
+
+ 4. Type `make install' in the source directory. This will
+ byte-compile all `.el' files and copy the `*.elc' files into the
+ directory you specified in step 1.
+
+ If you want to install the `*.el' files too, you can type `make
+ install-el' to do so.
+
+ If you only want to create the compiled elisp files, but don't
+ want to install them, you can type `make' without parameters.
+
+ 5. Edit the file `default.el' in your emacs lisp directory (usually
+ `/usr/gnu/lib/emacs/site-lisp' or something similar) and enter the
+ contents of the file `pcl-cvs-startup.el' into it. It contains a
+ couple of `auto-load's that facilitates the use of pcl-cvs.
+
+
+Installation of the on-line manual.
+===================================
+
+ 1. Create the info file(s) `pcl-cvs.info*' from `pcl-cvs.texinfo' by
+ typing `make info'. If you don't have the program `makeinfo' you
+ can get it by anonymous ftp from e.g. `prep.ai.mit.edu' as
+ `pub/gnu/texinfo-3.7.tar.gz' (there might be a newer version there
+ when you read this).
+
+ 2. Install the info file(s) `pcl-cvs.info*' into your standard `info'
+ directory. You should be able to do this by typing `make
+ install-info'.
+
+ 3. Edit the file `dir' in the `info' directory and enter one line to
+ contain a pointer to the info file(s) `pcl-cvs.info*'. The line
+ can, for instance, look like this:
+
+ * Pcl-cvs: (pcl-cvs). An Emacs front-end to CVS.
+
+How to make typeset documentation from pcl-cvs.texinfo
+======================================================
+
+ If you have TeX installed at your site, you can make a typeset manual
+from `pcl-cvs.texinfo'.
+
+ 1. Run TeX by typing ``make pcl-cvs.dvi''. You will not get the
+ indices unless you have the `texindex' program.
+
+ 2. Convert the resulting device independent file `pcl-cvs.dvi' to a
+ form which your printer can output and print it. If you have a
+ postscript printer there is a program, `dvi2ps', which does. There
+ is also a program which comes together with TeX, `dvips', which
+ you can use.
+
+
+--
+#ident "@(#)cvs/contrib/pcl-cvs:$Name: $Id$"
diff --git a/contrib/cvs/tools/pcl-cvs/Makefile.in b/contrib/cvs/tools/pcl-cvs/Makefile.in
new file mode 100644
index 0000000..ca881d0
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/Makefile.in
@@ -0,0 +1,238 @@
+# Makefile for pcl-cvs, an Emacs interface to CVS.
+# NOTE: pcl-cvs requires Elib to run. See ../../contrib/elib/.
+
+#
+#ident "@(#)original: dist-makefile,v 1.19 1993/05/31 22:43:45 ceder Exp "
+#
+#ident "@(#)elisp/pcl-cvs:$Name: $:$Id: Makefile.in,v 1.3 1996/04/15 06:33:20 kfogel Exp $"
+#
+# Makefile for pcl-cvs release 1.05-CVS-$Name: $.
+# Copyright (C) 1992, 1993 Per Cederqvist
+#
+# 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 2 of the License, 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.
+
+SHELL = /bin/sh
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+# Where to put the system-wide supplementary files
+libdir = $(prefix)/lib
+
+# Where to put the Info files
+infodir = $(prefix)/info
+
+# Where to put the manual pages.
+mandir = $(prefix)/man
+
+# Used to batch-byte-compile files.
+EMACS = emacs
+# compile with noninteractive environment
+BATCHFLAGS = -batch
+
+# This is the directory in which the ELCFILES will be installed.
+lispdir = $(libdir)/emacs/site-lisp
+
+#### End of system configuration section. ####
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+# Just in case...
+SHELL = /bin/sh
+@SET_MAKE@
+
+DISTFILES = \
+ .cvsignore ChangeLog INSTALL Makefile.in NEWS README \
+ ${ELFILES} \
+ pcl-cvs.texinfo texinfo.tex
+
+
+# OBJDIR_DISTFILES used to include the byte-compiled elisp files, but
+# this seems wrong because the person building the dist cannot have
+# made the appropriate site-specific modifications to pcl-cvs.el.
+# Therefore, I've taken the .elc files out of OBJDIR_DISTFILES for
+# now, pending the Right Solution to this problem (which probably
+# involves moving the site-specific modification section of pcl-cvs.el
+# to a separate file and having autoconf generate as much of the file
+# as possible). -Karl
+#
+# OBJDIR_DISTFILES = $(ELCFILES) pcl-cvs.aux pcl-cvs.ps
+OBJDIR_DISTFILES = pcl-cvs.aux pcl-cvs.ps
+
+
+# files that contain key macro definitions. almost everything
+# depends on them because the byte-compiler inlines macro
+# expansions. everything also depends on the byte compiler
+# options file since this might do odd things like turn off
+# certain compiler optimizations.
+CORE =
+
+ELFILES = pcl-cvs.el pcl-cvs-lucid.el pcl-cvs-startup.el
+ELCFILES = pcl-cvs.elc pcl-cvs-lucid.elc
+INFOFILES = pcl-cvs.info*
+TEXTMPS = pcl-cvs.aux pcl-cvs.log pcl-cvs.toc pcl-cvs.dvi pcl-cvs.cp \
+ pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky pcl-cvs.pg \
+ pcl-cvs.cps pcl-cvs.fns pcl-cvs.kys pcl-cvs.pgs pcl-cvs.tps \
+ pcl-cvs.vrs
+
+# Use cp if you don't have install.
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+MAKEINFO = makeinfo
+
+SET_TEXINPUTS = TEXINPUTS=.:$(srcdir):$$TEXINPUTS
+
+# Don Knuth's TeX formatter
+TEX = tex
+
+# auxiliary program for sorting Texinfo indices
+TEXINDEX = texindex
+
+DVIPS = dvips
+DVIPSFLAGS =
+
+# CYGNUS LOCAL: install does not depend on info
+all: $(ELCFILES) # info
+.PHONY: all
+
+.SUFFIXES: .el .elc
+# We copy the .el file to the build dir--is there a cleaner way to get
+# emacs to compile the .el file from srcdir and put the .elc in the build dir?
+# (that is also why we have separate rules for pcl-cvs.elc and
+# pcl-cvs-lucid.elc rather than just using a .el.elc rule).
+pcl-cvs.elc: pcl-cvs.el
+ @echo "You can probably ignore free variable and unknown function warnings..."
+ if test -f pcl-cvs.el; then \
+ : OK, we are building in srcdir ; \
+ else \
+ ln $(srcdir)/pcl-cvs.el . ; \
+ fi
+ $(EMACS) $(BATCHFLAGS) -f batch-byte-compile pcl-cvs.el
+pcl-cvs-lucid.elc: pcl-cvs-lucid.el
+ @echo "You can probably ignore free variable and unknown function warnings..."
+ if test -f pcl-cvs-lucid.el; then \
+ : OK, we are building in srcdir ; \
+ else \
+ ln $(srcdir)/pcl-cvs-lucid.el . ; \
+ fi
+ $(EMACS) $(BATCHFLAGS) -f batch-byte-compile pcl-cvs-lucid.el
+
+check installcheck:
+ @echo "$@ not supported in this makefile..."
+.PHONY: check installcheck
+
+# CYGNUS LOCAL: install does not depend on install-info
+install: install-elc # install-info install-el
+
+install-el: $(ELFILES)
+ for i in $(ELFILES) ; do \
+ $(INSTALL_DATA) $$i $(lispdir)/$$i ; \
+ done
+
+install-elc: $(ELCFILES)
+ for i in $(ELCFILES) ; do \
+ $(INSTALL_DATA) $$i $(lispdir)/$$i ; \
+ done
+
+install-info: info
+ test -f pcl-cvs.info || cd $(srcdir); \
+ for i in *.info* ; do \
+ $(INSTALL_DATA) $$i $(infodir)/$$i ; \
+ done
+
+.PHONY: install install-el install-elc install-info
+
+# mkinstalldirs isn't supported for CVS yet....
+installdirs: $(top_srcdir)/mkinstalldirs
+ $(SHELL) $(top_srcdir)/mkinstalldirs $(lispdir) $(infodir)
+.PHONY: installdirs
+
+uninstall:
+ @echo "$@ not yet supported in this makefile..."
+.PHONY: uninstall
+
+info: pcl-cvs.info
+.PHONY: info
+
+pcl-cvs.info: pcl-cvs.texinfo
+ $(MAKEINFO) ${srcdir}/pcl-cvs.texinfo -o pcl-cvs.info
+
+dvi: pcl-cvs.dvi
+.PHONY: dvi
+
+# this mess seems to be necessary to make the index right...
+pcl-cvs.dvi pcl-cvs.aux: pcl-cvs.texinfo
+ $(SET_TEXINPUTS) $(TEX) $(srcdir)/pcl-cvs.texinfo
+ $(SET_TEXINPUTS) $(TEX) $(srcdir)/pcl-cvs.texinfo
+ -$(TEXINDEX) pcl-cvs.cp pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky \
+ pcl-cvs.pg
+ $(SET_TEXINPUTS) $(TEX) $(srcdir)/pcl-cvs.texinfo
+
+pcl-cvs.ps: pcl-cvs.dvi
+ $(DVIPS) $(DVIPSFLAGS) pcl-cvs.dvi -o pcl-cvs.ps
+
+mostlyclean clean:
+ rm -f *~ core $(ELCFILES) $(INFOFILES) $(TEXTMPS)
+.PHONY: mostlyclean clean
+
+distclean: clean
+ rm -f Makefile tags TAGS
+.PHONY: distclean
+
+realclean maintainer-clean: distclean
+ rm -f pcl-cvs.info* pcl-cvs.ps
+.PHONY: realclean maintainer-clean
+
+# you can't use ctags for lisp...
+tags TAGS:
+ etags *.el
+.PHONY: tags
+
+ls:
+ @echo $(DISTFILES)
+.PHONY: ls
+
+dist-dir: ${OBJDIR_DISTFILES} ${DISTFILES} pcl-cvs.info
+ mkdir ${DISTDIR}
+ for i in ${DISTFILES}; do \
+ ln $(srcdir)/$${i} ${DISTDIR}; \
+ done
+ ln ${OBJDIR_DISTFILES} ${DISTDIR}
+ if [ -f pcl-cvs.info-1 ]; \
+ then ln -f pcl-cvs.info-* ${DISTDIR}; \
+ else : Pacify Ultrix sh; \
+ fi
+.PHONY: dist-dir
+
+subdir = tools/pcl-cvs
+Makefile: ../../config.status Makefile.in
+ cd ../.. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
+
+# CYGNUS LOCAL: don't depend on auto-re-config
+#../config.status: ../configure
+# cd .. ; $(SHELL) config.status --recheck
+
+# CYGNUS LOCAL: don't depend on auto-re-config
+#../configure: ../configure.in
+# cd $(top_srcdir) ; autoconf
diff --git a/contrib/cvs/tools/pcl-cvs/NEWS b/contrib/cvs/tools/pcl-cvs/NEWS
new file mode 100644
index 0000000..48b0b66
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/NEWS
@@ -0,0 +1,149 @@
+This is the NEWS file for pcl-cvs, an Emacs elisp front-end to CVS.
+
+User-visible changes in the un-official CVS release of pcl-cvs
+from the official 1.05 release to 1.05-CVS-$Name: $:
+
+* Support for using ChangeLog files, including hooks to automatically
+ guess CVS log entries from ChangeLog contents.
+
+* Support for client/server CVS (versions 1.5 through 1.7 and newer).
+
+* New commands for tagging files and directory trees (still needs to
+ be made to run in the background).
+
+* Better support for recognizing and handling unknown directories.
+
+* An attempt at new ediff and emerge interfaces (still needs work!),
+ including attempts to make vendor-branch merging work.
+
+* In a possibly misguided attempt to make it easier to see the effects
+ of changes that affect several files, diff output is now stored in a
+ uniqe buffer for each file.
+
+* Some commands now have default flags (cvs-*-flags).
+
+* Proper quoting of command line arguments displayed in *cvs-tmp*.
+
+* More hacking with getting CVSROOT right, though probably all
+ pointless, since CVS should do the right thing all the time.
+
+* Elib is back, at least in the CVS distribution.
+
+* Lots of minor bug fixes, tweaks, cleanup, re-indentation, etc.
+
+* Some minor tweaks, fixes, re-indentation, etc., in the
+ documentation.
+
+
+User-visible changes in pcl-cvs from 1.04 to 1.05:
+
+* Elib is no longer distributed with pcl-cvs. You must get Elib
+ separately, for instance from ftp.lysator.liu.se in pub/emacs.
+
+* The Lucid Emacs support works again.
+
+* A new function, cvs-change-cvsroot, can be used to interactively
+ switch between CVS repositories.
+
+* The mode line in the *cvs* buffer now indicates when a "cvs update"
+ is running.
+
+* The .cvsignore file is automatically sorted alphabetically (to
+ reduce the risk of conflicts when two people add different files
+ simultaneously). This behaviour can be turned off with
+ cvs-sort-ignore-file.
+
+* A trailing newline is always added in commit log messages. This
+ behaviour can be turned off with
+ cvs-commit-buffer-require-final-newline.
+
+* This version of pcl-cvs should work together with RCVS. I have not
+ tested this myself, though.
+
+* Plus some bug fixes. (Note that the version of cookie.el that is
+ distributed with pcl-cvs 1.04 contains errors that affects pcl-cvs.
+ You should get Elib 0.07).
+
+
+User-visible changes in pcl-cvs from 1.03 to 1.04:
+
+* Support for Emerge. Hitting "e" on a file that is Modified, Merged
+ or in Conflict will start Emerge, an interactive file merger written
+ in Emacs Lisp. This requires Emerge version 4. Emerge is not
+ included in this package. If you can't find it anywhere else, you
+ can get in from ftp.lysator.liu.se in pub/emacs. This package makes
+ it a lot easier to resolve conflicts.
+
+* Emacs will now automatically revert your buffers when the CVS
+ commands pcl-cvs issues causes the file to change. This automatic
+ revert never occurs if the buffer contents did not agree with the
+ file prior to the command.
+
+* If you are running Lucid GNU Emacs, you will get some fonts and
+ mouse support. This was contributed from people at Lucid.
+
+* The variable cvs-cvsroot can be used to select the location if the
+ repository. You no longer need to exit Emacs, setenv CVSROOT, and
+ start a new Emacs if you work with multiple repositories.
+
+* The "q" key can be used to hide the *cvs* buffer.
+
+* The name of the commands in the *cvs* have changed. If it was called
+ cvs-foo, it will now be called cvs-mode-foo. See the ChangeLog
+ entry from Tue Aug 4 03:02:25 1992 for a complete list of changes.
+
+* The variable cvs-cvs-diff-flags is no longer used. Instead,
+ cvs-diff-flags is always used.
+
+* Plus a lot of bug fixes.
+
+
+User-visible changes in pcl-cvs from 1.02 to 1.03:
+
+* Output from CVS to stdout and stderr is separated and parsed
+ independently. In that way pcl-cvs should work regardless of
+ whether stdout is buffered or line-buffered. Pcl-cvs should now
+ work with CVS 1.3 without modifications on hosts such as
+ DECstations.
+
+* Pcl-cvs now fully supports RCS version 5.6 as well as 5.5.
+
+* New functions:
+
+ + cvs-undo-local-changes ("U") - Undo all your modifications
+ to a file and get the newest
+ version from the repository.
+ + cvs-update-other-window - Similar to cvs-update.
+ + cvs-byte-compile-files - Byte compile the selected files.
+
+* cvs-update now displays the *cvs* buffer, which initially contains a
+ small message ("Running `cvs update' in /foo/bar/gazonk/...") until
+ the update is ready. The *cvs* buffer no longer pops up when the
+ update is ready. It often failed to pop up, due to race conditions
+ that are very hard to solve (and I doubt that they were at all
+ solvable).
+
+* cvs-unmark-all-files is moved from "U" to "ESC DEL" to be
+ "compatible" with dired.
+
+* cvs-diff ("d") and cvs-diff-backup ("b") can be configured to work
+ on only the file the cursor is positioned on, and ignore any marked
+ files. A prefix argument toggles this.
+
+* Only one `cvs update' can be run at a time. (It was previously
+ possible to start more than one simultaneously, but pcl-cvs could
+ not really handle more than one.)
+
+* Some rudimentary support for programs that CVS runs at update (due
+ to the -u switch in the modules file).
+
+* Pcl-cvs now automatically generates a bug report if it can't parse
+ the output from CVS.
+
+* The *cvs* buffer is read-only.
+
+* Pcl-cvs now creates temporary files in $TMPDIR if that environment
+ variable is set (otherwise it uses /tmp).
+
+---End of file NEWS---
+#ident "@(#)cvs/contrib/pcl-cvs:$Name: $:$Id: NEWS,v 1.1 1996/04/14 15:17:54 kfogel Exp $"
diff --git a/contrib/cvs/tools/pcl-cvs/README b/contrib/cvs/tools/pcl-cvs/README
new file mode 100644
index 0000000..9574c14
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/README
@@ -0,0 +1,25 @@
+This is the readme file for pcl-cvs, release 1.05-CVS-$Name: $.
+
+Pcl-cvs is a front-end to CVS versions 1.5 through 1.7. It integrates
+the most frequently used CVS commands into an emacs interface.
+
+There may be some configuration that needs to be done in pcl-cvs.el to
+get it to work. See the instructions in the file INSTALL.
+
+Full documentation is in Texinfo format in the file pcl-cvs.texinfo. To
+browse this document online, or in the emacs info mode, you will need to
+process this file with the makeinfo program, which can also be found on
+prep.ai.mit.edu in pub/gnu.
+
+If you have been using a previous version of pcl-cvs (for instance the
+official 1.05 release, or any previous releases) you should read through
+the file NEWS to see what has changed.
+
+This release has been tested under, Emacs 19.28 and Emacs 19.30.
+
+Per Cederqvist
+(updated by Jim Blandy, Greg A. Woods, Karl Fogel)
+
+--
+#OrigId "@(#) Id: README,v 1.14 1993/05/31 22:43:36 ceder Exp "
+#ident "@(#)cvs/contrib/pcl-cvs:$Name: $:$Id: README,v 1.1 1996/04/14 15:17:55 kfogel Exp $"
diff --git a/contrib/cvs/tools/pcl-cvs/pcl-cvs-lucid.el b/contrib/cvs/tools/pcl-cvs/pcl-cvs-lucid.el
new file mode 100644
index 0000000..8695f67
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/pcl-cvs-lucid.el
@@ -0,0 +1,134 @@
+;;; Mouse and font support for PCL-CVS 1.3 running in Lucid GNU Emacs
+;; @(#) Id: pcl-cvs-lucid.el,v 1.2 1993/05/31 19:37:34 ceder Exp
+;; Copyright (C) 1992-1993 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;; This simply adds a menu of the common CVS commands to the menubar and to
+;; the right mouse button. Clicking right moves point, and then pops up a
+;; menu from which commands can be executed.
+;;
+;; This could stand to be a lot more clever: for example, the "Commit Changes"
+;; command should only be active on files for which there is something to
+;; commit. Also, some indication of which files the command applies to
+;; (especially in the presence of multiple marked files) would be nice.
+;;
+;; Middle-click runs find-file.
+
+
+;(require 'pcl-cvs)
+(load "pcl-cvs.el")
+
+(defvar cvs-menu
+ '("CVS"
+ ["Find File" cvs-mode-find-file t]
+ ["Find File Other Window" cvs-mode-find-file-other-window t]
+ ["Interactively Merge (emerge)" cvs-mode-emerge t]
+ ["Diff against Repository" cvs-mode-diff-cvs t]
+ ["Diff against Backup Version" cvs-mode-diff-backup t]
+ "----"
+ ["Commit Changes to Repository" cvs-mode-commit t]
+ ["Revert File from Repository" cvs-mode-undo-local-changes t]
+ ["Add File to Repository" cvs-mode-add t]
+ ["Remove File from Repository" cvs-mode-remove-file t]
+ ["Ignore File" cvs-mode-ignore t]
+ ["Hide File" cvs-mode-acknowledge t]
+ ["Hide Handled Files" cvs-mode-remove-handled t]
+ "----"
+ ["Add ChangeLog Entry" cvs-mode-add-change-log-entry-other-window t]
+ ["Show CVS Log" cvs-mode-log t]
+ ["Show CVS Status" cvs-mode-status t]
+ "----"
+ ["Mark File" cvs-mode-mark t]
+ ["Unmark File" cvs-mode-unmark t]
+ ["Mark All Files" cvs-mode-mark-all-files t]
+ ["Unmark All Files" cvs-mode-unmark-all-files t]
+ "----"
+ ["Quit" bury-buffer t]
+ ))
+
+(defun cvs-menu (e)
+ (interactive "e")
+ (mouse-set-point e)
+ (beginning-of-line)
+ (or (looking-at "^[* ] ") (error "No CVS file line here"))
+ (popup-menu cvs-menu))
+
+(defun cvs-mouse-find-file (e)
+ (interactive "e")
+ (mouse-set-point e)
+ (beginning-of-line)
+ (or (looking-at "^[* ] ") (error "No CVS file line here"))
+ (cvs-mode-find-file (point)))
+
+(define-key cvs-mode-map 'button3 'cvs-menu)
+(define-key cvs-mode-map 'button2 'cvs-mouse-find-file)
+
+(make-face 'cvs-header-face)
+(make-face 'cvs-filename-face)
+(make-face 'cvs-status-face)
+
+(or (face-differs-from-default-p 'cvs-header-face)
+ (copy-face 'italic 'cvs-header-face))
+
+(or (face-differs-from-default-p 'cvs-filename-face)
+ (copy-face 'bold 'cvs-filename-face))
+
+(or (face-differs-from-default-p 'cvs-status-face)
+ (copy-face 'bold-italic 'cvs-status-face))
+
+
+(defun pcl-mode-motion-highlight-line (event)
+ (if (save-excursion
+ (let* ((window (event-window event))
+ (buffer (and window (window-buffer window)))
+ (point (and buffer (event-point event))))
+ (and point
+ (progn
+ (set-buffer buffer)
+ (goto-char point)
+ (beginning-of-line)
+ (looking-at "^[* ] ")))))
+ (mode-motion-highlight-line event)))
+
+(defconst pcl-cvs-font-lock-keywords
+ '(("^In directory \\(.+\\)$" 1 cvs-header-face)
+ ("^[* ] \\w+ +\\(ci\\)" 1 cvs-status-face)
+ ("^[* ] \\(Conflict\\|Merged\\)" 1 cvs-status-face)
+ ("^[* ] \\w+ +\\(ci +\\)?\\(.+\\)$" 2 cvs-filename-face)
+ )
+ "Patterns to highlight in the *cvs* buffer.")
+
+(defun pcl-cvs-fontify ()
+ ;;
+ ;; set up line highlighting
+ (require 'mode-motion)
+ (setq mode-motion-hook 'pcl-mode-motion-highlight-line)
+ ;;
+ ;; set up menubar
+ (if (and current-menubar (not (assoc "CVS" current-menubar)))
+ (progn
+ (set-buffer-menubar (copy-sequence current-menubar))
+ (add-menu nil "CVS" (cdr cvs-menu))))
+ ;;
+ ;; fontify mousable lines
+ (set (make-local-variable 'font-lock-keywords) pcl-cvs-font-lock-keywords)
+ (font-lock-mode 1)
+ )
+
+(add-hook 'cvs-mode-hook 'pcl-cvs-fontify)
diff --git a/contrib/cvs/tools/pcl-cvs/pcl-cvs-startup.el b/contrib/cvs/tools/pcl-cvs/pcl-cvs-startup.el
new file mode 100644
index 0000000..9db7a5f
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/pcl-cvs-startup.el
@@ -0,0 +1,17 @@
+;;;#ident "@(#)OrigId: pcl-cvs-startup.el,v 1.4 1993/05/31 18:40:33 ceder Exp "
+;;;
+;;;#ident "@(#)cvs/contrib/pcl-cvs:$Name: $:$Id: pcl-cvs-startup.el,v 1.1 1996/04/14 15:17:59 kfogel Exp $"
+;;;
+(autoload 'cvs-update "pcl-cvs"
+ "Run a 'cvs update' in the current working directory. Feed the
+output to a *cvs* buffer and run cvs-mode on it.
+If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run."
+ t)
+
+(autoload 'cvs-update-other-window "pcl-cvs"
+ "Run a 'cvs update' in the current working directory. Feed the
+output to a *cvs* buffer, display it in the other window, and run
+cvs-mode on it.
+
+If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run."
+ t)
diff --git a/contrib/cvs/tools/pcl-cvs/pcl-cvs.el b/contrib/cvs/tools/pcl-cvs/pcl-cvs.el
new file mode 100644
index 0000000..269b02f
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/pcl-cvs.el
@@ -0,0 +1,3450 @@
+;;;
+;;;#ident "@(#)OrigId: pcl-cvs.el,v 1.93 1993/05/31 22:44:00 ceder Exp "
+;;;
+;;;#ident "@(#)cvs/contrib/pcl-cvs:$Name: $:$Id: pcl-cvs.el,v 1.2 1996/04/14 20:09:45 kfogel Exp $"
+;;;
+;;; pcl-cvs.el -- A Front-end to CVS 1.3 or later.
+;;; Release 1.05-CVS-$Name: $.
+;;; Copyright (C) 1991, 1992, 1993 Per Cederqvist
+
+;;; 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 2 of the License, 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.
+
+;;; See below for installation instructions.
+
+;;; This package requires ELIB-1.0 to run. Elib is included in the
+;;; CVS distribution in the contrib/elib/ subdirectory, but you can
+;;; also download it at the following URL:
+;;;
+;;; ftp://ftp.lysator.liu.se/pub/emacs/elib-1.0.tar.gz
+;;;
+
+;;; There is an TeXinfo file that describes this package. You should read it
+;;; to get the most from this package.
+
+;;; Mail questions and bug reports regarding this version (as included in
+;;; CVS-1.7 or newer) to the pcl-cvs support team at <pcl-cvs@cyclic.com>.
+
+;;; Don't try to use this with CVS 1.2 or earlier. It won't work. Get CVS 1.7
+;;; or newer. Use the version of RCS best suited for the version of CVS you're
+;;; using.
+
+(require 'cookie) ; from ELIB-1.0
+(require 'add-log) ; for all the ChangeLog goodies
+
+;;; -------------------------------------------------------
+;;; START OF THINGS TO CHECK WHEN INSTALLING
+
+;; also use $GNU here, since may folks might install CVS as a GNU package
+;;
+(defvar local-path (cond
+ ((getenv "LOCAL")
+ (getenv "LOCAL"))
+ ((getenv "GNU")
+ (getenv "GNU"))
+ (t
+ "/usr/local"))
+ "*Path prefix for most locally installed things.")
+
+;; this isn't likely to be right all the time....
+;;
+(defvar local-gnu-path (cond
+ ((getenv "GNU")
+ (getenv "GNU"))
+ (t
+ "/usr/local")) ; or "/usr/gnu"?
+ "*Path prefix for locally installed GNU software.")
+
+(defvar cvs-program (concat local-path "/bin/cvs")
+ "*Full path to the cvs executable.")
+
+;; SunOS-4.1.1_U1 has "diff.c 1.12 88/08/04 SMI; from UCB 4.6 86/04/03"
+;;
+(defvar cvs-diff-program (concat local-gnu-path "/bin/diff")
+ "*Full path to the best diff program you've got.
+NOTE: there are some nasty bugs in the context diff variants of some vendor
+versions, such as the one in SunOS-4.1.1_U1")
+
+(defvar cvs-rmdir-program "/bin/rmdir"
+ "*Full path to the rmdir program. Typically /bin/rmdir.")
+
+(defvar cvs-shell "/bin/sh"
+ "*Full path to a shell that can do redirection on stdout.")
+
+;;; Options to control various features:
+
+(defvar cvs-changelog-full-paragraphs t
+ "If non-nil, include full ChangeLog paragraphs in the CVS log.
+This may be set in the ``local variables'' section of a ChangeLog, to
+indicate the policy for that ChangeLog.
+
+A ChangeLog paragraph is a bunch of log text containing no blank lines;
+a paragraph usually describes a set of changes with a single purpose,
+but perhaps spanning several functions in several files. Changes in
+different paragraphs are unrelated.
+
+You could argue that the CVS log entry for a file should contain the
+full ChangeLog paragraph mentioning the change to the file, even though
+it may mention other files, because that gives you the full context you
+need to understand the change. This is the behaviour you get when this
+variable is set to t.
+
+On the other hand, you could argue that the CVS log entry for a change
+should contain only the text for the changes which occurred in that
+file, because the CVS log is per-file. This is the behaviour you get
+when this variable is set to nil.")
+
+(defvar cvs-cvsroot-required nil
+ "*Specifies whether CVS needs to be told where the repository is.
+
+In CVS 1.3, if your CVSROOT environment variable is not set, and you
+do not set the `cvs-cvsroot' lisp variable, CVS will have no idea
+where to find the repository, and refuse to run. CVS 1.4 and later
+store the repository path with the working directories, so most
+operations don't need to be told where the repository is.
+
+If you work with multiple repositories with CVS 1.4, it's probably
+advisable to leave your CVSROOT environment variable unset, set this
+variable to nil, and let CVS figure out where the repository is for
+itself.")
+
+(defvar cvs-cvsroot nil
+ "*Specifies where the (current) cvs master repository is.
+Overrides the $CVSROOT variable by sending \" -d dir\" to all cvs commands.
+This switch is useful if you have multiple CVS repositories, and are not using
+a modern version of CVS that stores the current repository in CVS/Root.")
+
+;; Uncomment the following line if you are running on 18.57 or earlier.
+;(setq delete-exited-processes nil)
+;; Emacs version 18.57 and earlier is likely to crash if
+;; delete-exited-processes is t, since the sentinel uses lots of
+;; memory, and 18.57 forgets to GCPROT a variable if
+;; delete-exited-processes is t.
+
+;;; END OF THINGS TO CHECK WHEN INSTALLING
+;;; --------------------------------------------------------
+
+(defconst pcl-cvs-version "1.05-CVS-$Name: $"
+ "A string denoting the current release version of pcl-cvs.")
+
+;; You are NOT allowed to disable this message by default. However, you
+;; are encouraged to inform your users that by adding
+;; (setq cvs-inhibit-copyright-message t)
+;; to their .emacs they can get rid of it. Just don't add that line
+;; to your default.el!
+(defvar cvs-inhibit-copyright-message nil
+ "*Non-nil means don't display a Copyright message in the ``*cvs*'' buffer.")
+
+(defconst cvs-startup-message
+ (if cvs-inhibit-copyright-message
+ "PCL-CVS release 1.05-CVS-$Name: $"
+ "PCL-CVS release 1.05 from CVS release $Name: $.
+Copyright (C) 1992, 1993 Per Cederqvist
+Pcl-cvs comes with absolutely no warranty; for details consult the manual.
+This is free software, and you are welcome to redistribute it under certain
+conditions; again, consult the TeXinfo manual for details.")
+ "*Startup message for CVS.")
+
+(defconst pcl-cvs-bugs-address "pcl-cvs-auto-bugs@cyclic.com"
+ "The destination address used for the default bug report form.")
+
+(defvar cvs-stdout-file nil
+ "Name of the file that holds the output that CVS sends to stdout.
+This variable is buffer local.")
+
+(defvar cvs-lock-file nil
+ "Full path to a lock file that CVS is waiting for (or was waiting for).")
+
+(defvar cvs-bakprefix ".#"
+ "The prefix that CVS prepends to files when rcsmerge'ing.")
+
+(defvar cvs-erase-input-buffer nil
+ "*Non-nil if input buffers should be cleared before asking for new info.")
+
+(defvar cvs-auto-remove-handled nil
+ "*Non-nil if cvs-mode-remove-handled should be called automatically.
+If this is set to any non-nil value, entries that do not need to be checked in
+will be removed from the *cvs* buffer after every cvs-mode-commit command.")
+
+(defvar cvs-auto-remove-handled-directories nil
+ "*Non-nil if cvs-mode-remove-handled and cvs-update should automatically
+remove empty directories.
+If this is set to any non-nil value, directories that do not contain any files
+to be checked in will be removed from the *cvs* buffer.")
+
+(defvar cvs-sort-ignore-file t
+ "*Non-nil if cvs-mode-ignore should sort the .cvsignore automatically.")
+
+(defvar cvs-auto-revert-after-commit t
+ "*Non-nil if committed buffers should be automatically reverted.")
+
+(defconst cvs-cursor-column 14
+ "Column to position cursor in in cvs-mode.
+Column 0 is left-most column.")
+
+(defvar cvs-mode-map nil
+ "Keymap for the cvs mode.")
+
+(defvar cvs-edit-mode-map nil
+ "Keymap for the cvs edit mode (used when editing cvs log messages).")
+
+(defvar cvs-buffer-name "*cvs*"
+ "Name of the cvs buffer.")
+
+(defvar cvs-commit-prompt-buffer "*cvs-commit-message*"
+ "Name of buffer in which the user is prompted for a log message when
+committing files.")
+
+(defvar cvs-commit-buffer-require-final-newline t
+ "*t says silently put a newline at the end of commit log messages.
+Non-nil but not t says ask user whether to add a newline in each such case.
+nil means don't add newlines.")
+
+(defvar cvs-temp-buffer-name "*cvs-tmp*"
+ "*Name of the cvs temporary buffer.
+Output from cvs is placed here by synchronous commands.")
+
+(defvar cvs-diff-ignore-marks nil
+ "*Non-nil if cvs-diff and cvs-mode-diff-backup should ignore any marked files.
+Normally they run diff on the files that are marked (with cvs-mode-mark),
+or the file under the cursor if no files are marked. If this variable
+is set to a non-nil value they will always run diff on the file on the
+current line.")
+
+;;; (setq cvs-status-flags '("-v"))
+(defvar cvs-status-flags '("-v")
+ "*List of flags to pass to ``cvs status''. Default is \"-v\".")
+
+;;; (setq cvs-log-flags nil)
+(defvar cvs-log-flags nil
+ "*List of flags to pass to ``cvs log''. Default is none.")
+
+;;; (setq cvs-tag-flags nil)
+(defvar cvs-tag-flags nil
+ "*List of extra flags to pass to ``cvs tag''. Default is none.")
+
+;;; (setq cvs-rtag-flags nil)
+(defvar cvs-rtag-flags nil
+ "*List of extra flags to pass to ``cvs rtag''. Default is none.")
+
+;;; (setq cvs-diff-flags '("-u"))
+(defvar cvs-diff-flags '("-u")
+ "*List of flags to use as flags to pass to ``diff'' and ``cvs diff''.
+Used by cvs-mode-diff-cvs and cvs-mode-diff-backup. Default is \"-u\".
+
+Set this to \"-u\" to get a Unidiff format, or \"-c\" to get context diffs.")
+
+;;; (setq cvs-update-optional-flags nil)
+(defvar cvs-update-optional-flags nil
+ "*List of strings to use as optional flags to pass to ``cvs update''. Used
+by cvs-do-update, called by cvs-update, cvs-update-other-window,
+cvs-mode-update-no-prompt, and cvs-examine. Default is none.
+
+For example set this to \"-j VENDOR_PREV_RELEASE -j VENDOR_TOP_RELEASE\" to
+perform an update after a new vendor release has been imported.
+
+To restrict the update to the current working directory, set this to \"-l\".")
+
+(defvar cvs-update-prog-output-skip-regexp "$"
+ "*A regexp that matches the end of the output from all cvs update programs.
+That is, output from any programs that are run by CVS (by the flag -u in the
+`modules' file - see cvs(5)) when `cvs update' is performed should terminate
+with a line that this regexp matches. It is enough that some part of the line
+is matched.
+
+The default (a single $) fits programs without output.")
+
+;;; --------------------------------------------------------
+;;; The variables below are used internally by pcl-cvs. You should
+;;; never change them.
+
+(defvar cvs-buffers-to-delete nil
+ "List of temporary buffers that should be discarded as soon as possible.
+Due to a bug in emacs 18.57 the sentinel can't discard them reliably.")
+
+(defvar cvs-update-running nil
+ "This is set to nil when no process is running, and to
+the process when a cvs update process is running.")
+
+(defvar cvs-cookie-handle nil
+ "Handle for the cookie structure that is displayed in the *cvs* buffer.")
+
+(defvar cvs-commit-list nil
+ "Used internally by pcl-cvs.")
+
+;;; The cvs data structure:
+;;;
+;;; When the `cvs update' is ready we parse the output. Every file
+;;; that is affected in some way is added as a cookie of fileinfo
+;;; (as defined below).
+;;;
+
+;;; cvs-fileinfo
+
+;;; Constructor:
+
+(defun cvs-create-fileinfo (type
+ dir
+ file-name
+ full-log)
+ "Create a fileinfo from all parameters.
+Arguments: TYPE DIR FILE-NAME FULL-LOG.
+A fileinfo is a vector with the following fields:
+
+[0] handled True if this file doesn't require further action.
+[1] marked t/nil
+[2] type One of
+ UPDATED - file copied from repository
+ PATCHED - file update with patch from repository
+ MODIFIED - modified by you, unchanged in
+ repository
+ ADDED - added by you, not yet committed
+ REMOVED - removed by you, not yet committed
+ CVS-REMOVED- removed, since file no longer exists
+ in the repository.
+ MERGED - successful merge
+ CONFLICT - conflict when merging (if pcl-cvs did it)
+ REM-CONFLICT-removed in repository, but altered
+ locally.
+ MOD-CONFLICT-removed locally, changed in repository.
+ REM-EXIST - removed locally, but still exists.
+ DIRCHANGE - A change of directory.
+ UNKNOWN - An unknown file.
+ UNKNOWN-DIR- An unknown directory.
+ MOVE-AWAY - A file that is in the way.
+ REPOS-MISSING- The directory has vanished from the
+ repository.
+ MESSAGE - This is a special fileinfo that is used
+ to display a text that should be in
+ full-log.
+[3] dir Directory the file resides in. Should not end with slash.
+[4] file-name The file name.
+[5] backup-file The name of a backup file created during a merge.
+ Only valid for MERGED and CONFLICT files.
+[6] base-revision The revision that the working file was based on.
+ Only valid for MERGED and CONFLICT files.
+[7] head-revision The revision that the newly merged changes came from
+ Only valid for MERGED and CONFLICT files.
+[8] backup-revision The revision of the cvs backup file (original working rev.)
+ Only valid for MERGED and CONFLICT files.
+[9] cvs-diff-buffer A buffer that contains a 'cvs diff file'.
+[10] vendor-diff-buffer A buffer that contains a 'diff base-file head-file'.
+[11] backup-diff-buffer A buffer that contains a 'diff file backup-file'.
+[12] full-log The output from cvs, unparsed.
+[13] mod-time Modification time of file used for *-diff-buffer."
+
+ (cons
+ 'CVS-FILEINFO
+ (vector nil nil type dir file-name nil nil nil nil nil nil nil full-log nil nil)))
+
+;;; Selectors:
+
+(defun cvs-fileinfo->handled (cvs-fileinfo)
+ "Get the `handled' field from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 0))
+
+(defun cvs-fileinfo->marked (cvs-fileinfo)
+ "Check if CVS-FILEINFO is marked."
+ (elt (cdr cvs-fileinfo) 1))
+
+(defun cvs-fileinfo->type (cvs-fileinfo)
+ "Get type from CVS-FILEINFO.
+Type is one of UPDATED, PATCHED, MODIFIED, ADDED, REMOVED, CVS-REMOVED, MERGED,
+CONFLICT, REM-CONFLICT, MOD-CONFLICT, REM-EXIST, DIRCHANGE, UNKNOWN,
+UNKNOWN-DIR, MOVE-AWAY, REPOS-MISSING or MESSAGE."
+ (elt (cdr cvs-fileinfo) 2))
+
+(defun cvs-fileinfo->dir (cvs-fileinfo)
+ "Get dir from CVS-FILEINFO.
+The directory name does not end with a slash."
+ (elt (cdr cvs-fileinfo) 3))
+
+(defun cvs-fileinfo->file-name (cvs-fileinfo)
+ "Get file-name from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 4))
+
+(defun cvs-fileinfo->backup-file (cvs-fileinfo)
+ "Get backup-file from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 5))
+
+(defun cvs-fileinfo->base-revision (cvs-fileinfo)
+ "Get the base revision from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 6))
+
+(defun cvs-fileinfo->head-revision (cvs-fileinfo)
+ "Get the head revision from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 7))
+
+(defun cvs-fileinfo->backup-revision (cvs-fileinfo)
+ "Get the backup revision from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 8))
+
+(defun cvs-fileinfo->cvs-diff-buffer (cvs-fileinfo)
+ "Get cvs-diff-buffer from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 9))
+
+(defun cvs-fileinfo->vendor-diff-buffer (cvs-fileinfo)
+ "Get backup-diff-buffer from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 10))
+
+(defun cvs-fileinfo->backup-diff-buffer (cvs-fileinfo)
+ "Get backup-diff-buffer from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 11))
+
+(defun cvs-fileinfo->full-log (cvs-fileinfo)
+ "Get full-log from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 12))
+
+(defun cvs-fileinfo->mod-time (cvs-fileinfo)
+ "Get mod-time from CVS-FILEINFO."
+ (elt (cdr cvs-fileinfo) 13))
+
+;;; Modifiers:
+
+(defun cvs-set-fileinfo->handled (cvs-fileinfo newval)
+ "Set handled in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 0 newval))
+
+(defun cvs-set-fileinfo->marked (cvs-fileinfo newval)
+ "Set marked in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 1 newval))
+
+(defun cvs-set-fileinfo->type (cvs-fileinfo newval)
+ "Set type in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 2 newval))
+
+(defun cvs-set-fileinfo->dir (cvs-fileinfo newval)
+ "Set dir in CVS-FILEINFO to NEWVAL.
+The directory should now end with a slash."
+ (aset (cdr cvs-fileinfo) 3 newval))
+
+(defun cvs-set-fileinfo->file-name (cvs-fileinfo newval)
+ "Set file-name in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 4 newval))
+
+(defun cvs-set-fileinfo->backup-file (cvs-fileinfo newval)
+ "Set backup-file in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 5 newval))
+
+(defun cvs-set-fileinfo->base-revision (cvs-fileinfo newval)
+ "Set base-revision in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 6 newval))
+
+(defun cvs-set-fileinfo->head-revision (cvs-fileinfo newval)
+ "Set head-revision in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 7 newval))
+
+(defun cvs-set-fileinfo->backup-revision (cvs-fileinfo newval)
+ "Set backup-revision in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 8 newval))
+
+(defun cvs-set-fileinfo->cvs-diff-buffer (cvs-fileinfo newval)
+ "Set cvs-diff-buffer in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 9 newval))
+
+(defun cvs-set-fileinfo->vendor-diff-buffer (cvs-fileinfo newval)
+ "Set vendor-diff-buffer in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 10 newval))
+
+(defun cvs-set-fileinfo->backup-diff-buffer (cvs-fileinfo newval)
+ "Set backup-diff-buffer in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 11 newval))
+
+(defun cvs-set-fileinfo->full-log (cvs-fileinfo newval)
+ "Set full-log in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 12 newval))
+
+(defun cvs-set-fileinfo->mod-time (cvs-fileinfo newval)
+ "Set full-log in CVS-FILEINFO to NEWVAL."
+ (aset (cdr cvs-fileinfo) 13 newval))
+
+;;; Predicate:
+
+(defun cvs-fileinfo-p (object)
+ "Return t if OBJECT is a cvs-fileinfo."
+ (eq (car-safe object) 'CVS-FILEINFO))
+
+;;;; End of types.
+
+;;----------
+(defun cvs-use-temp-buffer ()
+ "Display a temporary buffer in another window and select it.
+The selected window will not be changed. The temporary buffer will
+be erased and writable."
+
+ (let ((dir default-directory))
+ (display-buffer (get-buffer-create cvs-temp-buffer-name))
+ (set-buffer cvs-temp-buffer-name)
+ (setq buffer-read-only nil)
+ (setq default-directory dir)
+ (erase-buffer)))
+
+;;----------
+(defun cvs-examine (directory &optional local)
+ "Run a 'cvs -n update' in the current working directory.
+That is, check what needs to be done, but don't change the disc.
+Feed the output to a *cvs* buffer and run cvs-mode on it.
+If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run.
+WARNING: this doesn't work very well yet...."
+
+ ;; TODO: this should do everything cvs-update does...
+ ;; for example, for CONFLICT files, it should setup fileinfo appropriately
+
+ (interactive (list (read-file-name "CVS Update (directory): "
+ nil default-directory nil)
+ current-prefix-arg))
+ (cvs-do-update directory local 'noupdate))
+
+;;----------
+(defun cvs-update (directory &optional local)
+ "Run a 'cvs update' in the current working directory. Feed the
+output to a *cvs* buffer and run cvs-mode on it.
+If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run."
+
+ (interactive (list (read-file-name "CVS Update (directory): "
+ nil default-directory nil)
+ current-prefix-arg))
+ (cvs-do-update directory local nil)
+ (switch-to-buffer cvs-buffer-name))
+
+;;----------
+(defun cvs-update-other-window (directory &optional local)
+ "Run a 'cvs update' in the current working directory. Feed the
+output to a *cvs* buffer, display it in the other window, and run
+cvs-mode on it.
+
+If optional prefix argument LOCAL is non-nil, 'cvs update -l' is run."
+
+ (interactive (list (read-file-name "CVS Update other window (directory): "
+ nil default-directory nil)
+ current-prefix-arg))
+ (cvs-do-update directory local nil)
+ (switch-to-buffer-other-window cvs-buffer-name))
+
+;;----------
+(defun cvs-filter (predicate list &rest extra-args)
+ "Apply PREDICATE to each element on LIST.
+Args: PREDICATE LIST &rest EXTRA-ARGS.
+
+Return a new list consisting of those elements that PREDICATE
+returns non-nil for.
+
+If more than two arguments are given the remaining args are
+passed to PREDICATE."
+
+ ;; Avoid recursion - this should work for LONG lists also!
+ (let* ((head (cons 'dummy-header nil))
+ (tail head))
+ (while list
+ (if (apply predicate (car list) extra-args)
+ (setq tail (setcdr tail (list (car list)))))
+ (setq list (cdr list)))
+ (cdr head)))
+
+;;----------
+(defun cvs-mode-update-no-prompt ()
+ "Run cvs update in current directory."
+
+ (interactive)
+ (cvs-do-update default-directory nil nil))
+
+;;----------
+(defun cvs-do-update (directory local dont-change-disc)
+ "Do a 'cvs update' in DIRECTORY.
+Args: DIRECTORY LOCAL DONT-CHANGE-DISC.
+
+If LOCAL is non-nil 'cvs update -l' is executed.
+If DONT-CHANGE-DISC is non-nil 'cvs -n update' is executed.
+Both LOCAL and DONT-CHANGE-DISC may be non-nil simultaneously.
+
+*Note*: DONT-CHANGE-DISC does not yet work. The parser gets confused."
+
+ (save-some-buffers)
+ ;; Ensure that it is safe to do an update. If not, ask user
+ ;; for confirmation.
+ (if (and (boundp 'cvs-cookie-handle) (collection-buffer cvs-cookie-handle))
+ (if (collection-collect-tin
+ cvs-cookie-handle
+ '(lambda (cookie) (eq (cvs-fileinfo->type cookie) 'CONFLICT)))
+ (if (not
+ (yes-or-no-p
+ "Only update if conflicts have been resolved. Continue? "))
+ (error "Update aborted by user request."))))
+ (if (not (file-exists-p cvs-program))
+ (error "%s: file not found (check setting of cvs-program)"
+ cvs-program))
+ (let* ((this-dir (file-name-as-directory (expand-file-name directory)))
+ (update-buffer (generate-new-buffer
+ (concat " " (file-name-nondirectory
+ (substring this-dir 0 -1))
+ "-update")))
+ (temp-name (make-temp-name
+ (concat (file-name-as-directory
+ (or (getenv "TMPDIR") "/tmp"))
+ "pcl-cvs.")))
+ (args nil))
+
+ ;; Check that this-dir exists and is a directory that is under CVS contr.
+
+ (if (not (file-directory-p this-dir))
+ (error "%s is not a directory." this-dir))
+ (if (not (file-directory-p (concat this-dir "CVS")))
+ (error "%s does not contain CVS controlled files." this-dir))
+ (if (file-readable-p (concat this-dir "CVS/Root"))
+ (save-excursion ; read CVS/Root into cvs-cvsroot
+ (find-file (concat this-dir "CVS/Root"))
+ (goto-char (point-min))
+ (setq cvs-cvsroot (buffer-substring (point)
+ (progn (end-of-line) (point))))
+ (if (not cvs-cvsroot)
+ (error "Invalid contents of %sCVS/Root" this-dir))
+ (kill-buffer (current-buffer)))
+ (if (and cvs-cvsroot-required
+ (not (or (getenv "CVSROOT") cvs-cvsroot)))
+ (error "Both cvs-cvsroot and environment variable CVSROOT are unset, and no CVS/Root.")))
+
+ ;; Check that at most one `cvs update' is run at any time.
+
+ (if (and cvs-update-running (process-status cvs-update-running)
+ (or (eq (process-status cvs-update-running) 'run)
+ (eq (process-status cvs-update-running) 'stop)))
+ (error "Can't run two `cvs update' simultaneously."))
+
+ (if (not (listp cvs-update-optional-flags))
+ (error "cvs-update-optional-flags should be set using cvs-set-update-optional-flags"))
+
+ ;; Generate "-d /master -n update -l".
+ (setq args (concat (if cvs-cvsroot (concat " -d " cvs-cvsroot))
+ (if dont-change-disc " -n ")
+ " update "
+ (if local " -l ")
+ (if cvs-update-optional-flags
+ (mapconcat 'identity
+ (copy-sequence cvs-update-optional-flags)
+ " "))))
+
+ ;; Set up the buffer that receives the stderr output from "cvs update".
+ (set-buffer update-buffer)
+ (setq default-directory this-dir)
+ (make-local-variable 'cvs-stdout-file)
+ (setq cvs-stdout-file temp-name)
+
+ (setq cvs-update-running
+ (let ((process-connection-type nil)) ; Use a pipe, not a pty.
+ (start-process "cvs" update-buffer cvs-shell "-c"
+ (concat cvs-program " " args " > " temp-name))))
+
+ (setq mode-line-process
+ (concat ": "
+ (symbol-name (process-status cvs-update-running))))
+ (set-buffer-modified-p (buffer-modified-p)) ; Update the mode line.
+ (set-process-sentinel cvs-update-running 'cvs-sentinel)
+ (set-process-filter cvs-update-running 'cvs-update-filter)
+ (set-marker (process-mark cvs-update-running) (point-min))
+
+ (save-excursion
+ (set-buffer (get-buffer-create cvs-buffer-name))
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (cvs-mode))
+
+ (setq cvs-cookie-handle
+ (collection-create
+ cvs-buffer-name 'cvs-pp
+ cvs-startup-message ;See comment above cvs-startup-message.
+ "---------- End -----"))
+
+ (cookie-enter-first
+ cvs-cookie-handle
+ (cvs-create-fileinfo
+ 'MESSAGE nil nil (concat "\n Running `cvs " args "' in " this-dir
+ "...\n")))
+
+ (save-excursion
+ (set-buffer cvs-buffer-name)
+ (setq mode-line-process
+ (concat ": "
+ (symbol-name (process-status cvs-update-running))))
+ (set-buffer-modified-p (buffer-modified-p)) ; Update the mode line.
+ (setq buffer-read-only t))
+
+ ;; Work around a bug in emacs 18.57 and earlier.
+ (setq cvs-buffers-to-delete
+ (cvs-delete-unused-temporary-buffers cvs-buffers-to-delete)))
+
+ ;; The following line is said to improve display updates on some
+ ;; emacses. It shouldn't be needed, but it does no harm.
+ (sit-for 0))
+
+;;----------
+(defun cvs-delete-unused-temporary-buffers (list)
+ "Delete all buffers on LIST that is not visible.
+Return a list of all buffers that still is alive."
+
+ (cond
+ ((null list) nil)
+ ((get-buffer-window (car list))
+ (cons (car list)
+ (cvs-delete-unused-temporary-buffers (cdr list))))
+ (t
+ (kill-buffer (car list))
+ (cvs-delete-unused-temporary-buffers (cdr list)))))
+
+;;----------
+(put 'cvs-mode 'mode-class 'special)
+
+;;----------
+(defun cvs-mode ()
+ "\\<cvs-mode-map>Mode used for pcl-cvs, a front-end to CVS.
+
+To get to the \"*cvs*\" buffer you should use ``\\[execute-extended-command] cvs-update''.
+
+Full documentation is in the Texinfo file. Here are the most useful commands:
+
+\\[cvs-mode-previous-line] Move up. \\[cvs-mode-next-line] Move down.
+\\[cvs-mode-commit] Commit file. \\[cvs-mode-update-no-prompt] Re-update directory.
+\\[cvs-mode-mark] Mark file/dir. \\[cvs-mode-unmark] Unmark file/dir.
+\\[cvs-mode-mark-all-files] Mark all files. \\[cvs-mode-unmark-all-files] Unmark all files.
+\\[cvs-mode-find-file] Edit file/run Dired. \\[cvs-mode-find-file-other-window] Find file or run Dired in other window.
+\\[cvs-mode-ignore] Add file to ./.cvsignore. \\[cvs-mode-add-change-log-entry-other-window] Write ChangeLog in other window.
+\\[cvs-mode-add] Add to repository. \\[cvs-mode-remove-file] Remove file.
+\\[cvs-mode-diff-cvs] Diff with base revision. \\[cvs-mode-diff-backup] Diff backup file.
+\\[cvs-mode-ediff] Ediff base rev & backup. \\[cvs-mode-diff-vendor] Show merge from vendor branch.
+\\[cvs-mode-emerge] Emerge base rev & backup. \\[cvs-mode-diff-backup] Diff backup file.
+\\[cvs-mode-acknowledge] Delete line from buffer. \\[cvs-mode-remove-handled] Remove processed entries.
+\\[cvs-mode-log] Run ``cvs log''. \\[cvs-mode-status] Run ``cvs status''.
+\\[cvs-mode-tag] Run ``cvs tag''. \\[cvs-mode-rtag] Run ``cvs rtag''.
+\\[cvs-mode-changelog-commit] Like \\[cvs-mode-commit], but get default log text from ChangeLog.
+\\[cvs-mode-undo-local-changes] Revert the last checked in version - discard your changes to the file.
+
+Entry to this mode runs cvs-mode-hook.
+This description is updated for release 1.05-CVS-$Name: $ of pcl-cvs.
+
+All bindings:
+\\{cvs-mode-map}"
+
+ (interactive)
+ (setq major-mode 'cvs-mode)
+ (setq mode-name "CVS")
+ (setq mode-line-process nil)
+;; for older v18 emacs
+;;(buffer-flush-undo (current-buffer))
+ (buffer-disable-undo (current-buffer))
+ (make-local-variable 'goal-column)
+ (setq goal-column cvs-cursor-column)
+ (use-local-map cvs-mode-map)
+ (run-hooks 'cvs-mode-hook))
+
+;;----------
+(defun cvs-sentinel (proc msg)
+ "Sentinel for the cvs update process.
+This is responsible for parsing the output from the cvs update when
+it is finished."
+
+ (cond
+ ((null (buffer-name (process-buffer proc)))
+ ;; buffer killed
+ (set-process-buffer proc nil))
+ ((memq (process-status proc) '(signal exit))
+ (let* ((obuf (current-buffer))
+ (omax (point-max))
+ (opoint (point)))
+ ;; save-excursion isn't the right thing if
+ ;; process-buffer is current-buffer
+ (unwind-protect
+ (progn
+ (set-buffer (process-buffer proc))
+ (setq mode-line-process
+ (concat ": "
+ (symbol-name (process-status proc))))
+ (let* ((out-file cvs-stdout-file)
+ (stdout-buffer (find-file-noselect out-file)))
+ (save-excursion
+ (set-buffer stdout-buffer)
+ (rename-buffer (concat " "
+ (file-name-nondirectory out-file)) t))
+ (cvs-parse-update stdout-buffer (process-buffer proc))
+ (setq cvs-buffers-to-delete
+ (cons (process-buffer proc)
+ (cons stdout-buffer
+ cvs-buffers-to-delete)))
+ (delete-file out-file)))
+ (set-buffer-modified-p (buffer-modified-p))
+ (setq cvs-update-running nil))
+ (if (equal obuf (process-buffer proc))
+ nil
+ (set-buffer (process-buffer proc))
+ (if (< opoint omax)
+ (goto-char opoint))
+ (set-buffer obuf))))))
+
+;;----------
+(defun cvs-update-filter (proc string)
+ "Filter function for pcl-cvs.
+This function gets the output that CVS sends to stderr. It inserts it
+into (process-buffer proc) but it also checks if CVS is waiting for a
+lock file. If so, it inserts a message cookie in the *cvs* buffer."
+
+ (let ((old-buffer (current-buffer))
+ (data (match-data)))
+ (unwind-protect
+ (progn
+ (set-buffer (process-buffer proc))
+ (save-excursion
+ ;; Insert the text, moving the process-marker.
+ (goto-char (process-mark proc))
+ (insert string)
+ (set-marker (process-mark proc) (point))
+ ;; Delete any old lock message
+ (if (tin-nth cvs-cookie-handle 1)
+ (tin-delete cvs-cookie-handle
+ (tin-nth cvs-cookie-handle 1)))
+ ;; Check if CVS is waiting for a lock.
+ (beginning-of-line 0) ;Move to beginning of last
+ ;complete line.
+ (cond
+ ((looking-at
+ "^cvs \\(update\\|server\\): \\[..:..:..\\] waiting for \\(.*\\)lock in \\(.*\\)$")
+ (setq cvs-lock-file (buffer-substring (match-beginning 3)
+ (match-end 3)))
+ (cookie-enter-last
+ cvs-cookie-handle
+ (cvs-create-fileinfo
+ 'MESSAGE nil nil
+ (concat "\tWaiting for "
+ (buffer-substring (match-beginning 2)
+ (match-end 2))
+ "lock in " cvs-lock-file
+ ".\n\t (type M-x cvs-delete-lock to delete it)")))))))
+ (store-match-data data)
+ (set-buffer old-buffer))))
+
+;;----------
+(defun cvs-delete-lock ()
+ "Delete the lock file that CVS is waiting for.
+Note that this can be dangerous. You should only do this
+if you are convinced that the process that created the lock is dead."
+
+ (interactive)
+ (cond
+ ((not (or (file-exists-p
+ (concat (file-name-as-directory cvs-lock-file) "#cvs.lock"))
+ (cvs-filter (function cvs-lock-file-p)
+ (directory-files cvs-lock-file))))
+ (error "No lock files found."))
+ ((yes-or-no-p (concat "Really delete locks in " cvs-lock-file "? "))
+ ;; Re-read the directory -- the locks might have disappeared.
+ (let ((locks (cvs-filter (function cvs-lock-file-p)
+ (directory-files cvs-lock-file))))
+ (while locks
+ (delete-file (concat (file-name-as-directory cvs-lock-file)
+ (car locks)))
+ (setq locks (cdr locks)))
+ (cvs-remove-directory
+ (concat (file-name-as-directory cvs-lock-file) "#cvs.lock"))))))
+
+;;----------
+(defun cvs-remove-directory (dir)
+ "Remove a directory."
+
+ (if (file-directory-p dir)
+ (call-process cvs-rmdir-program nil nil nil dir)
+ (error "Not a directory: %s" dir))
+ (if (file-exists-p dir)
+ (error "Could not remove directory %s" dir)))
+
+;;----------
+(defun cvs-lock-file-p (file)
+ "Return true if FILE looks like a CVS lock file."
+
+ (or
+ (string-match "^#cvs.tfl.[0-9]+$" file)
+ (string-match "^#cvs.rfl.[0-9]+$" file)
+ (string-match "^#cvs.wfl.[0-9]+$" file)))
+
+;;----------
+(defun cvs-quote-multiword-string (str)
+ "Return STR surrounded in single quotes if it contains whitespace."
+ (cond ((string-match "[ \t\n]" str)
+ (concat "'" str "'"))
+ (t
+ str)))
+
+;;----------
+;; this should be in subr.el or some similar place....
+(defun parse-string (str &optional regexp)
+ "Explode the string STR into a list of words ala strtok(3). Optional REGEXP
+defines regexp matching word separator, which defaults to \"[ \\t\\n]+\"."
+ (let (str-list ; new list
+ str-token ; "index" of next token
+ (str-start 0) ; "index" of current token
+ (str-sep (if regexp
+ regexp
+ "[ \t\n]+")))
+ (while (setq str-token (string-match str-sep str str-start))
+ (setq str-list
+ (nconc str-list
+ (list (substring str str-start str-token))))
+ (setq str-start (match-end 0)))
+ ;; tag on the remainder as the final item
+ (if (not (>= str-start (length str)))
+ (setq str-list
+ (nconc str-list
+ (list (substring str str-start)))))
+ str-list))
+
+;;----------
+(defun cvs-make-list (str)
+ "Return list of words made from the string STR."
+ (cond ((string-match "[ \t\n]+" str)
+ (let ((new-str (parse-string str "[ \t\n]+")))
+ ;; this is ugly, but assume if the first element is empty, there are
+ ;; no more elements.
+ (cond ((string= (car new-str) "")
+ nil)
+ (t
+ new-str))))
+ ((string= str "")
+ nil)
+ (t
+ (list str))))
+
+;;----------
+(defun cvs-skip-line (stdout stderr regexp &optional arg)
+ "Like forward-line, but check that the skipped line matches REGEXP.
+Args: STDOUT STDERR REGEXP &optional ARG.
+
+If it doesn't match REGEXP a bug report is generated and displayed.
+STDOUT and STDERR is only used to do that.
+
+If optional ARG, a number, is given the ARGth parenthesized expression
+in the REGEXP is returned as a string.
+Point should be in column 1 when this function is called."
+
+ (cond
+ ((looking-at regexp)
+ (forward-line 1)
+ (if arg
+ (buffer-substring (match-beginning arg)
+ (match-end arg))))
+ (t
+ (cvs-parse-error stdout
+ stderr
+ (if (eq (current-buffer) stdout)
+ 'STDOUT
+ 'STDERR)
+ (point)
+ regexp))))
+
+;;----------
+(defun cvs-get-current-dir (root-dir dirname)
+ "Return current working directory, suitable for cvs-parse-update.
+Args: ROOT-DIR DIRNAME.
+
+Concatenates ROOT-DIR and DIRNAME to form an absolute path."
+
+ (if (string= "." dirname)
+ (substring root-dir 0 -1)
+ (concat root-dir dirname)))
+
+;;----------
+(defun cvs-compare-fileinfos (a b)
+ "Compare fileinfo A with fileinfo B and return t if A is `less'."
+
+ (cond
+ ;; Sort acording to directories.
+ ((string< (cvs-fileinfo->dir a) (cvs-fileinfo->dir b)) t)
+ ((not (string= (cvs-fileinfo->dir a) (cvs-fileinfo->dir b))) nil)
+ ;; The DIRCHANGE entry is always first within the directory.
+ ((and (eq (cvs-fileinfo->type a) 'DIRCHANGE)
+ (not (eq (cvs-fileinfo->type b) 'DIRCHANGE))) t)
+ ((and (eq (cvs-fileinfo->type b) 'DIRCHANGE)
+ (not (eq (cvs-fileinfo->type a) 'DIRCHANGE))) nil)
+ ;; All files are sorted by file name.
+ ((string< (cvs-fileinfo->file-name a) (cvs-fileinfo->file-name b)))))
+
+;;----------
+(defun cvs-parse-error (stdout-buffer stderr-buffer err-buf pos &optional indicator)
+ "Handle a parse error when parsing the output from cvs.
+Args: STDOUT-BUFFER STDERR-BUFFER ERR-BUF POS &optional INDICATOR.
+
+ERR-BUF should be 'STDOUT or 'STDERR."
+
+ (setq pos (1- pos))
+ (set-buffer cvs-buffer-name)
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (insert "To: " pcl-cvs-bugs-address "\n")
+ (insert "Subject: pcl-cvs release" pcl-cvs-version " parse error.\n")
+ (insert (concat mail-header-separator "\n"))
+ (insert "This bug report is automatically generated by pcl-cvs\n")
+ (insert "because it doesn't understand some output from CVS. Below\n")
+ (insert "is detailed information about the error. Please send\n")
+ (insert "this, together with any information you think might be\n")
+ (insert "useful for me to fix the bug, to the address above. But\n")
+ (insert "please check the \"known problems\" section of the\n")
+ (insert "documentation first. Note that this buffer contains\n")
+ (insert "information that you might consider confidential. You\n")
+ (insert "are encouraged to read through it before sending it.\n")
+ (insert "\n")
+ (insert "Press C-c C-c to send this email.\n\n")
+ (insert "Please state the version of these programs you are using:\n\n")
+ (insert "RCS: \ndiff: \n\n")
+
+ (let* ((stdout (save-excursion (set-buffer stdout-buffer) (buffer-string)))
+ (stderr (save-excursion (set-buffer stderr-buffer) (buffer-string)))
+ (errstr (if (eq err-buf 'STDOUT) stdout stderr))
+ (errline-end (string-match "\n" errstr pos))
+ (errline (substring errstr pos errline-end)))
+ (insert (format "Offending line (%d chars): >" (- errline-end pos)))
+ (insert errline)
+ (insert "<\n")
+ (insert "Sent to " (symbol-name err-buf) " at pos " (format "%d\n" pos))
+ (if indicator
+ (insert "Optional args: \"" indicator "\".\n"))
+ (insert "\nEmacs-version: " (emacs-version) "\n")
+ (insert "Pcl-cvs Version: "
+ "@(#)OrigId: pcl-cvs.el,v 1.93 1993/05/31 22:44:00 ceder Exp\n")
+ (insert "CVS Version: "
+ "@(#)cvs/contrib/pcl-cvs:$Name: $:$Id: pcl-cvs.el,v 1.2 1996/04/14 20:09:45 kfogel Exp $\n\n")
+ (insert (format "--- Contents of stdout buffer (%d chars) ---\n"
+ (length stdout)))
+ (insert stdout)
+ (insert "--- End of stdout buffer ---\n")
+ (insert (format "--- Contents of stderr buffer (%d chars) ---\n"
+ (length stderr)))
+ (insert stderr)
+ (insert "--- End of stderr buffer ---\n")
+ (insert "\nEnd of bug report.\n")
+ (require 'sendmail)
+ (mail-mode)
+ (error "CVS parse error - please report this bug.")))
+
+;;----------
+(defun cvs-parse-update (stdout-buffer stderr-buffer)
+ "Parse the output from `cvs update'.
+
+Args: STDOUT-BUFFER STDERR-BUFFER.
+
+This functions parses the from `cvs update' (which should be
+separated in its stdout- and stderr-components) and prints a
+pretty representation of it in the *cvs* buffer.
+
+Signals an error if unexpected output was detected in the buffer."
+
+ (let* ((head (cons 'dummy nil))
+ (tail (cvs-parse-stderr stdout-buffer stderr-buffer
+ head default-directory))
+ (root-dir default-directory))
+ (cvs-parse-stdout stdout-buffer stderr-buffer tail root-dir)
+ (setq head (sort (cdr head) (function cvs-compare-fileinfos)))
+ (collection-clear cvs-cookie-handle)
+ (collection-append-cookies cvs-cookie-handle head)
+ (cvs-remove-stdout-shadows)
+ (if cvs-auto-remove-handled-directories
+ (cvs-remove-empty-directories))
+ (set-buffer cvs-buffer-name)
+ (cvs-mode)
+ (goto-char (point-min))
+ (tin-goto-previous cvs-cookie-handle (point-min) 1)
+ (setq default-directory root-dir)))
+
+;;----------
+(defun cvs-remove-stdout-shadows ()
+ "Remove entries in the *cvs* buffer that comes from both stdout and stderr.
+If there is two entries for a single file the second one should be
+deleted. (Remember that sort uses a stable sort algorithm, so one can
+be sure that the stderr entry is always first)."
+
+ (collection-filter-tins cvs-cookie-handle
+ (function
+ (lambda (tin)
+ (not (cvs-shadow-entry-p tin))))))
+
+;;----------
+(defun cvs-shadow-entry-p (tin)
+ "Return non-nil if TIN is a shadow entry.
+Args: TIN.
+
+A TIN is a shadow entry if the previous tin contains the same file."
+
+ (let* ((previous-tin (tin-previous cvs-cookie-handle tin))
+ (curr (tin-cookie cvs-cookie-handle tin))
+ (prev (and previous-tin
+ (tin-cookie cvs-cookie-handle previous-tin))))
+ (and
+ prev curr
+ (string= (cvs-fileinfo->file-name prev)
+ (cvs-fileinfo->file-name curr))
+ (string= (cvs-fileinfo->dir prev)
+ (cvs-fileinfo->dir curr))
+ (or
+ (and (eq (cvs-fileinfo->type prev) 'CONFLICT)
+ (eq (cvs-fileinfo->type curr) 'CONFLICT))
+ (and (eq (cvs-fileinfo->type prev) 'MERGED)
+ (eq (cvs-fileinfo->type curr) 'MODIFIED))
+ (and (eq (cvs-fileinfo->type prev) 'REM-EXIST)
+ (eq (cvs-fileinfo->type curr) 'REMOVED))))))
+
+;;----------
+(defun cvs-find-backup-file (filename &optional dirname)
+ "Look for a backup file for FILENAME, optionally in directory DIRNAME, and if
+there is one, return the name of the first file found as a string."
+
+ (if (eq dirname nil)
+ (setq dirname default-directory))
+ (car (directory-files dirname nil (concat "^\\" cvs-bakprefix filename
+ "\\."))))
+
+;;----------
+(defun cvs-find-backup-revision (filename)
+ "Take FILENAME as the name of a cvs backup file and return the revision of
+that file as a string."
+
+ (substring filename
+ (+ 1 (string-match "\\.\\([0-9.]+\\)$" filename))))
+
+;;----------
+(defun cvs-parse-stderr (stdout-buffer stderr-buffer head dir)
+ "Parse the output from CVS that is written to stderr.
+Args: STDOUT-BUFFER STDERR-BUFFER HEAD DIR
+
+STDOUT-BUFFER holds the output that cvs sent to stdout. It is only
+used to create a bug report in case there is a parse error.
+STDERR-BUFFER is the buffer that holds the output to parse.
+HEAD is a cons-cell, the head of the list that is built.
+DIR is the directory the `cvs update' was run in.
+
+This function returns the last cons-cell in the list that is built."
+
+ (save-window-excursion
+ (set-buffer stderr-buffer)
+ (goto-char (point-min))
+ (let ((current-dir dir)
+ (root-dir dir))
+
+ (while (< (point) (point-max))
+ (cond
+
+ ;; CVS is descending a subdirectory.
+
+ ((looking-at
+ "^cvs \\(server\\|update\\): Updating \\(.*\\)$")
+ (setq current-dir
+ (cvs-get-current-dir
+ root-dir
+ (buffer-substring (match-beginning 2) (match-end 2))))
+ (setcdr head (list (cvs-create-fileinfo
+ 'DIRCHANGE
+ current-dir
+ "." ; the old version had nil here???
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (setq head (cdr head))
+ (forward-line 1))
+
+ ;; File removed, since it is removed (by third party) in repository.
+
+ ((or (looking-at
+ "^cvs \\(update\\|server\\): warning: \\(.*\\) is not (any longer) pertinent")
+ (looking-at
+ "^cvs \\(update\\|server\\): \\(.*\\) is no longer in the repository"))
+
+ (setcdr head (list (cvs-create-fileinfo
+ 'CVS-REMOVED
+ current-dir
+ (file-name-nondirectory
+ (buffer-substring (match-beginning 2)
+ (match-end 2)))
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (setq head (cdr head))
+ (forward-line 1))
+
+ ;; File removed by you, but recreated by cvs. Ignored. Will say
+ ;; "Updated" on the next line.
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): warning: .* was lost$")
+ (forward-line 1))
+
+ ;; File unknown for some reason.
+ ;; FIXME: is it really a good idea to add this as unknown here?
+
+ ((looking-at
+ "cvs \\(update\\|server\\): nothing known about \\(.*\\)$")
+ (let ((filename (buffer-substring (match-beginning 2)
+ (match-end 2))))
+ (if (file-directory-p filename)
+ (setcdr head (list (cvs-create-fileinfo
+ 'UNKNOWN-DIR
+ current-dir
+ "."
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (setcdr head (list (cvs-create-fileinfo
+ 'UNKNOWN
+ current-dir
+ (file-name-nondirectory filename)
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))))
+ (setq head (cdr head))
+ (forward-line 1))
+
+ ;; A file that has been created by you, but added to the cvs
+ ;; repository by another.
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): move away \\(.*\\); it is in the way$")
+ (setcdr head (list (cvs-create-fileinfo
+ 'MOVE-AWAY
+ current-dir
+ (file-name-nondirectory
+ (buffer-substring (match-beginning 2)
+ (match-end 2)))
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (setq head (cdr head))
+ (forward-line 1))
+
+ ;; Cvs waits for a lock. Ignore.
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): \\[..:..:..\\] waiting for .*lock in ")
+ (forward-line 1))
+
+ ;; File removed in repository, but edited by you.
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): conflict: \\(.*\\) is modified but no longer in the repository$")
+ (setcdr head (list
+ (cvs-create-fileinfo
+ 'REM-CONFLICT
+ current-dir
+ (file-name-nondirectory
+ (buffer-substring (match-beginning 2)
+ (match-end 2)))
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (setq head (cdr head))
+ (forward-line 1))
+
+ ;; File removed in repository, but edited by someone else.
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): conflict: removed \\(.*\\) was modified by second party")
+ (setcdr head
+ (list
+ (cvs-create-fileinfo
+ 'MOD-CONFLICT
+ current-dir
+ (buffer-substring (match-beginning 1)
+ (match-end 1))
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (setq head (cdr head))
+ (forward-line 1))
+
+ ;; File removed in repository, but not in local directory.
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): \\(.*\\) should be removed and is still there")
+ (setcdr head
+ (list
+ (cvs-create-fileinfo
+ 'REM-EXIST
+ current-dir
+ (buffer-substring (match-beginning 2)
+ (match-end 2))
+ (buffer-substring (match-beginning 0)
+ (match-end 0)))))
+ (setq head (cdr head))
+ (forward-line 1))
+
+ ;; Error searching for repository
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): in directory ")
+ (let ((start (point)))
+ (forward-line 1)
+ (cvs-skip-line stdout-buffer stderr-buffer
+ (regexp-quote "cvs [update aborted]: there is no repository "))
+ (setcdr head (list (cvs-create-fileinfo
+ 'REPOS-MISSING
+ current-dir
+ nil
+ (buffer-substring start (point)))))
+ (setq head (cdr head))))
+
+ ;; Silly warning from attempted conflict resolution. Ignored.
+ ;; FIXME: Should it be?
+ ;; eg.: "cvs update: cannot find revision APC-web-update in file .cvsignore"
+ ;;
+ ((looking-at
+ "^cvs \\(update\\|server\\): cannot find revision \\(.*\\) in file \\(.*\\)$")
+ (forward-line 1)
+ (message "%s" (buffer-substring (match-beginning 0) (match-end 0))))
+
+ ;; CVS has decided to merge someone elses changes into this document.
+ ;; About to start an rcsmerge operation...
+ ;;
+ ((looking-at
+ "^RCS file: ")
+
+ ;; skip the "RCS file:" line...
+ (forward-line 1)
+
+ (let ((complex-start (point))
+ base-revision ; the first revision retrieved to merge from
+ head-revision ; the second revision retrieved to merge from
+ filename ; the name of the file being merged
+ backup-file ; the name of the backup of the working file
+ backup-revision) ; the revision of the original working file
+
+ (setq base-revision
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^retrieving revision \\(.*\\)$"
+ 1))
+ (setq head-revision
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^retrieving revision \\(.*\\)$"
+ 1))
+ (setq filename
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^Merging differences between [0-9.]+ and [0-9.]+ into \\(.*\\)$"
+ 1))
+ (setq backup-file
+ (cvs-find-backup-file filename current-dir))
+ (setq backup-revision
+ (cvs-find-backup-revision backup-file))
+
+ ;; Was there a conflict during the merge?
+
+ (cond
+
+ ;;;; From CVS-1.3 & RCS-5.6.0.1 with GNU-Diffutils-2.5:
+ ;;;; "cvs update -j OLD-REV -j NEW-REV ."
+ ;;
+ ;; RCS file: /big/web-CVS/apc/cmd/Main/logout.sh,v
+ ;; retrieving revision 1.1.1.1
+ ;; retrieving revision 1.1.1.2
+ ;; Merging differences between 1.1.1.1 and 1.1.1.2 into logout.sh
+ ;; rcsmerge warning: overlaps during merge
+
+ ((looking-at
+ ;; Allow both RCS 5.5 and 5.6. (5.6 prints "rcs" and " warning").
+ "^\\(rcs\\)?merge[:]*\\( warning\\)?: \\((overlaps\\|conflicts\\) during merge$")
+
+ ;; Yes, this is a conflict.
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^\\(rcs\\)?merge[:]*\\( warning\\)?: \\(overlaps\\|conflicts\\) during merge$")
+
+ ;; this line doesn't seem to appear in all cases -- perhaps only
+ ;; in "-j A -j B" usage, in which case this indicates ????
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^cvs \\(update\\|server\\): conflicts found in ")
+
+ (let ((fileinfo
+ (cvs-create-fileinfo
+ 'CONFLICT current-dir
+ filename
+ (buffer-substring complex-start (point)))))
+
+ ;; squirrel away info about the files that were retrieved for merging
+ (cvs-set-fileinfo->base-revision fileinfo base-revision)
+ (cvs-set-fileinfo->head-revision fileinfo head-revision)
+ (cvs-set-fileinfo->backup-revision fileinfo backup-revision)
+ (cvs-set-fileinfo->backup-file fileinfo backup-file)
+
+ (setcdr head (list fileinfo))
+ (setq head (cdr head))))
+
+ ;; Was it a conflict, and was RCS compiled without DIFF3_BIN, in
+ ;; which case this is a failed conflict resolution?
+
+ ((looking-at
+ ;; Allow both RCS 5.5 and 5.6. (5.6 prints "rcs" and " warning").
+ "^\\(rcs\\)?merge\\( warning\\)?: overlaps or other problems during merge$")
+
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^\\(rcs\\)?merge\\( warning\\)?: overlaps or other problems during merge$")
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^cvs update: could not merge ")
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^cvs update: restoring .* from backup file ")
+ (let ((fileinfo
+ (cvs-create-fileinfo
+ 'CONFLICT current-dir
+ filename
+ (buffer-substring complex-start (point)))))
+ (setcdr head (list fileinfo))
+ (setq head (cdr head))))
+
+ ;; Not a conflict; it must be a succesful merge.
+
+ (t
+ (let ((fileinfo
+ (cvs-create-fileinfo
+ 'MERGED current-dir
+ filename
+ (buffer-substring complex-start (point)))))
+ (cvs-set-fileinfo->base-revision fileinfo base-revision)
+ (cvs-set-fileinfo->head-revision fileinfo head-revision)
+ (cvs-set-fileinfo->backup-revision fileinfo backup-revision)
+ (cvs-set-fileinfo->backup-file fileinfo backup-file)
+ (setcdr head (list fileinfo))
+ (setq head (cdr head)))))))
+
+ ;; Error messages from CVS (incomplete)
+
+ ((looking-at
+ "^cvs \\(update\\|server\\): \\(invalid option .*\\)$")
+ (error "Interface problem with CVS: %s"
+ (buffer-substring (match-beginning 2) (match-end 2))))
+
+ ;; network errors
+
+ ;; Kerberos connection attempted but failed. This is not
+ ;; really an error, as CVS will automatically fall back to
+ ;; rsh. Plus it tries kerberos, if available, even when rsh
+ ;; is what you really wanted.
+
+ ((looking-at
+ "^cvs update: kerberos connect:.*$")
+ (forward-line 1)
+ (message "Remote CVS: %s"
+ (buffer-substring (match-beginning 0) (match-end 0))))
+
+ ;; And when kerberos *does* fail, cvs prints out some stuff
+ ;; as it tries rsh. Ignore that stuff too.
+
+ ((looking-at
+ "^cvs update: trying to start server using rsh$")
+ (forward-line 1))
+
+ ((looking-at
+ "^\\([^:]*\\) Connection timed out")
+ (error "Remote CVS: %s"
+ (buffer-substring (match-beginning 0) (match-end 0))))
+
+ ((looking-at
+ "^Permission denied.")
+ (error "Remote CVS: %s"
+ (buffer-substring (match-beginning 0) (match-end 0))))
+
+ ((looking-at
+ "^cvs \\[update aborted\\]: premature end of file from server")
+ (error "Remote CVS: %s"
+ (buffer-substring (match-beginning 0) (match-end 0))))
+
+ ;; Empty line. Probably inserted by mistake by user (or developer :-)
+ ;; Ignore.
+
+ ((looking-at
+ "^$")
+ (forward-line 1))
+
+ ;; top-level parser (cond) default clause
+
+ (t
+ (cvs-skip-line stdout-buffer stderr-buffer
+ "^UN-MATCHABLE-OUTPUT"))))))
+
+ ;; cause this function to return the head of the parser output list
+ head)
+
+;;----------
+(defun cvs-parse-stdout (stdout-buffer stderr-buffer head root-dir)
+ "Parse the output from CVS that is written to stderr.
+Args: STDOUT-BUFFER STDERR-BUFFER HEAD ROOT-DIR
+
+STDOUT-BUFFER is the buffer that holds the output to parse.
+STDERR-BUFFER holds the output that cvs sent to stderr. It is only
+used to create a bug report in case there is a parse error.
+
+HEAD is a cons-cell, the head of the list that is built.
+ROOT-DIR is the directory the `cvs update' was run in.
+
+This function doesn't return anything particular."
+
+ (save-window-excursion
+ (set-buffer stdout-buffer)
+ (goto-char (point-min))
+ (while (< (point) (point-max))
+ (cond
+
+ ;; M: The file is modified by the user, and untouched in the repository.
+ ;; A: The file is "cvs add"ed, but not "cvs ci"ed.
+ ;; R: The file is "cvs remove"ed, but not "cvs ci"ed.
+ ;; C: Conflict (only useful if a join was done and stderr has info...)
+ ;; U: The file is copied from the repository.
+ ;; ?: Unknown file or directory.
+
+ ((looking-at
+ "^\\([MARCUP?]\\) \\(.*\\)$")
+ (let*
+ ((c (char-after (match-beginning 1)))
+ (full-path (concat (file-name-as-directory root-dir)
+ (buffer-substring (match-beginning 2)
+ (match-end 2))))
+ (isdir (file-directory-p full-path))
+ (fileinfo (cvs-create-fileinfo
+ (cond ((eq c ?M) 'MODIFIED)
+ ((eq c ?A) 'ADDED)
+ ((eq c ?R) 'REMOVED)
+ ((eq c ?C) 'CONFLICT)
+ ((eq c ?U) 'UPDATED)
+ ((eq c ?P) 'PATCHED)
+ ((eq c ??) (if isdir
+ 'UNKNOWN-DIR
+ 'UNKNOWN)))
+ (substring (file-name-directory full-path) 0 -1)
+ (file-name-nondirectory full-path)
+ (buffer-substring (match-beginning 0) (match-end 0)))))
+ ;; Updated and Patched files require no further action.
+ (if (memq c '(?U ?P))
+ (cvs-set-fileinfo->handled fileinfo t))
+
+ ;; Link this last on the list.
+ (setcdr head (list fileinfo))
+ (setq head (cdr head))
+ (forward-line 1)))
+
+ ;; Executing a program because of the -u option in modules.
+ ((looking-at
+ "^cvs \\(update\\|server\\): Executing")
+ ;; Skip by any output the program may generate to stdout.
+ ;; Note that pcl-cvs will get seriously confused if the
+ ;; program prints anything to stderr.
+ (re-search-forward cvs-update-prog-output-skip-regexp)
+ (forward-line 1))
+
+ (t
+ (cvs-parse-error stdout-buffer stderr-buffer 'STDOUT (point)
+ "cvs-parse-stdout"))))))
+
+;;----------
+(defun cvs-pp (fileinfo)
+ "Pretty print FILEINFO. Insert a printed representation in current buffer.
+For use by the cookie package."
+
+ (let ((a (cvs-fileinfo->type fileinfo))
+ (s (if (cvs-fileinfo->marked fileinfo)
+ "*" " "))
+ (f (cvs-fileinfo->file-name fileinfo))
+ (ci (if (cvs-fileinfo->handled fileinfo)
+ " " "ci")))
+ (insert
+ (cond
+ ((eq a 'UPDATED)
+ (format "%s Updated %s" s f))
+ ((eq a 'PATCHED)
+ (format "%s Patched %s" s f))
+ ((eq a 'MODIFIED)
+ (format "%s Modified %s %s" s ci f))
+ ((eq a 'MERGED)
+ (format "%s Merged %s %s" s ci f))
+ ((eq a 'CONFLICT)
+ (format "%s Conflict %s" s f))
+ ((eq a 'ADDED)
+ (format "%s Added %s %s" s ci f))
+ ((eq a 'REMOVED)
+ (format "%s Removed %s %s" s ci f))
+ ((eq a 'UNKNOWN)
+ (format "%s Unknown %s" s f))
+ ((eq a 'UNKNOWN-DIR)
+ (format "%s Unknown dir %s" s f))
+ ((eq a 'CVS-REMOVED)
+ (format "%s Removed from repository: %s" s f))
+ ((eq a 'REM-CONFLICT)
+ (format "%s Conflict: Removed from repository, changed by you: %s" s f))
+ ((eq a 'MOD-CONFLICT)
+ (format "%s Conflict: Removed by you, changed in repository: %s" s f))
+ ((eq a 'REM-EXIST)
+ (format "%s Conflict: Removed by you, but still exists: %s" s f))
+ ((eq a 'DIRCHANGE)
+ (format "\nIn directory %s:" (cvs-fileinfo->dir fileinfo)))
+ ((eq a 'MOVE-AWAY)
+ (format "%s Move away %s - it is in the way" s f))
+ ((eq a 'REPOS-MISSING)
+ (format " This repository directory is missing! Remove this directory manually."))
+ ((eq a 'MESSAGE)
+ (cvs-fileinfo->full-log fileinfo))
+ (t
+ (format "%s Internal error! %s" s f))))))
+
+
+;;; You can define your own keymap in .emacs. pcl-cvs.el won't overwrite it.
+
+(if cvs-mode-map
+ nil
+ (setq cvs-mode-map (make-keymap))
+ (suppress-keymap cvs-mode-map)
+ (define-prefix-command 'cvs-mode-map-control-c-prefix)
+ (define-key cvs-mode-map "\C-?" 'cvs-mode-unmark-up)
+ (define-key cvs-mode-map "\C-k" 'cvs-mode-acknowledge)
+ (define-key cvs-mode-map "\C-n" 'cvs-mode-next-line)
+ (define-key cvs-mode-map "\C-p" 'cvs-mode-previous-line)
+ ;; ^C- keys are used to set various flags to control CVS features
+ (define-key cvs-mode-map "\C-c" 'cvs-mode-map-control-c-prefix)
+ (define-key cvs-mode-map "\C-c\C-c" 'cvs-change-cvsroot)
+ (define-key cvs-mode-map "\C-c\C-d" 'cvs-set-diff-flags)
+ (define-key cvs-mode-map "\C-c\C-l" 'cvs-set-log-flags)
+ (define-key cvs-mode-map "\C-c\C-s" 'cvs-set-status-flags)
+ (define-key cvs-mode-map "\C-c\C-u" 'cvs-set-update-optional-flags)
+ ;; M- keys are usually those that operate on modules
+ (define-key cvs-mode-map "\M-\C-?" 'cvs-mode-unmark-all-files)
+ (define-key cvs-mode-map "\M-C" 'cvs-mode-rcs2log) ; i.e. "Create a ChangeLog"
+ (define-key cvs-mode-map "\M-a" 'cvs-mode-admin)
+ (define-key cvs-mode-map "\M-c" 'cvs-mode-checkout)
+ (define-key cvs-mode-map "\M-o" 'cvs-mode-checkout-other-window)
+ (define-key cvs-mode-map "\M-p" 'cvs-mode-rdiff) ; i.e. "create a Patch"
+ (define-key cvs-mode-map "\M-r" 'cvs-mode-release)
+ (define-key cvs-mode-map "\M-t" 'cvs-mode-rtag)
+ ;; keys that operate on files
+ (define-key cvs-mode-map " " 'cvs-mode-next-line)
+ (define-key cvs-mode-map "?" 'describe-mode)
+ (define-key cvs-mode-map "A" 'cvs-mode-add-change-log-entry-other-window)
+ (define-key cvs-mode-map "B" 'cvs-mode-byte-compile-files)
+ (define-key cvs-mode-map "C" 'cvs-mode-changelog-commit)
+ (define-key cvs-mode-map "E" 'cvs-mode-emerge)
+ (define-key cvs-mode-map "G" 'cvs-update)
+ (define-key cvs-mode-map "M" 'cvs-mode-mark-all-files)
+ (define-key cvs-mode-map "Q" 'cvs-examine)
+ (define-key cvs-mode-map "R" 'cvs-mode-revert-updated-buffers)
+ (define-key cvs-mode-map "U" 'cvs-mode-undo-local-changes)
+ (define-key cvs-mode-map "a" 'cvs-mode-add)
+ (define-key cvs-mode-map "b" 'cvs-mode-diff-backup)
+ (define-key cvs-mode-map "c" 'cvs-mode-commit)
+ (define-key cvs-mode-map "d" 'cvs-mode-diff-cvs)
+ (define-key cvs-mode-map "e" 'cvs-mode-ediff)
+ (define-key cvs-mode-map "f" 'cvs-mode-find-file)
+ (define-key cvs-mode-map "g" 'cvs-mode-update-no-prompt)
+ (define-key cvs-mode-map "i" 'cvs-mode-ignore)
+ (define-key cvs-mode-map "l" 'cvs-mode-log)
+ (define-key cvs-mode-map "m" 'cvs-mode-mark)
+ (define-key cvs-mode-map "n" 'cvs-mode-next-line)
+ (define-key cvs-mode-map "o" 'cvs-mode-find-file-other-window)
+ (define-key cvs-mode-map "p" 'cvs-mode-previous-line)
+ (define-key cvs-mode-map "q" 'bury-buffer)
+ (define-key cvs-mode-map "r" 'cvs-mode-remove-file)
+ (define-key cvs-mode-map "s" 'cvs-mode-status)
+ (define-key cvs-mode-map "t" 'cvs-mode-tag)
+ (define-key cvs-mode-map "u" 'cvs-mode-unmark)
+ (define-key cvs-mode-map "v" 'cvs-mode-diff-vendor)
+ (define-key cvs-mode-map "x" 'cvs-mode-remove-handled))
+
+;;----------
+(defun cvs-get-marked (&optional ignore-marks ignore-contents)
+ "Return a list of all selected tins.
+Args: &optional IGNORE-MARKS IGNORE-CONTENTS.
+
+If there are any marked tins, and IGNORE-MARKS is nil, return them. Otherwise,
+if the cursor selects a directory, return all files in it, unless there are
+none, in which case just return the directory; or unless IGNORE-CONTENTS is not
+nil, in which case also just return the directory. Otherwise return (a list
+containing) the file the cursor points to, or an empty list if it doesn't point
+to a file at all."
+
+ (cond
+ ;; Any marked cookies?
+ ((and (not ignore-marks)
+ (collection-collect-tin cvs-cookie-handle 'cvs-fileinfo->marked)))
+ ;; Nope.
+ ((and (not ignore-contents)
+ (let ((sel (tin-locate cvs-cookie-handle (point))))
+ (cond
+ ;; If a directory is selected, all it members are returned.
+ ((and sel (eq (cvs-fileinfo->type (tin-cookie cvs-cookie-handle
+ sel))
+ 'DIRCHANGE))
+ (let ((retsel
+ (collection-collect-tin cvs-cookie-handle
+ 'cvs-dir-member-p
+ (cvs-fileinfo->dir (tin-cookie
+ cvs-cookie-handle sel)))))
+ (if retsel
+ retsel
+ (list sel))))
+ (t
+ (list sel))))))
+ (t
+ (list (tin-locate cvs-cookie-handle (point))))))
+
+;;----------
+(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))
+ (string= (cvs-fileinfo->dir fileinfo) dir)))
+
+;;----------
+(defun cvs-dir-empty-p (tin)
+ "Return non-nil if TIN is a directory that is empty.
+Args: CVS-BUF TIN."
+
+ (and (eq (cvs-fileinfo->type (tin-cookie cvs-cookie-handle tin)) 'DIRCHANGE)
+ (or (not (tin-next cvs-cookie-handle tin))
+ (eq (cvs-fileinfo->type
+ (tin-cookie cvs-cookie-handle
+ (tin-next cvs-cookie-handle tin)))
+ 'DIRCHANGE))))
+
+;;----------
+(defun cvs-mode-revert-updated-buffers ()
+ "Revert any buffers that are UPDATED, PATCHED, MERGED or CONFLICT."
+
+ (interactive)
+ (cookie-map (function cvs-revert-fileinfo) cvs-cookie-handle))
+
+;;----------
+(defun cvs-revert-fileinfo (fileinfo)
+ "Revert the buffer that holds the file in FILEINFO if it has changed,
+and if the type is UPDATED, PATCHED, MERGED or CONFLICT."
+
+ (let* ((type (cvs-fileinfo->type fileinfo))
+ (file (cvs-fileinfo->full-path fileinfo))
+ (buffer (get-file-buffer file)))
+ ;; For a revert to happen...
+ (cond
+ ((and
+ ;; ...the type must be one that justifies a revert...
+ (or (eq type 'UPDATED)
+ (eq type 'PATCHED)
+ (eq type 'MERGED)
+ (eq type 'CONFLICT))
+ ;; ...and the user must be editing the file...
+ buffer)
+ (save-excursion
+ (set-buffer buffer)
+ (cond
+ ((buffer-modified-p)
+ (error "%s: edited since last cvs-update."
+ (buffer-file-name)))
+ ;; Go ahead and revert the file.
+ (t (revert-buffer 'dont-use-auto-save-file 'dont-ask))))))))
+
+;;----------
+(defun cvs-mode-remove-handled ()
+ "Remove all lines that are handled.
+Empty directories are removed."
+
+ (interactive)
+ ;; Pass one: remove files that are handled.
+ (collection-filter-cookies cvs-cookie-handle
+ (function
+ (lambda (fileinfo)
+ (not (cvs-fileinfo->handled fileinfo)))))
+ ;; Pass two: remove empty directories.
+ (if cvs-auto-remove-handled-directories
+ (cvs-remove-empty-directories)))
+
+;;----------
+(defun cvs-remove-empty-directories ()
+ "Remove empty directories in the *cvs* buffer."
+
+ (collection-filter-tins cvs-cookie-handle
+ (function
+ (lambda (tin)
+ (not (cvs-dir-empty-p tin))))))
+
+;;----------
+(defun cvs-mode-mark (pos)
+ "Mark a fileinfo.
+Args: POS.
+
+If the fileinfo is a directory, all the contents of that directory are marked
+instead. A directory can never be marked. POS is a buffer position."
+
+ (interactive "d")
+ (let* ((tin (tin-locate cvs-cookie-handle pos))
+ (sel (tin-cookie cvs-cookie-handle tin)))
+ (cond
+ ;; Does POS point to a directory? If so, mark all files in that directory.
+ ((eq (cvs-fileinfo->type sel) 'DIRCHANGE)
+ (cookie-map
+ (function (lambda (f dir)
+ (cond
+ ((cvs-dir-member-p f dir)
+ (cvs-set-fileinfo->marked f t)
+ t)))) ; Tell cookie to redisplay this cookie.
+ cvs-cookie-handle
+ (cvs-fileinfo->dir sel)))
+ (t
+ (cvs-set-fileinfo->marked sel t)
+ (tin-invalidate cvs-cookie-handle tin)
+ (tin-goto-next cvs-cookie-handle pos 1)))))
+
+;;----------
+(defun cvs-committable (tin)
+ "Check if the TIN is committable.
+It is committable if it
+ a) is not handled and
+ b) is either MODIFIED, ADDED, REMOVED, MERGED or CONFLICT."
+
+ (let* ((fileinfo (tin-cookie cvs-cookie-handle tin))
+ (type (cvs-fileinfo->type fileinfo)))
+ (and (not (cvs-fileinfo->handled fileinfo))
+ (or (eq type 'MODIFIED)
+ (eq type 'ADDED)
+ (eq type 'REMOVED)
+ (eq type 'MERGED)
+ (eq type 'CONFLICT)))))
+
+;;----------
+(defun cvs-mode-commit ()
+ "Check in all marked files, or the current file.
+The user will be asked for a log message in a buffer.
+If cvs-erase-input-buffer is non-nil that buffer will be erased.
+Otherwise mark and point will be set around the entire contents of the
+buffer so that it is easy to kill the contents of the buffer with \\[kill-region]."
+
+ (interactive)
+ (let* ((cvs-buf (current-buffer))
+ (marked (cvs-filter (function cvs-committable)
+ (cvs-get-marked))))
+ (if (null marked)
+ (error "Nothing to commit!")
+ (pop-to-buffer (get-buffer-create cvs-commit-prompt-buffer))
+ (goto-char (point-min))
+
+ (if cvs-erase-input-buffer
+ (erase-buffer)
+ (push-mark (point-max)))
+ (cvs-edit-mode)
+ (make-local-variable 'cvs-commit-list)
+ (setq cvs-commit-list marked)
+ (message "Press C-c C-c when you are done editing."))))
+
+;;----------
+(defun cvs-edit-done ()
+ "Commit the files to the repository."
+
+ (interactive)
+ (if (null cvs-commit-list)
+ (error "You have already committed the files"))
+ (if (and (> (point-max) 1)
+ (/= (char-after (1- (point-max))) ?\n)
+ (or (eq cvs-commit-buffer-require-final-newline t)
+ (and cvs-commit-buffer-require-final-newline
+ (yes-or-no-p
+ (format "Buffer %s does not end in newline. Add one? "
+ (buffer-name))))))
+ (save-excursion
+ (goto-char (point-max))
+ (insert ?\n)))
+ (save-some-buffers)
+ (let ((cc-list cvs-commit-list)
+ (cc-buffer (get-buffer cvs-buffer-name))
+ (msg-buffer (current-buffer))
+ (msg (buffer-substring (point-min) (point-max))))
+ (pop-to-buffer cc-buffer)
+ (bury-buffer msg-buffer)
+ (cvs-use-temp-buffer)
+ (message "Committing...")
+ (if (cvs-execute-list cc-list cvs-program
+ (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "commit" "-m" msg)
+ (list "commit" "-m" msg))
+ "Committing %s...")
+ (error "Something went wrong. Check the %s buffer carefully."
+ cvs-temp-buffer-name))
+ ;; FIXME: don't do any of this if the commit fails.
+ (let ((ccl cc-list))
+ (while ccl
+ (cvs-after-commit-function (tin-cookie cvs-cookie-handle (car ccl)))
+ (setq ccl (cdr ccl))))
+ (apply 'tin-invalidate cvs-cookie-handle cc-list)
+ (set-buffer msg-buffer)
+ (setq cvs-commit-list nil)
+ (set-buffer cc-buffer)
+ (if cvs-auto-remove-handled
+ (cvs-mode-remove-handled)))
+
+ (message "Committing... Done."))
+
+;;----------
+(defun cvs-after-commit-function (fileinfo)
+ "Do everything that needs to be done when FILEINFO has been committed.
+The fileinfo->handle is set, and if the buffer is present it is reverted."
+
+ (cvs-set-fileinfo->handled fileinfo t)
+ (if cvs-auto-revert-after-commit
+ (let* ((file (cvs-fileinfo->full-path fileinfo))
+ (buffer (get-file-buffer file)))
+ ;; For a revert to happen...
+ (if buffer
+ ;; ...the user must be editing the file...
+ (save-excursion
+ (set-buffer buffer)
+ (if (not (buffer-modified-p))
+ ;; ...but it must be unmodified.
+ (revert-buffer 'dont-use-auto-save-file 'dont-ask)))))))
+
+;;----------
+(defun cvs-execute-list (tin-list program constant-args &optional message-fmt)
+ "Run PROGRAM on all elements on TIN-LIST.
+Args: TIN-LIST PROGRAM CONSTANT-ARGS.
+
+The PROGRAM will be called with pwd set to the directory the files reside
+in. CONSTANT-ARGS should be a list of strings. The arguments given to the
+program will be CONSTANT-ARGS followed by all the files (from TIN-LIST) that
+resides in that directory. If the files in TIN-LIST resides in different
+directories the PROGRAM will be run once for each directory (if all files in
+the same directory appears after each other).
+
+Any output from PROGRAM will be inserted in the current buffer.
+
+This function return nil if all went well, or the numerical exit status or a
+signal name as a string. Note that PROGRAM might be called several times. This
+will return non-nil if something goes wrong, but there is no way to know which
+process that failed.
+
+If MESSAGE-FMT is not nil, then message is called to display progress with
+MESSAGE-FMT as the string. MESSAGE-FMT should contain one %s for the arg-list
+being passed to PROGRAM."
+
+ ;; FIXME: something seems wrong with the error checking here....
+
+ (let ((exitstatus nil))
+ (while tin-list
+ (let ((current-dir (cvs-fileinfo->dir (tin-cookie cvs-cookie-handle
+ (car tin-list))))
+ arg-list
+ arg-str)
+
+ ;; Collect all marked files in this directory.
+
+ (while (and tin-list
+ (string= current-dir
+ (cvs-fileinfo->dir (tin-cookie cvs-cookie-handle
+ (car tin-list)))))
+ (setq arg-list
+ (cons (cvs-fileinfo->file-name
+ (tin-cookie cvs-cookie-handle (car tin-list)))
+ arg-list))
+ (setq tin-list (cdr tin-list)))
+
+ (setq arg-list (nreverse arg-list))
+
+ ;; Execute the command on all the files that were collected.
+
+ (if message-fmt
+ (message message-fmt
+ (mapconcat 'cvs-quote-multiword-string
+ arg-list
+ " ")))
+ (setq default-directory (file-name-as-directory current-dir))
+ (insert (format "=== cd %s\n" default-directory))
+ (insert (format "=== %s %s\n\n"
+ program
+ (mapconcat 'cvs-quote-multiword-string
+ (nconc (copy-sequence constant-args)
+ arg-list)
+ " ")))
+ (let ((res (apply 'call-process program nil t t
+ (nconc (copy-sequence constant-args) arg-list))))
+ ;; Remember the first, or highest, exitstatus.
+ (if (and (not (and (integerp res) (zerop res)))
+ (or (null exitstatus)
+ (and (integerp exitstatus) (= 1 exitstatus))))
+ (setq exitstatus res)))
+ (goto-char (point-max))
+ (if message-fmt
+ (message message-fmt
+ (mapconcat 'cvs-quote-multiword-string
+ (nconc (copy-sequence arg-list) '("Done."))
+ " ")))
+ exitstatus))))
+
+;;----------
+;;;; +++ not currently used!
+(defun cvs-execute-single-file-list (tin-list extractor program constant-args
+ &optional cleanup message-fmt)
+ "Run PROGRAM on all elements on TIN-LIST.
+Args: TIN-LIST EXTRACTOR PROGRAM CONSTANT-ARGS &optional CLEANUP.
+
+The PROGRAM will be called with pwd set to the directory the files
+reside in. CONSTANT-ARGS is a list of strings to pass as arguments to
+PROGRAM. The arguments given to the program will be CONSTANT-ARGS
+followed by the list that EXTRACTOR returns.
+
+EXTRACTOR will be called once for each file on TIN-LIST. It is given
+one argument, the cvs-fileinfo. It can return t, which means ignore
+this file, or a list of arguments to send to the program.
+
+If CLEANUP is not nil, the filenames returned by EXTRACTOR are deleted.
+
+If MESSAGE-FMT is not nil, then message is called to display progress with
+MESSAGE-FMT as the string. MESSAGE-FMT should contain one %s for the arg-list
+being passed to PROGRAM."
+
+ (while tin-list
+ (let ((current-dir (file-name-as-directory
+ (cvs-fileinfo->dir
+ (tin-cookie cvs-cookie-handle
+ (car tin-list)))))
+ (arg-list
+ (funcall extractor
+ (tin-cookie cvs-cookie-handle (car tin-list)))))
+
+ ;; Execute the command unless extractor returned t.
+
+ (if (eq arg-list t)
+ nil
+ (setq default-directory current-dir)
+ (insert (format "=== cd %s\n" default-directory))
+ (insert (format "=== %s %s\n\n"
+ program
+ (mapconcat 'cvs-quote-multiword-string
+ (nconc (copy-sequence constant-args)
+ arg-list)
+ " ")))
+ (if message-fmt
+ (message message-fmt (mapconcat 'cvs-quote-multiword-string
+ arg-list
+ " ")))
+ (apply 'call-process program nil t t
+ (nconc (copy-sequence constant-args) arg-list))
+ (goto-char (point-max))
+ (if message-fmt
+ (message message-fmt (mapconcat 'cvs-quote-multiword-string
+ (nconc arg-list '("Done."))
+ " ")))
+ (if cleanup
+ (while arg-list
+;;;; (kill-buffer ?????)
+ (delete-file (car arg-list))
+ (setq arg-list (cdr arg-list))))))
+ (setq tin-list (cdr tin-list))))
+
+;;----------
+(defun cvs-edit-mode ()
+ "\\<cvs-edit-mode-map>Mode for editing cvs log messages.
+Commands:
+\\[cvs-edit-done] checks in the file when you are ready.
+This mode is based on fundamental mode."
+
+ (interactive)
+ (use-local-map cvs-edit-mode-map)
+ (setq major-mode 'cvs-edit-mode)
+ (setq mode-name "CVS Log")
+ (auto-fill-mode 1))
+
+;;----------
+(if cvs-edit-mode-map
+ nil
+ (setq cvs-edit-mode-map (make-sparse-keymap))
+ (define-prefix-command 'cvs-edit-mode-control-c-prefix)
+ (define-key cvs-edit-mode-map "\C-c" 'cvs-edit-mode-control-c-prefix)
+ (define-key cvs-edit-mode-map "\C-c\C-c" 'cvs-edit-done))
+
+;;----------
+(defun cvs-diffable (tins)
+ "Return a list of all tins on TINS that it makes sense to run
+``cvs diff'' on."
+
+ ;; +++ There is an unnecessary (nreverse) here. Get the list the
+ ;; other way around instead!
+ (let ((result nil))
+ (while tins
+ (let ((type (cvs-fileinfo->type
+ (tin-cookie cvs-cookie-handle (car tins)))))
+ (if (or (eq type 'MODIFIED)
+ (eq type 'UPDATED)
+ (eq type 'PATCHED)
+ (eq type 'MERGED)
+ (eq type 'CONFLICT)
+ (eq type 'REMOVED) ;+++Does this line make sense?
+ (eq type 'ADDED)) ;+++Does this line make sense?
+ (setq result (cons (car tins) result)))
+ (setq tins (cdr tins))))
+ (nreverse result)))
+
+;;----------
+(defun cvs-mode-diff-cvs (&optional ignore-marks)
+ "Diff the selected files against the head revisions in the repository.
+
+If the variable cvs-diff-ignore-marks is non-nil any marked files will not be
+considered to be selected. An optional prefix argument will invert the
+influence from cvs-diff-ignore-marks.
+
+The flags in the variable cvs-diff-flags will be passed to ``cvs diff''.
+
+The resulting diffs are placed in the cvs-fileinfo->cvs-diff-buffer."
+
+ (interactive "P")
+ (if (not (listp cvs-diff-flags))
+ (error "cvs-diff-flags should be set using cvs-set-diff-flags."))
+ (save-some-buffers)
+ (message "cvsdiffing...")
+ (let ((marked-file-list (cvs-diffable
+ (cvs-get-marked
+ (or (and ignore-marks (not cvs-diff-ignore-marks))
+ (and (not ignore-marks) cvs-diff-ignore-marks))))))
+ (while marked-file-list
+ (let ((fileinfo-to-diff (tin-cookie cvs-cookie-handle
+ (car marked-file-list)))
+ (local-def-directory (file-name-as-directory
+ (cvs-fileinfo->dir
+ (tin-cookie cvs-cookie-handle
+ (car marked-file-list))))))
+ (message "cvsdiffing %s..."
+ (cvs-fileinfo->file-name fileinfo-to-diff))
+
+ ;; FIXME: this seems messy to test and set buffer name at this point....
+ (if (not (cvs-fileinfo->cvs-diff-buffer fileinfo-to-diff))
+ (cvs-set-fileinfo->cvs-diff-buffer fileinfo-to-diff
+ (concat "*cvs-diff-"
+ (cvs-fileinfo->file-name
+ fileinfo-to-diff)
+ "-in-"
+ local-def-directory
+ "*")))
+ (display-buffer (get-buffer-create
+ (cvs-fileinfo->cvs-diff-buffer fileinfo-to-diff)))
+ (set-buffer (cvs-fileinfo->cvs-diff-buffer fileinfo-to-diff))
+ (setq buffer-read-only nil)
+ (setq default-directory local-def-directory)
+ (erase-buffer)
+ (insert (format "=== cd %s\n" default-directory))
+ (insert (format "=== cvs %s\n\n"
+ (mapconcat 'cvs-quote-multiword-string
+ (nconc (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "diff")
+ '("diff"))
+ (copy-sequence cvs-diff-flags)
+ (list (cvs-fileinfo->file-name
+ fileinfo-to-diff)))
+ " ")))
+ (if (apply 'call-process cvs-program nil t t
+ (nconc (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "diff")
+ '("diff"))
+ (copy-sequence cvs-diff-flags)
+ (list (cvs-fileinfo->file-name fileinfo-to-diff))))
+ (message "cvsdiffing %s... Done."
+ (cvs-fileinfo->file-name fileinfo-to-diff))
+ (message "cvsdiffing %s... No differences found."
+ (cvs-fileinfo->file-name fileinfo-to-diff)))
+ (goto-char (point-max))
+ (setq marked-file-list (cdr marked-file-list)))))
+ (message "cvsdiffing... Done."))
+
+;;----------
+(defun cvs-mode-diff-backup (&optional ignore-marks)
+ "Diff the files against the backup file.
+This command can be used on files that are marked with \"Merged\"
+or \"Conflict\" in the *cvs* buffer.
+
+If the variable cvs-diff-ignore-marks is non-nil any marked files will
+not be considered to be selected. An optional prefix argument will
+invert the influence from cvs-diff-ignore-marks.
+
+The flags in cvs-diff-flags will be passed to ``diff''.
+
+The resulting diffs are placed in the cvs-fileinfo->backup-diff-buffer."
+
+ (interactive "P")
+ (if (not (listp cvs-diff-flags))
+ (error "cvs-diff-flags should be set using cvs-set-diff-flags."))
+ (save-some-buffers)
+ (let ((marked-file-list (cvs-filter
+ (function cvs-backup-diffable)
+ (cvs-get-marked
+ (or
+ (and ignore-marks (not cvs-diff-ignore-marks))
+ (and (not ignore-marks) cvs-diff-ignore-marks))))))
+ (if (null marked-file-list)
+ (error "No ``Conflict'' or ``Merged'' file selected!"))
+ (message "backup diff...")
+ (while marked-file-list
+ (let ((fileinfo-to-diff (tin-cookie cvs-cookie-handle
+ (car marked-file-list)))
+ (local-def-directory (file-name-as-directory
+ (cvs-fileinfo->dir
+ (tin-cookie cvs-cookie-handle
+ (car marked-file-list)))))
+ (backup-temp-files (cvs-diff-backup-extractor
+ (tin-cookie cvs-cookie-handle
+ (car marked-file-list)))))
+ (message "backup diff %s..."
+ (cvs-fileinfo->file-name fileinfo-to-diff))
+
+ ;; FIXME: this seems messy to test and set buffer name at this point....
+ (if (not (cvs-fileinfo->backup-diff-buffer fileinfo-to-diff))
+ (cvs-set-fileinfo->backup-diff-buffer fileinfo-to-diff
+ (concat "*cvs-diff-"
+ (cvs-fileinfo->backup-file
+ fileinfo-to-diff)
+ "-to-"
+ (cvs-fileinfo->file-name
+ fileinfo-to-diff)
+ "-in"
+ local-def-directory
+ "*")))
+ (display-buffer (get-buffer-create
+ (cvs-fileinfo->backup-diff-buffer fileinfo-to-diff)))
+ (set-buffer (cvs-fileinfo->backup-diff-buffer fileinfo-to-diff))
+ (setq buffer-read-only nil)
+ (setq default-directory local-def-directory)
+ (erase-buffer)
+ (insert (format "=== cd %s\n" default-directory))
+ (insert (format "=== %s %s\n\n"
+ cvs-diff-program
+ (mapconcat 'cvs-quote-multiword-string
+ (nconc (copy-sequence cvs-diff-flags)
+ backup-temp-files)
+ " ")))
+ (apply 'call-process cvs-diff-program nil t t
+ (nconc (copy-sequence cvs-diff-flags) backup-temp-files))
+ (goto-char (point-max))
+ (message "backup diff %s... Done."
+ (cvs-fileinfo->file-name fileinfo-to-diff))
+ (setq marked-file-list (cdr marked-file-list)))))
+ (message "backup diff... Done."))
+
+;;----------
+(defun cvs-mode-diff-vendor (&optional ignore-marks)
+ "Diff the revisions merged into the current file. I.e. show what changes
+were merged in.
+
+This command can be used on files that are marked with \"Merged\"
+or \"Conflict\" in the *cvs* buffer.
+
+If the variable cvs-diff-ignore-marks is non-nil any marked files will
+not be considered to be selected. An optional prefix argument will
+invert the influence from cvs-diff-ignore-marks.
+
+The flags in cvs-diff-flags will be passed to ``diff''.
+
+The resulting diffs are placed in the cvs-fileinfo->vendor-diff-buffer."
+
+ (interactive "P")
+ (if (not (listp cvs-diff-flags))
+ (error "cvs-diff-flags should be set using cvs-set-diff-flags."))
+ (save-some-buffers)
+ (let ((marked-file-list (cvs-filter
+ (function cvs-vendor-diffable)
+ (cvs-get-marked
+ (or
+ (and ignore-marks (not cvs-diff-ignore-marks))
+ (and (not ignore-marks) cvs-diff-ignore-marks))))))
+ (if (null marked-file-list)
+ (error "No ``Conflict'' or ``Merged'' file selected!"))
+ (message "vendor diff...")
+ (while marked-file-list
+ (let ((fileinfo-to-diff (tin-cookie cvs-cookie-handle
+ (car marked-file-list)))
+ (local-def-directory (file-name-as-directory
+ (cvs-fileinfo->dir
+ (tin-cookie cvs-cookie-handle
+ (car marked-file-list)))))
+ (vendor-temp-files (cvs-diff-vendor-extractor
+ (tin-cookie cvs-cookie-handle
+ (car marked-file-list)))))
+ (message "vendor diff %s..."
+ (cvs-fileinfo->file-name fileinfo-to-diff))
+ (if (not (cvs-fileinfo->vendor-diff-buffer fileinfo-to-diff))
+ (cvs-set-fileinfo->vendor-diff-buffer fileinfo-to-diff
+ (concat "*cvs-diff-"
+ (cvs-fileinfo->file-name
+ fileinfo-to-diff)
+ "-of-"
+ (cvs-fileinfo->base-revision
+ fileinfo-to-diff)
+ "-to-"
+ (cvs-fileinfo->head-revision
+ fileinfo-to-diff)
+ "-in-"
+ local-def-directory
+ "*")))
+ (display-buffer (get-buffer-create
+ (cvs-fileinfo->vendor-diff-buffer fileinfo-to-diff)))
+ (set-buffer (cvs-fileinfo->vendor-diff-buffer fileinfo-to-diff))
+ (setq buffer-read-only nil)
+ (setq default-directory local-def-directory)
+ (erase-buffer)
+ (insert (format "=== cd %s\n" default-directory))
+ (insert (format "=== %s %s\n\n"
+ cvs-diff-program
+ (mapconcat 'cvs-quote-multiword-string
+ (nconc (copy-sequence cvs-diff-flags)
+ vendor-temp-files)
+ " ")))
+ (apply 'call-process cvs-diff-program nil t t
+ (nconc (copy-sequence cvs-diff-flags) vendor-temp-files))
+ (goto-char (point-max))
+ (message "vendor diff %s... Done."
+ (cvs-fileinfo->file-name fileinfo-to-diff))
+ (while vendor-temp-files
+ (cvs-kill-buffer-visiting (car vendor-temp-files))
+ (delete-file (car vendor-temp-files))
+ (setq vendor-temp-files (cdr vendor-temp-files)))
+ (setq marked-file-list (cdr marked-file-list)))))
+ (message "vendor diff... Done."))
+
+;;----------
+(defun cvs-backup-diffable (tin)
+ "Check if the TIN is backup-diffable.
+It must have a backup file to be diffable."
+
+ (file-readable-p
+ (cvs-fileinfo->backup-file (tin-cookie cvs-cookie-handle tin))))
+
+;;----------
+(defun cvs-vendor-diffable (tin)
+ "Check if the TIN is vendor-diffable.
+It must have head and base revision info to be diffable."
+
+ (and
+ (cvs-fileinfo->base-revision (tin-cookie cvs-cookie-handle tin))
+ (cvs-fileinfo->head-revision (tin-cookie cvs-cookie-handle tin))))
+
+;;----------
+(defun cvs-diff-backup-extractor (fileinfo)
+ "Return the filename and the name of the backup file as a list.
+Signal an error if there is no backup file."
+
+ (if (not (file-readable-p (cvs-fileinfo->backup-file fileinfo)))
+ (error "%s has no backup file."
+ (concat
+ (file-name-as-directory (cvs-fileinfo->dir fileinfo))
+ (cvs-fileinfo->file-name fileinfo))))
+ (list (cvs-fileinfo->backup-file fileinfo)
+ (cvs-fileinfo->file-name fileinfo)))
+
+;;----------
+(defun cvs-diff-vendor-extractor (fileinfo)
+ "Retrieve and return the filenames of the vendor branch revisions as a list.
+Signal an error if there is no info for the vendor revisions."
+
+ (list (cvs-retrieve-revision-to-tmpfile fileinfo
+ (cvs-fileinfo->base-revision
+ fileinfo))
+ (cvs-retrieve-revision-to-tmpfile fileinfo
+ (cvs-fileinfo->head-revision
+ fileinfo))))
+
+;;----------
+(defun cvs-mode-find-file-other-window (pos)
+ "Select a buffer containing the file in another window.
+Args: POS."
+
+ (interactive "d")
+ (let ((tin (tin-locate cvs-cookie-handle pos)))
+ (if tin
+ (let ((type (cvs-fileinfo->type (tin-cookie cvs-cookie-handle tin))))
+ (cond
+ ((or (eq type 'REMOVED)
+ (eq type 'CVS-REMOVED))
+ (error "Can't visit a removed file."))
+ ((eq type 'DIRCHANGE)
+ (let ((obuf (current-buffer))
+ (odir default-directory))
+ (setq default-directory
+ (file-name-as-directory
+ (cvs-fileinfo->dir
+ (tin-cookie cvs-cookie-handle tin))))
+ (dired-other-window default-directory)
+ (set-buffer obuf)
+ (setq default-directory odir)))
+ (t
+ (find-file-other-window (cvs-full-path tin)))))
+ (error "There is no file to find."))))
+
+;;----------
+(defun cvs-fileinfo->full-path (fileinfo)
+ "Return the full path for the file that is described in FILEINFO."
+
+ (concat
+ (file-name-as-directory
+ (cvs-fileinfo->dir fileinfo))
+ (cvs-fileinfo->file-name fileinfo)))
+
+;;----------
+(defun cvs-full-path (tin)
+ "Return the full path for the file that is described in TIN."
+
+ (cvs-fileinfo->full-path (tin-cookie cvs-cookie-handle tin)))
+
+;;----------
+(defun cvs-mode-find-file (pos)
+ "Select a buffer containing the file in another window.
+Args: POS."
+
+ (interactive "d")
+ (let* ((cvs-buf (current-buffer))
+ (tin (tin-locate cvs-cookie-handle pos)))
+ (if tin
+ (let* ((fileinfo (tin-cookie cvs-cookie-handle tin))
+ (type (cvs-fileinfo->type fileinfo)))
+ (cond
+ ((or (eq type 'REMOVED)
+ (eq type 'CVS-REMOVED))
+ (error "Can't visit a removed file."))
+ ((eq type 'DIRCHANGE)
+ (let ((odir default-directory))
+ (setq default-directory
+ (file-name-as-directory (cvs-fileinfo->dir fileinfo)))
+ (dired default-directory)
+ (set-buffer cvs-buf)
+ (setq default-directory odir)))
+ (t
+ (find-file (cvs-full-path tin)))))
+ (error "There is no file to find."))))
+
+;;----------
+(defun cvs-mode-mark-all-files ()
+ "Mark all files.
+Directories are not marked."
+
+ (interactive)
+ (cookie-map (function (lambda (cookie)
+ (cond
+ ((not (eq (cvs-fileinfo->type cookie) 'DIRCHANGE))
+ (cvs-set-fileinfo->marked cookie t)
+ t))))
+ cvs-cookie-handle))
+
+;;----------
+(defun cvs-mode-unmark (pos)
+ "Unmark a fileinfo.
+Args: POS."
+
+ (interactive "d")
+ (let* ((tin (tin-locate cvs-cookie-handle pos))
+ (sel (tin-cookie cvs-cookie-handle tin)))
+ (cond
+ ((eq (cvs-fileinfo->type sel) 'DIRCHANGE)
+ (cookie-map
+ (function (lambda (f dir)
+ (cond
+ ((cvs-dir-member-p f dir)
+ (cvs-set-fileinfo->marked f nil)
+ t))))
+ cvs-cookie-handle
+ (cvs-fileinfo->dir sel)))
+ (t
+ (cvs-set-fileinfo->marked sel nil)
+ (tin-invalidate cvs-cookie-handle tin)
+ (tin-goto-next cvs-cookie-handle pos 1)))))
+
+;;----------
+(defun cvs-mode-unmark-all-files ()
+ "Unmark all files.
+Directories are also unmarked, but that doesn't matter, since
+they should always be unmarked."
+
+ (interactive)
+ (cookie-map (function (lambda (cookie)
+ (cvs-set-fileinfo->marked cookie nil)
+ t))
+ cvs-cookie-handle))
+
+;;----------
+(defun cvs-do-removal (tins)
+ "Remove files.
+Args: TINS.
+
+TINS is a list of tins that the user wants to delete. The files are deleted.
+If the type of the tin is 'UNKNOWN or 'UNKNOWN-DIR the tin is removed from the
+buffer. If it is anything else the file is added to a list that should be `cvs
+remove'd and the tin is changed to be of type 'REMOVED.
+
+Returns a list of tins files that should be `cvs remove'd."
+
+ (cvs-use-temp-buffer)
+ (mapcar 'cvs-insert-full-path tins)
+ (cond
+ ((and tins (yes-or-no-p (format "Delete %d files? " (length tins))))
+ (let (files-to-remove)
+ (while tins
+ (let* ((tin (car tins))
+ (fileinfo (tin-cookie cvs-cookie-handle tin))
+ (filepath (cvs-full-path tin))
+ (type (cvs-fileinfo->type fileinfo)))
+ (if (or (eq type 'REMOVED)
+ (eq type 'CVS-REMOVED))
+ nil
+ ;; if it doesn't exist, as a file or directory, ignore it
+ (cond ((file-directory-p filepath)
+ (call-process cvs-rmdir-program nil nil nil filepath))
+ ((file-exists-p filepath)
+ (delete-file filepath)))
+ (if (or (eq type 'UNKNOWN)
+ (eq type 'UNKNOWN-DIR)
+ (eq type 'MOVE-AWAY))
+ (tin-delete cvs-cookie-handle tin)
+ (setq files-to-remove (cons tin files-to-remove))
+ (cvs-set-fileinfo->type fileinfo 'REMOVED)
+ (cvs-set-fileinfo->handled fileinfo nil)
+ (tin-invalidate cvs-cookie-handle tin))))
+ (setq tins (cdr tins)))
+ files-to-remove))
+ (t nil)))
+
+;;----------
+(defun cvs-mode-remove-file ()
+ "Remove all marked files."
+
+ (interactive)
+ (let ((files-to-remove (cvs-do-removal (cvs-get-marked))))
+ (if (null files-to-remove)
+ nil
+ (cvs-use-temp-buffer)
+ (message "removing from repository...")
+ (if (cvs-execute-list files-to-remove cvs-program
+ (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "remove")
+ '("remove"))
+ "removing %s from repository...")
+ (error "CVS exited with non-zero exit status.")
+ (message "removing from repository... Done.")))))
+
+;;----------
+(defun cvs-mode-undo-local-changes ()
+ "Undo local changes to all marked files.
+The file is removed and `cvs update FILE' is run."
+
+ (interactive)
+ (let ((tins-to-undo (cvs-get-marked)))
+ (cvs-use-temp-buffer)
+ (mapcar 'cvs-insert-full-path tins-to-undo)
+ (cond
+ ((and tins-to-undo (yes-or-no-p (format "Undo changes to %d files? "
+ (length tins-to-undo))))
+ (let (files-to-update)
+ (while tins-to-undo
+ (let* ((tin (car tins-to-undo))
+ (fileinfo (tin-cookie cvs-cookie-handle tin))
+ (type (cvs-fileinfo->type fileinfo)))
+ (cond
+ ((or
+ (eq type 'UPDATED)
+ (eq type 'PATCHED)
+ (eq type 'MODIFIED)
+ (eq type 'MERGED)
+ (eq type 'CONFLICT)
+ (eq type 'CVS-REMOVED)
+ (eq type 'REM-CONFLICT)
+ (eq type 'MOVE-AWAY)
+ (eq type 'REMOVED))
+ (if (not (eq type 'REMOVED))
+ (delete-file (cvs-full-path tin)))
+ (setq files-to-update (cons tin files-to-update))
+ (cvs-set-fileinfo->type fileinfo 'UPDATED)
+ (cvs-set-fileinfo->handled fileinfo t)
+ (tin-invalidate cvs-cookie-handle tin))
+
+ ((eq type 'MOD-CONFLICT)
+ (error "Use cvs-mode-add instead on %s."
+ (cvs-fileinfo->file-name fileinfo)))
+
+ ((eq type 'REM-CONFLICT)
+ (error "Can't deal with a file you have removed and recreated."))
+
+ ((eq type 'DIRCHANGE)
+ (error "Undo on directories not supported (yet)."))
+
+ ((eq type 'ADDED)
+ (error "There is no old revision to get for %s"
+ (cvs-fileinfo->file-name fileinfo)))
+ (t (error "cvs-mode-undo-local-changes: can't handle an %s"
+ type)))
+
+ (setq tins-to-undo (cdr tins-to-undo))))
+ (cvs-use-temp-buffer)
+ (message "Re-getting files from repository...")
+ (if (cvs-execute-list files-to-update cvs-program
+ (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "update")
+ '("update"))
+ "Re-getting %s from repository...")
+ (error "CVS exited with non-zero exit status.")
+ (message "Re-getting files from repository... Done.")))))))
+
+;;----------
+(defun cvs-mode-acknowledge ()
+ "Remove all marked files from the buffer."
+
+ (interactive)
+ (mapcar (function (lambda (tin)
+ (tin-delete cvs-cookie-handle tin)))
+ (cvs-get-marked)))
+
+;;----------
+(defun cvs-mode-unmark-up (pos)
+ "Unmark the file on the previous line.
+Takes one argument POS, a buffer position."
+
+ (interactive "d")
+ (let ((tin (tin-goto-previous cvs-cookie-handle pos 1)))
+ (cond
+ (tin
+ (cvs-set-fileinfo->marked (tin-cookie cvs-cookie-handle tin)
+ nil)
+ (tin-invalidate cvs-cookie-handle tin)))))
+
+;;----------
+(defun cvs-mode-previous-line (arg)
+ "Go to the previous line.
+If a prefix argument is given, move by that many lines."
+
+ (interactive "p")
+ (tin-goto-previous cvs-cookie-handle (point) arg))
+
+;;----------
+(defun cvs-mode-next-line (arg)
+ "Go to the next line.
+If a prefix argument is given, move by that many lines."
+
+ (interactive "p")
+ (tin-goto-next cvs-cookie-handle (point) arg))
+
+;;----------
+(defun cvs-add-file-update-buffer (tin)
+ "Sub-function to cvs-mode-add. Internal use only. Update the display. Return
+non-nil if `cvs add' should be called on this file.
+Args: TIN.
+
+Returns 'DIR, 'ADD, 'ADD-DIR, or 'RESURRECT."
+
+ (let ((fileinfo (tin-cookie cvs-cookie-handle tin)))
+ (cond
+ ((eq (cvs-fileinfo->type fileinfo) 'UNKNOWN-DIR)
+ (cvs-set-fileinfo->full-log fileinfo "new directory added with cvs-mode-add")
+ 'ADD-DIR)
+ ((eq (cvs-fileinfo->type fileinfo) 'UNKNOWN)
+ (cvs-set-fileinfo->type fileinfo 'ADDED)
+ (cvs-set-fileinfo->full-log fileinfo "new file added with cvs-mode-add")
+ (tin-invalidate cvs-cookie-handle tin)
+ 'ADD)
+ ((eq (cvs-fileinfo->type fileinfo) 'REMOVED)
+ (cvs-set-fileinfo->type fileinfo 'UPDATED)
+ (cvs-set-fileinfo->full-log fileinfo "file resurrected with cvs-mode-add")
+ (cvs-set-fileinfo->handled fileinfo t)
+ (tin-invalidate cvs-cookie-handle tin)
+ 'RESURRECT))))
+
+;;----------
+(defun cvs-add-sub (cvs-buf candidates)
+ "Internal use only.
+Args: CVS-BUF CANDIDATES.
+
+CANDIDATES is a list of tins. Updates the CVS-BUF and returns a list of lists.
+The first list is unknown tins that shall be `cvs add -m msg'ed.
+The second list is unknown directory tins that shall be `cvs add -m msg'ed.
+The third list is removed files that shall be `cvs add'ed (resurrected)."
+
+ (let (add add-dir resurrect)
+ (while candidates
+ (let ((type (cvs-add-file-update-buffer (car candidates))))
+ (cond ((eq type 'ADD)
+ (setq add (cons (car candidates) add)))
+ ((eq type 'ADD-DIR)
+ (setq add-dir (cons (car candidates) add-dir)))
+ ((eq type 'RESURRECT)
+ (setq resurrect (cons (car candidates) resurrect)))))
+ (setq candidates (cdr candidates)))
+ (list add add-dir resurrect)))
+
+;;----------
+(defun cvs-mode-add ()
+ "Add marked files to the cvs repository."
+
+ (interactive)
+ (let* ((buf (current-buffer))
+ (marked (cvs-get-marked))
+ (result (cvs-add-sub buf marked))
+ (added (car result))
+ (newdirs (car (cdr result)))
+ (resurrect (car (cdr (cdr result))))
+ (msg (if (or added newdirs)
+ (read-from-minibuffer "Enter description: "))))
+
+ (if (or resurrect (or added newdirs))
+ (cvs-use-temp-buffer))
+
+ (cond (resurrect
+ (message "Resurrecting files from repository...")
+ (if (cvs-execute-list resurrect
+ cvs-program
+ (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "add")
+ '("add"))
+ "Resurrecting %s from repository...")
+ (error "CVS exited with non-zero exit status.")
+ (message "Resurrecting files from repository... Done."))))
+
+ (cond (added
+ (message "Adding new files to repository...")
+ (if (cvs-execute-list added
+ cvs-program
+ (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "add" "-m" msg)
+ (list "add" "-m" msg))
+ "Adding %s to repository...")
+ (error "CVS exited with non-zero exit status.")
+ (message "Adding new files to repository... Done."))))
+
+ (cond (newdirs
+ (message "Adding new directories to repository...")
+ (if (cvs-execute-list newdirs
+ cvs-program
+ (if cvs-cvsroot
+ (list "-d" cvs-cvsroot "add" "-m" msg)
+ (list "add" "-m" msg))
+ "Adding %s to repository...")
+ (error "CVS exited with non-zero exit status.")
+ (while newdirs
+ (let* ((tin (car newdirs))
+ (fileinfo (tin-cookie cvs-cookie-handle tin))
+ (newdir (cvs-fileinfo->file-name fileinfo)))
+ (cvs-set-fileinfo->dir fileinfo
+ (concat (cvs-fileinfo->dir fileinfo)
+ "/"
+ newdir))
+ (cvs-set-fileinfo->type fileinfo 'DIRCHANGE)
+ (cvs-set-fileinfo->file-name fileinfo ".")
+ (tin-invalidate cvs-cookie-handle tin)
+ (setq newdirs (cdr newdirs))))
+ ;; FIXME: this should really run cvs-update-no-prompt on the
+ ;; subdir and insert everthing in the current list.
+ (message "You must re-update to visit the new directories."))))))
+
+;;----------
+(defun cvs-mode-ignore ()
+ "Arrange so that CVS ignores the selected files and directories.
+This command ignores files/dirs that are flagged as `Unknown'."
+
+ (interactive)
+ (mapcar (function (lambda (tin)
+ (let* ((fileinfo (tin-cookie cvs-cookie-handle tin))
+ (type (cvs-fileinfo->type fileinfo)))
+ (cond ((or (eq type 'UNKNOWN)
+ (eq type 'UNKNOWN-DIR))
+ (cvs-append-to-ignore fileinfo)
+ (tin-delete cvs-cookie-handle tin))))))
+ (cvs-get-marked)))
+
+;;----------
+(defun cvs-append-to-ignore (fileinfo)
+ "Append the file in fileinfo to the .cvsignore file"
+
+ (save-window-excursion
+ (set-buffer (find-file-noselect (concat (file-name-as-directory
+ (cvs-fileinfo->dir fileinfo))
+ ".cvsignore")))
+ (goto-char (point-max))
+ (if (not (zerop (current-column)))
+ (insert "\n"))
+ (insert (cvs-fileinfo->file-name fileinfo) "\n")
+ (if cvs-sort-ignore-file
+ (sort-lines nil (point-min) (point-max)))
+ (save-buffer)))
+
+;;----------
+(defun cvs-mode-status ()
+ "Show cvs status for all marked files."
+
+ (interactive)
+ (save-some-buffers)
+ (if (not (listp cvs-status-flags))
+ (error "cvs-status-flags should be set using cvs-set-status-flags."))
+ (let ((marked (cvs-get-marked nil t)))
+ (cvs-use-temp-buffer)
+ (message "Running cvs status ...")
+ (if (cvs-execute-list marked
+ cvs-program
+ (append (if cvs-cvsroot (list "-d" cvs-cvsroot))
+ (list "-Q" "status")
+ cvs-status-flags)
+ "Running cvs -Q status %s...")
+ (error "CVS exited with non-zero exit status.")
+ (message "Running cvs -Q status ... Done."))))
+
+;;----------
+(defun cvs-mode-log ()
+ "Display the cvs log of all selected files."
+
+ (interactive)
+ (if (not (listp cvs-log-flags))
+ (error "cvs-log-flags should be set using cvs-set-log-flags."))
+ (let ((marked (cvs-get-marked nil t)))
+ (cvs-use-temp-buffer)
+ (message "Running cvs log ...")
+ (if (cvs-execute-list marked
+ cvs-program
+ (append (if cvs-cvsroot (list "-d" cvs-cvsroot))
+ (list "log")
+ cvs-log-flags)
+ "Running cvs log %s...")
+ (error "CVS exited with non-zero exit status.")
+ (message "Running cvs log ... Done."))))
+
+;;----------
+(defun cvs-mode-tag ()
+ "Run 'cvs tag' on all selected files."
+
+ (interactive)
+ (if (not (listp cvs-tag-flags))
+ (error "cvs-tag-flags should be set using cvs-set-tag-flags."))
+ (let ((marked (cvs-get-marked nil t))
+ (tag-args (cvs-make-list (read-string "Tag name (and flags): "))))
+ (cvs-use-temp-buffer)
+ (message "Running cvs tag ...")
+ (if (cvs-execute-list marked
+ cvs-program
+ (append (if cvs-cvsroot (list "-d" cvs-cvsroot))
+ (list "tag")
+ cvs-tag-flags
+ tag-args)
+ "Running cvs tag %s...")
+ (error "CVS exited with non-zero exit status.")
+ (message "Running cvs tag ... Done."))))
+
+;;----------
+(defun cvs-mode-rtag ()
+ "Run 'cvs rtag' on all selected files."
+
+ (interactive)
+ (if (not (listp cvs-rtag-flags))
+ (error "cvs-rtag-flags should be set using cvs-set-rtag-flags."))
+ (let ((marked (cvs-get-marked nil t))
+ ;; FIXME: should give selection from the modules file
+ (module-name (read-string "Module name: "))
+ ;; FIXME: should also ask for an existing tag *or* date
+ (rtag-args (cvs-make-list (read-string "Tag name (and flags): "))))
+ (cvs-use-temp-buffer)
+ (message "Running cvs rtag ...")
+ (if (cvs-execute-list marked
+ cvs-program
+ (append (if cvs-cvsroot (list "-d" cvs-cvsroot))
+ (list "rtag")
+ cvs-rtag-flags
+ rtag-args
+ (list module-name))
+ "Running cvs rtag %s...")
+ (error "CVS rtag exited with non-zero exit status.")
+ (message "Running cvs rtag ... Done."))))
+
+;;----------
+(defun cvs-mode-byte-compile-files ()
+ "Run byte-compile-file on all selected files that end in '.el'."
+
+ (interactive)
+ (let ((marked (cvs-get-marked)))
+ (while marked
+ (let ((filename (cvs-full-path (car marked))))
+ (if (string-match "\\.el$" filename)
+ (byte-compile-file filename)))
+ (setq marked (cdr marked)))))
+
+;;----------
+(defun cvs-insert-full-path (tin)
+ "Insert full path to the file described in TIN in the current buffer."
+
+ (insert (format "%s\n" (cvs-full-path tin))))
+
+;;----------
+(defun cvs-mode-add-change-log-entry-other-window (pos)
+ "Add a ChangeLog entry in the ChangeLog of the current directory.
+Args: POS."
+
+ (interactive "d")
+ (let* ((cvs-buf (current-buffer))
+ (odir default-directory)
+ (obfname buffer-file-name)
+ (tin (tin-locate cvs-cookie-handle pos))
+ (fileinfo (tin-cookie cvs-cookie-handle tin))
+ (fname (cvs-fileinfo->file-name fileinfo))
+ (dname (file-name-as-directory (cvs-fileinfo->dir fileinfo))))
+ (setq change-log-default-name nil) ; this rarely correct in 19.28
+ (setq buffer-file-name (cond (fname
+ fname)
+ (t
+ nil)))
+ (setq default-directory (cond (dname
+ dname)
+ (t
+ odir)))
+ (add-change-log-entry-other-window)
+ (set-buffer cvs-buf)
+ (setq default-directory odir)
+ (setq buffer-file-name obfname)))
+
+;;----------
+(defun print-cvs-tin (foo)
+ "Debug utility."
+
+ (let ((cookie (tin-cookie cvs-cookie-handle foo))
+ (stream (get-buffer-create "pcl-cvs-debug")))
+ (princ "==============\n" stream)
+ (princ (cvs-fileinfo->file-name cookie) stream)
+ (princ "\n" stream)
+ (princ (cvs-fileinfo->dir cookie) stream)
+ (princ "\n" stream)
+ (princ (cvs-fileinfo->full-log cookie) stream)
+ (princ "\n" stream)
+ (princ (cvs-fileinfo->marked cookie) stream)
+ (princ "\n" stream)))
+
+;;----------
+;; NOTE: the variable cvs-emerge-tmp-head-file will be "free" when compiling
+(defun cvs-mode-emerge (pos)
+ "Emerge appropriate revisions of the selected file.
+Args: POS."
+
+ (interactive "d")
+ (let* ((cvs-buf (current-buffer))
+ (tin (tin-locate cvs-cookie-handle pos)))
+ (if (boundp 'cvs-emerge-tmp-head-file)
+ (error "There can only be one emerge session active at a time."))
+ (if tin
+ (let* ((fileinfo (tin-cookie cvs-cookie-handle tin))
+ (type (cvs-fileinfo->type fileinfo)))
+ (cond
+ ((eq type 'MODIFIED) ; merge repository head rev. with working file
+ (require 'emerge)
+ (setq cvs-emerge-tmp-head-file ; trick to prevent multiple runs
+ (cvs-retrieve-revision-to-tmpfile fileinfo))
+ (unwind-protect
+ (if (not (emerge-files
+ t ; arg
+ (cvs-fileinfo->full-path fileinfo) ; file-A
+ ;; this is an un-avoidable compiler reference to a free variable
+ cvs-emerge-tmp-head-file ; file-B
+ (cvs-fileinfo->full-path fileinfo) ; file-out
+ nil ; start-hooks
+ '(lambda () ; quit-hooks
+ (delete-file cvs-emerge-tmp-head-file)
+ (makunbound 'cvs-emerge-tmp-head-file))))
+ (error "Emerge session failed"))))
+
+ ;; re-do the same merge rcsmerge supposedly just did....
+ ((or (eq type 'MERGED)
+ (eq type 'CONFLICT)) ; merge backup-working=A, head=B, base=ancestor
+ (require 'emerge)
+ (setq cvs-emerge-tmp-head-file ; trick to prevent multiple runs
+ (cvs-retrieve-revision-to-tmpfile fileinfo
+ (cvs-fileinfo->head-revision
+ fileinfo)))
+ (let ((cvs-emerge-tmp-backup-working-file
+ (cvs-fileinfo->backup-file fileinfo))
+ (cvs-emerge-tmp-ancestor-file
+ (cvs-retrieve-revision-to-tmpfile fileinfo
+ (cvs-fileinfo->base-revision
+ fileinfo))))
+ (unwind-protect
+ (if (not (emerge-files-with-ancestor
+ t ; arg
+ cvs-emerge-tmp-backup-working-file ; file-A
+ ;; this is an un-avoidable compiler reference to a free variable
+ cvs-emerge-tmp-head-file ; file-B
+ cvs-emerge-tmp-ancestor-file ; file-ancestor
+ (cvs-fileinfo->full-path fileinfo) ; file-out
+ nil ; start-hooks
+ '(lambda () ; quit-hooks
+ (delete-file cvs-emerge-tmp-backup-file)
+ (delete-file cvs-emerge-tmp-ancestor-file)
+ (delete-file cvs-emerge-tmp-head-file)
+ (makunbound 'cvs-emerge-tmp-head-file))))
+ (error "Emerge session failed")))))
+ (t
+ (error "Can only e-merge \"Modified\", \"Merged\" or \"Conflict\" files"))))
+ (error "There is no file to e-merge."))))
+
+;;----------
+;; NOTE: the variable ediff-version may be "free" when compiling
+(defun cvs-mode-ediff (pos)
+ "Ediff appropriate revisions of the selected file.
+Args: POS."
+
+ (interactive "d")
+ (if (boundp 'cvs-ediff-tmp-head-file)
+ (error "There can only be one ediff session active at a time."))
+ (require 'ediff)
+ (if (and (boundp 'ediff-version)
+ (>= (string-to-number ediff-version) 2.0)) ; FIXME real number?
+ (run-ediff-from-cvs-buffer pos)
+ (cvs-old-ediff-interface pos)))
+
+(defun cvs-old-ediff-interface (pos)
+ "Emerge like interface for older ediffs.
+Args: POS"
+
+ (let* ((cvs-buf (current-buffer))
+ (tin (tin-locate cvs-cookie-handle pos)))
+ (if tin
+ (let* ((fileinfo (tin-cookie cvs-cookie-handle tin))
+ (type (cvs-fileinfo->type fileinfo)))
+ (cond
+ ((eq type 'MODIFIED) ; diff repository head rev. with working file
+ ;; should this be inside the unwind-protect, and should the
+ ;; makeunbound be an unwindform?
+ (setq cvs-ediff-tmp-head-file ; trick to prevent multiple runs
+ (cvs-retrieve-revision-to-tmpfile fileinfo))
+ (unwind-protect
+ (if (not (ediff-files ; check correct ordering of args
+ (cvs-fileinfo->full-path fileinfo) ; file-A
+ ;; this is an un-avoidable compiler reference to a free variable
+ cvs-ediff-tmp-head-file ; file-B
+ '(lambda () ; startup-hooks
+ (make-local-hook 'ediff-cleanup-hooks)
+ (add-hook 'ediff-cleanup-hooks
+ '(lambda ()
+ (ediff-janitor)
+ (delete-file cvs-ediff-tmp-head-file)
+ (makunbound 'cvs-ediff-tmp-head-file))
+ nil t))))
+ (error "Ediff session failed"))))
+
+ ;; look at the merge rcsmerge supposedly just did....
+ ((or (eq type 'MERGED)
+ (eq type 'CONFLICT)) ; diff backup-working=A, head=B, base=ancestor
+ (if (not (boundp 'ediff-version))
+ (error "ediff version way too old for 3-way diff"))
+ (if (<= (string-to-number ediff-version) 1.9) ; FIXME real number?
+ (error "ediff version %s too old for 3-way diff" ediff-version))
+ (setq cvs-ediff-tmp-head-file ; trick to prevent multiple runs
+ (cvs-retrieve-revision-to-tmpfile fileinfo
+ (cvs-fileinfo->head-revision
+ fileinfo)))
+ (let ((cvs-ediff-tmp-backup-working-file
+ (cvs-fileinfo->backup-file fileinfo))
+ (cvs-ediff-tmp-ancestor-file
+ (cvs-retrieve-revision-to-tmpfile fileinfo
+ (cvs-fileinfo->base-revision
+ fileinfo))))
+ (unwind-protect
+ (if (not (ediff-files3 ; check correct ordering of args
+ cvs-ediff-tmp-backup-working-file ; file-A
+ ;; this is an un-avoidable compiler reference to a free variable
+ cvs-ediff-tmp-head-file ; file-B
+ cvs-ediff-tmp-ancestor-file ; file-ancestor
+ '(lambda () ; start-hooks
+ (make-local-hook 'ediff-cleanup-hooks)
+ (add-hook 'ediff-cleanup-hooks
+ '(lambda ()
+ (ediff-janitor)
+ (delete-file cvs-ediff-tmp-backup-file)
+ (delete-file cvs-ediff-tmp-ancestor-file)
+ (delete-file cvs-ediff-tmp-head-file)
+ (makunbound 'cvs-ediff-tmp-head-file))
+ nil t))))
+ (error "Ediff session failed")))))
+
+ ((not (or (eq type 'UNKNOWN)
+ (eq type 'UNKNOWN-DIR))) ; i.e. UPDATED or PATCHED ????
+ ;; this should really diff the current working file with the previous
+ ;; rev. on the current branch (i.e. not the head, since that's what
+ ;; the current file should be)
+ (setq cvs-ediff-tmp-head-file ; trick to prevent multiple runs
+ (cvs-retrieve-revision-to-tmpfile fileinfo
+ (read-string "Rev #/tag to diff against: "
+ (cvs-fileinfo->head-revision
+ fileinfo))))
+ (unwind-protect
+ (if (not (ediff-files ; check correct ordering of args
+ (cvs-fileinfo->full-path fileinfo) ; file-A
+ ;; this is an un-avoidable compiler reference to a free variable
+ cvs-ediff-tmp-head-file ; file-B
+ '(lambda () ; startup-hooks
+ (make-local-hook 'ediff-cleanup-hooks)
+ (add-hook 'ediff-cleanup-hooks
+ '(lambda ()
+ (ediff-janitor)
+ (delete-file cvs-ediff-tmp-head-file)
+ (makunbound 'cvs-ediff-tmp-head-file))
+ nil t))))
+ (error "Ediff session failed"))))
+ (t
+ (error "Can not ediff \"Unknown\" files"))))
+ (error "There is no file to ediff."))))
+
+;;----------
+(defun cvs-retrieve-revision-to-tmpfile (fileinfo &optional revision)
+ "Retrieve the latest revision of the file in FILEINFO to a temporary file.
+If second optional argument REVISION is given, retrieve that revision instead."
+
+ (let
+ ((temp-name (make-temp-name
+ (concat (file-name-as-directory
+ (or (getenv "TMPDIR") "/tmp"))
+ "pcl-cvs." revision))))
+ (cvs-kill-buffer-visiting temp-name)
+ (if (and revision
+ (stringp revision)
+ (not (string= revision "")))
+ (message "Retrieving revision %s..." revision)
+ (message "Retrieving latest revision..."))
+ (let ((res (call-process cvs-shell nil nil nil "-c"
+ (concat cvs-program " update -p "
+ (if (and revision
+ (stringp revision)
+ (not (string= revision "")))
+ (concat "-r " revision " ")
+ "")
+ (cvs-fileinfo->full-path fileinfo)
+ " > " temp-name))))
+ (if (and res (not (and (integerp res) (zerop res))))
+ (error "Something went wrong retrieving revision %s: %s"
+ revision res))
+
+ (if revision
+ (message "Retrieving revision %s... Done." revision)
+ (message "Retrieving latest revision... Done."))
+ (save-excursion
+ (set-buffer (find-file-noselect temp-name))
+ (rename-buffer (concat " " (file-name-nondirectory temp-name)) t))
+ temp-name)))
+
+;;----------
+(defun cvs-kill-buffer-visiting (filename)
+ "If there is any buffer visiting FILENAME, kill it (without confirmation)."
+
+ (let ((l (buffer-list)))
+ (while l
+ (if (string= (buffer-file-name (car l)) filename)
+ (kill-buffer (car l)))
+ (setq l (cdr l)))))
+
+;;----------
+(defun cvs-change-cvsroot ()
+ "Ask for a new cvsroot."
+
+ (interactive)
+ (cvs-set-cvsroot (read-file-name "New CVSROOT: " cvs-cvsroot)))
+
+;;----------
+(defun cvs-set-cvsroot (newroot)
+ "Change the cvsroot."
+
+ (if (or (file-directory-p (expand-file-name "CVSROOT" newroot))
+ (y-or-n-p (concat "Warning: no CVSROOT found inside repository."
+ " Change cvs-cvsroot anyhow?")))
+ (setq cvs-cvsroot newroot)))
+
+;;----------
+(defun cvs-set-diff-flags ()
+ "Ask for new setting of cvs-diff-flags."
+
+ (interactive)
+ (let ((old-value (mapconcat 'identity
+ (copy-sequence cvs-diff-flags) " ")))
+ (setq cvs-diff-flags
+ (cvs-make-list (read-string "Diff flags: " old-value)))))
+
+;;----------
+(defun cvs-set-update-optional-flags ()
+ "Ask for new setting of cvs-update-optional-flags."
+
+ (interactive)
+ (let ((old-value (mapconcat 'identity
+ (copy-sequence cvs-update-optional-flags) " ")))
+ (setq cvs-update-optional-flags
+ (cvs-make-list (read-string "Update optional flags: " old-value)))))
+
+;;----------
+(defun cvs-set-status-flags ()
+ "Ask for new setting of cvs-status-flags."
+
+ (interactive)
+ (let ((old-value (mapconcat 'identity
+ (copy-sequence cvs-status-flags) " ")))
+ (setq cvs-status-flags
+ (cvs-make-list (read-string "Status flags: " old-value)))))
+
+;;----------
+(defun cvs-set-log-flags ()
+ "Ask for new setting of cvs-log-flags."
+
+ (interactive)
+ (let ((old-value (mapconcat 'identity
+ (copy-sequence cvs-log-flags) " ")))
+ (setq cvs-log-flags
+ (cvs-make-list (read-string "Log flags: " old-value)))))
+
+;;----------
+(defun cvs-set-tag-flags ()
+ "Ask for new setting of cvs-tag-flags."
+
+ (interactive)
+ (let ((old-value (mapconcat 'identity
+ (copy-sequence cvs-tag-flags) " ")))
+ (setq cvs-tag-flags
+ (cvs-make-list (read-string "Tag flags: " old-value)))))
+
+;;----------
+(defun cvs-set-rtag-flags ()
+ "Ask for new setting of cvs-rtag-flags."
+
+ (interactive)
+ (let ((old-value (mapconcat 'identity
+ (copy-sequence cvs-rtag-flags) " ")))
+ (setq cvs-rtag-flags
+ (cvs-make-list (read-string "Rtag flags: " old-value)))))
+
+;;----------
+(if (string-match "Lucid" emacs-version)
+ (progn
+ (autoload 'pcl-cvs-fontify "pcl-cvs-lucid")
+ (add-hook 'cvs-mode-hook 'pcl-cvs-fontify)))
+
+(defun cvs-changelog-name (directory)
+ "Return the name of the ChangeLog file that handles DIRECTORY.
+This is in DIRECTORY or one of its parents.
+Signal an error if we can't find an appropriate ChangeLog file."
+ (let ((dir (file-name-as-directory directory))
+ file)
+ (while (and dir
+ (not (file-exists-p
+ (setq file (expand-file-name "ChangeLog" dir)))))
+ (let ((last dir))
+ (setq dir (file-name-directory (directory-file-name dir)))
+ (if (equal last dir)
+ (setq dir nil))))
+ (or dir
+ (error "Can't find ChangeLog for %s" directory))
+ file))
+
+(defun cvs-narrow-changelog ()
+ "Narrow to the top page of the current buffer, a ChangeLog file.
+Actually, the narrowed region doesn't include the date line.
+A \"page\" in a ChangeLog file is the area between two dates."
+ (or (eq major-mode 'change-log-mode)
+ (error "cvs-narrow-changelog: current buffer isn't a ChangeLog"))
+
+ (goto-char (point-min))
+
+ ;; Skip date line and subsequent blank lines.
+ (forward-line 1)
+ (if (looking-at "[ \t\n]*\n")
+ (goto-char (match-end 0)))
+
+ (let ((start (point)))
+ (forward-page 1)
+ (narrow-to-region start (point))
+ (goto-char (point-min))))
+
+(defun cvs-changelog-paragraph ()
+ "Return the bounds of the ChangeLog paragraph containing point.
+If we are between paragraphs, return the previous paragraph."
+ (save-excursion
+ (beginning-of-line)
+ (if (looking-at "^[ \t]*$")
+ (skip-chars-backward " \t\n" (point-min)))
+ (list (progn
+ (if (re-search-backward "^[ \t]*\n" nil 'or-to-limit)
+ (goto-char (match-end 0)))
+ (point))
+ (if (re-search-forward "^[ \t\n]*$" nil t)
+ (match-beginning 0)
+ (point)))))
+
+(defun cvs-changelog-subparagraph ()
+ "Return the bounds of the ChangeLog subparagraph containing point.
+A subparagraph is a block of non-blank lines beginning with an asterisk.
+If we are between sub-paragraphs, return the previous subparagraph."
+ (save-excursion
+ (end-of-line)
+ (if (search-backward "*" nil t)
+ (list (progn (beginning-of-line) (point))
+ (progn
+ (forward-line 1)
+ (if (re-search-forward "^[ \t]*[\n*]" nil t)
+ (match-beginning 0)
+ (point-max))))
+ (list (point) (point)))))
+
+(defun cvs-changelog-entry ()
+ "Return the bounds of the ChangeLog entry containing point.
+The variable `cvs-changelog-full-paragraphs' decides whether an
+\"entry\" is a paragraph or a subparagraph; see its documentation string
+for more details."
+ (if cvs-changelog-full-paragraphs
+ (cvs-changelog-paragraph)
+ (cvs-changelog-subparagraph)))
+
+;; NOTE: the variable user-full-name may be "free" when compiling
+(defun cvs-changelog-ours-p ()
+ "See if ChangeLog entry at point is for the current user, today.
+Return non-nil iff it is."
+ ;; Code adapted from add-change-log-entry.
+ (looking-at (concat (regexp-quote (substring (current-time-string)
+ 0 10))
+ ".* "
+ (regexp-quote (substring (current-time-string) -4))
+ "[ \t]+"
+ (regexp-quote (if (and (boundp 'add-log-full-name)
+ add-log-full-name)
+ add-log-full-name
+ user-full-name))
+ " <"
+ (regexp-quote (if (and (boundp 'add-log-mailing-address)
+ add-log-mailing-address)
+ add-log-mailing-address
+ user-mail-address)))))
+
+(defun cvs-relative-path (base child)
+ "Return a directory path relative to BASE for CHILD.
+If CHILD doesn't seem to be in a subdirectory of BASE, just return
+the full path to CHILD."
+ (let ((base (file-name-as-directory (expand-file-name base)))
+ (child (expand-file-name child)))
+ (or (string= base (substring child 0 (length base)))
+ (error "cvs-relative-path: %s isn't in %s" child base))
+ (substring child (length base))))
+
+(defun cvs-changelog-entries (file)
+ "Return the ChangeLog entries for FILE, and the ChangeLog they came from.
+The return value looks like this:
+ (LOGBUFFER (ENTRYSTART . ENTRYEND) ...)
+where LOGBUFFER is the name of the ChangeLog buffer, and each
+\(ENTRYSTART . ENTRYEND\) pair is a buffer region."
+ (save-excursion
+ (set-buffer (find-file-noselect
+ (cvs-changelog-name
+ (file-name-directory
+ (expand-file-name file)))))
+ (or (eq major-mode 'change-log-mode)
+ (change-log-mode))
+ (goto-char (point-min))
+ (if (looking-at "[ \t\n]*\n")
+ (goto-char (match-end 0)))
+ (if (not (cvs-changelog-ours-p))
+ (list (current-buffer))
+ (save-restriction
+ (cvs-narrow-changelog)
+ (goto-char (point-min))
+
+ ;; Search for the name of FILE relative to the ChangeLog. If that
+ ;; doesn't occur anywhere, they're not using full relative
+ ;; filenames in the ChangeLog, so just look for FILE; we'll accept
+ ;; some false positives.
+ (let ((pattern (cvs-relative-path
+ (file-name-directory buffer-file-name) file)))
+ (if (or (string= pattern "")
+ (not (save-excursion
+ (search-forward pattern nil t))))
+ (setq pattern file))
+
+ (let (texts)
+ (while (search-forward pattern nil t)
+ (let ((entry (cvs-changelog-entry)))
+ (setq texts (cons entry texts))
+ (goto-char (elt entry 1))))
+
+ (cons (current-buffer) texts)))))))
+
+(defun cvs-changelog-insert-entries (buffer regions)
+ "Insert those regions in BUFFER specified in REGIONS.
+Sort REGIONS front-to-back first."
+ (let ((regions (sort regions 'car-less-than-car))
+ (last))
+ (while regions
+ (if (and last (< last (car (car regions))))
+ (newline))
+ (setq last (elt (car regions) 1))
+ (apply 'insert-buffer-substring buffer (car regions))
+ (setq regions (cdr regions)))))
+
+(defun cvs-union (set1 set2)
+ "Return the union of SET1 and SET2, according to `equal'."
+ (while set2
+ (or (member (car set2) set1)
+ (setq set1 (cons (car set2) set1)))
+ (setq set2 (cdr set2)))
+ set1)
+
+(defun cvs-insert-changelog-entries (files)
+ "Given a list of files FILES, insert the ChangeLog entries for them."
+ (let ((buffer-entries nil))
+
+ ;; Add each buffer to buffer-entries, and associate it with the list
+ ;; of entries we want from that file.
+ (while files
+ (let* ((entries (cvs-changelog-entries (car files)))
+ (pair (assq (car entries) buffer-entries)))
+ (if pair
+ (setcdr pair (cvs-union (cdr pair) (cdr entries)))
+ (setq buffer-entries (cons entries buffer-entries))))
+ (setq files (cdr files)))
+
+ ;; Now map over each buffer in buffer-entries, sort the entries for
+ ;; each buffer, and extract them as strings.
+ (while buffer-entries
+ (cvs-changelog-insert-entries (car (car buffer-entries))
+ (cdr (car buffer-entries)))
+ (if (and (cdr buffer-entries) (cdr (car buffer-entries)))
+ (newline))
+ (setq buffer-entries (cdr buffer-entries)))))
+
+(defun cvs-edit-delete-common-indentation ()
+ "Unindent the current buffer rigidly until at least one line is flush left."
+ (save-excursion
+ (let ((common 100000))
+ (goto-char (point-min))
+ (while (< (point) (point-max))
+ (if (not (looking-at "^[ \t]*$"))
+ (setq common (min common (current-indentation))))
+ (forward-line 1))
+ (indent-rigidly (point-min) (point-max) (- common)))))
+
+(defun cvs-mode-changelog-commit ()
+ "Check in all marked files, or the current file.
+Ask the user for a log message in a buffer.
+
+This is just like `\\[cvs-mode-commit]', except that it tries to provide
+appropriate default log messages by looking at the ChangeLog. The
+idea is to write your ChangeLog entries first, and then use this
+command to commit your changes.
+
+To select default log text, we:
+- find the ChangeLog entries for the files to be checked in,
+- verify that the top entry in the ChangeLog is on the current date
+ and by the current user; if not, we don't provide any default text,
+- search the ChangeLog entry for paragraphs containing the names of
+ the files we're checking in, and finally
+- use those paragraphs as the log text."
+
+ (interactive)
+
+ (let* ((cvs-buf (current-buffer))
+ (marked (cvs-filter (function cvs-committable)
+ (cvs-get-marked))))
+ (if (null marked)
+ (error "Nothing to commit!")
+ (pop-to-buffer (get-buffer-create cvs-commit-prompt-buffer))
+ (goto-char (point-min))
+
+ (erase-buffer)
+ (cvs-insert-changelog-entries
+ (mapcar (lambda (tin)
+ (let ((cookie (tin-cookie cvs-cookie-handle tin)))
+ (expand-file-name
+ (cvs-fileinfo->file-name cookie)
+ (cvs-fileinfo->dir cookie))))
+ marked))
+ (cvs-edit-delete-common-indentation)
+
+ (cvs-edit-mode)
+ (make-local-variable 'cvs-commit-list)
+ (setq cvs-commit-list marked)
+ (message "Press C-c C-c when you are done editing."))))
+
+(provide 'pcl-cvs)
+
+;;;; end of file pcl-cvs.el
diff --git a/contrib/cvs/tools/pcl-cvs/pcl-cvs.texinfo b/contrib/cvs/tools/pcl-cvs/pcl-cvs.texinfo
new file mode 100644
index 0000000..8bd3619
--- /dev/null
+++ b/contrib/cvs/tools/pcl-cvs/pcl-cvs.texinfo
@@ -0,0 +1,1565 @@
+\input texinfo @c -*-texinfo-*-
+
+@comment OrigId: pcl-cvs.texinfo,v 1.45 1993/05/31 22:38:15 ceder Exp
+@comment @@(#)cvs/contrib/pcl-cvs:$Name: $:$Id: pcl-cvs.texinfo,v 1.1 1996/04/14 15:18:04 kfogel Exp $
+
+@comment Documentation for the GNU Emacs CVS mode.
+@comment Copyright (C) 1992 Per Cederqvist
+
+@comment This file is part of the pcl-cvs distribution.
+
+@comment Pcl-cvs is free software; you can redistribute it and/or modify
+@comment it under the terms of the GNU General Public License as published by
+@comment the Free Software Foundation; either version 1, or (at your option)
+@comment any later version.
+
+@comment Pcl-cvs is distributed in the hope that it will be useful,
+@comment but WITHOUT ANY WARRANTY; without even the implied warranty of
+@comment MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+@comment GNU General Public License for more details.
+
+@comment You should have received a copy of the GNU General Public License
+@comment along with pcl-cvs; see the file COPYING. If not, write to
+@comment the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+@setfilename pcl-cvs.info
+@settitle Pcl-cvs - The Emacs Front-End to CVS
+@setchapternewpage on
+
+@ifinfo
+Copyright @copyright{} 1992 Per Cederqvist
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and provided that the entire resulting derived work is
+distributed under the terms of a permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' and
+this permission notice may be included in translations approved by the
+Free Software Foundation instead of in the original English.
+@end ifinfo
+
+@synindex vr fn
+@comment The titlepage section does not appear in the Info file.
+@titlepage
+@sp 4
+@comment The title is printed in a large font.
+@center @titlefont{User's Guide}
+@sp
+@center @titlefont{to}
+@sp
+@center @titlefont{pcl-cvs - the Emacs Front-End to CVS}
+@sp 2
+@center release 1.05-CVS-$Name: $
+@comment -release-
+@sp 3
+@center Per Cederqvist
+@sp 3
+@center last updated 20 Nov 1995
+@comment -date-
+
+@comment The following two commands start the copyright page
+@comment for the printed manual. This will not appear in the Info file.
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992 Per Cederqvist
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and provided that the entire resulting derived work is
+distributed under the terms of a permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' and
+this permission notice may be included in translations approved by the
+Free Software Foundation instead of in the original English.
+@end titlepage
+
+@comment ================================================================
+@comment The real text starts here
+@comment ================================================================
+
+@node Top, Installation, (dir), (dir)
+@comment node-name, next, previous, up
+
+
+@ifinfo
+This info manual describes pcl-cvs which is a GNU Emacs front-end to
+CVS. It works with CVS versions 1.5 through 1.7 and newer, and possibly
+CVS-1.3 and CVS-1.4A2. This manual is updated to release
+1.05-CVS-$Name: $ of pcl-cvs.
+@end ifinfo
+@comment -release-
+
+@menu
+* Installation:: How to install pcl-cvs on your system.
+* About pcl-cvs:: Authors and ftp sites.
+
+* Getting started:: An introduction with a walk-through example.
+* Buffer contents:: An explanation of the buffer contents.
+* Commands:: All commands, grouped by type.
+
+* Customization:: How you can tailor pcl-cvs to suit your needs.
+* Future enhancements:: Future enhancements of pcl-cvs.
+* Bugs:: Bugs (known and unknown).
+* COPYING:: GNU General Public License
+* Function and Variable Index:: List of functions and variables.
+* Concept Index:: List of concepts.
+* Key Index:: List of keystrokes.
+
+ --- The Detailed Node Listing ---
+
+Installation
+
+* Pcl-cvs installation:: How to install pcl-cvs on your system.
+* On-line manual installation:: How to install the on-line manual.
+* Typeset manual installation:: How to create typeset documentation
+ about pcl-cvs.
+
+About pcl-cvs
+
+* Contributors:: Contributors to pcl-cvs.
+* Archives:: Where can I get a copy of Pcl-Cvs?
+
+Buffer contents
+
+* File status:: The meaning of the second field.
+* Selected files:: How selection works.
+
+Commands
+
+* Updating the directory:: Commands to update the local directory
+* Movement commands:: How to move up and down in the buffer
+* Marking files:: How to mark files that other commands
+ will later operate on.
+* Committing changes:: Checking in your modifications to the
+ CVS repository.
+* Editing files:: Loading files into Emacs.
+* Getting info about files:: Display the log and status of files.
+* Adding and removing files:: Adding and removing files
+* Undoing changes:: Undoing changes
+* Removing handled entries:: Uninteresting lines can easily be removed.
+* Ignoring files:: Telling CVS to ignore generated files.
+* Viewing differences:: Commands to @samp{diff} different versions.
+* Invoking Ediff:: Running @samp{ediff} from @samp{*cvs*} buffer.
+* Invoking Emerge:: Running @samp{emerge} from @samp{*cvs*} buffer.
+* Reverting your buffers:: Reverting your buffers
+* Miscellaneous commands:: Miscellaneous commands
+@end menu
+
+
+@node Installation, About pcl-cvs, Top, Top
+@comment node-name, next, previous, up
+
+@chapter Installation
+@cindex Installation
+
+This section describes the installation of pcl-cvs, the GNU Emacs CVS
+front-end. You should install not only the elisp files themselves, but
+also the on-line documentation so that your users will know how to use
+it. You can create typeset documentation from the file
+@file{pcl-cvs.texinfo} as well as an on-line info file. The following
+steps are also described in the file @file{INSTALL} in the source
+directory.
+
+@menu
+* Pcl-cvs installation:: How to install pcl-cvs on your system.
+* On-line manual installation:: How to install the on-line manual.
+* Typeset manual installation:: How to create typeset documentation
+ about pcl-cvs.
+@end menu
+
+
+@node Pcl-cvs installation, On-line manual installation, Installation, Installation
+@comment node-name, next, previous, up
+@section Installation of the pcl-cvs program
+@cindex Installation of elisp files
+
+@enumerate
+@item
+Possibly edit the file @file{Makefile} to reflect the situation at your
+site. We say "possibly" because the version of pcl-cvs included with
+CVS uses a configuration mechanism integrated with the overall
+mechanisms used by the CVS build and install procedures. Thus the file
+@code{Makefile} will be generated automatically from the file
+@code{Makefile.in}, and it should not be necessary to edit it further.
+
+If you do have to edit the @file{Makefile}, the only things you have to
+change is the definition of @code{lispdir} and @code{infodir}. The
+elisp files will be copied to @code{lispdir}, and the info file(s) to
+@code{infodir}.
+
+@item
+Configure pcl-cvs.el
+
+There are a couple of pathnames that you have to check to make sure that
+they match your system. They appear early in the file
+@samp{pcl-cvs.el}.
+
+@strong{NOTE:} If your system is running emacs 18.57 or earlier you MUST
+uncomment the line that says:
+@example
+(setq delete-exited-processes nil)
+@end example
+
+Setting @code{delete-exited-processes} to @code{nil} works around a bug
+in emacs that causes it to dump core. The bug was fixed in emacs
+18.58.@refill
+
+@item
+Release 1.05 and later of pcl-cvs requires parts of the Elib library,
+version 1.0 or later. Elib is available via anonymous ftp from
+prep.ai.mit.edu in @file{pub/gnu/elib-1.0.tar.gz}, and from a lot of
+other sites that mirror prep. Get Elib, and install it, before
+proceeding.
+
+@strong{NOTE:} The version of pcl-cvs included with CVS includes a copy
+of Elib in the sub-directory @file{elib} under the
+@file{contrib/pcl-cvs} directory.
+
+@item
+Type @samp{make install} in the source directory. This will
+byte-compile all @file{.el} files and copy the @file{*.elc} files into
+the directory you specified in step 1.
+
+If you want to install the @file{*.el} files too, you can type
+@samp{make install-el} to do so.
+
+If you only want to create the compiled elisp files, but don't want to
+install them, you can type @samp{make} without parameters.
+
+@item
+Edit the file @file{default.el} in your emacs lisp directory (usually
+@file{/usr/gnu/lib/emacs/site-lisp} or something similar) and enter the
+contents of the file @file{pcl-cvs-startup.el} into it. It contains a
+couple of @code{auto-load}s that facilitates the use of pcl-cvs.
+
+@end enumerate
+
+
+@node On-line manual installation, Typeset manual installation, Pcl-cvs installation, Installation
+@comment node-name, next, previous, up
+
+@section Installation of the on-line manual.
+@cindex Manual installation (on-line)
+@cindex Installation of on-line manual
+@cindex Generating the on-line manual
+@cindex On-line manual (how to generate)
+@cindex Info-file (how to generate)
+
+@enumerate
+@item
+Create the info file(s) @file{pcl-cvs.info*} from @file{pcl-cvs.texinfo}
+by typing @samp{make info}. If you don't have the program
+@samp{makeinfo} you can get it by anonymous ftp from
+e.g. @samp{prep.ai.mit.edu} as @file{pub/gnu/texinfo-3.7.tar.gz} (there
+might be a newer version there when you read this).@refill
+
+@item
+Install the info file(s) @file{pcl-cvs.info*} into your standard
+@file{info} directory. You should be able to do this by typing
+@samp{make install-info}.@refill
+
+@item
+Edit the file @file{dir} in the @file{info} directory and enter one line
+to contain a pointer to the info file(s) @file{pcl-cvs.info*}. The line
+can, for instance, look like this:@refill
+
+@example
+* Pcl-cvs: (pcl-cvs). An Emacs front-end to CVS.
+@end example
+@end enumerate
+
+
+@node Typeset manual installation, , On-line manual installation, Installation
+@comment node-name, next, previous, up
+
+@section How to make typeset documentation from pcl-cvs.texinfo
+@cindex Manual installation (typeset)
+@cindex Installation of typeset manual
+@cindex Printing a manual
+@cindex TeX - generating a typeset manual
+@cindex Generating a typeset manual
+
+If you have @TeX{} installed at your site, you can make a typeset manual
+from @file{pcl-cvs.texinfo}.
+
+@enumerate
+@item
+Run @TeX{} by typing `@samp{make pcl-cvs.dvi}'. You will not get the
+indices unless you have the @code{texindex} program.
+
+@item
+Convert the resulting device independent file @file{pcl-cvs.dvi} to a
+form which your printer can output and print it. If you have a
+postscript printer there is a program, @code{dvi2ps}, which does. There
+is also a program which comes together with @TeX{}, @code{dvips}, which
+you can use.
+
+@end enumerate
+
+
+@node About pcl-cvs, Getting started, Installation, Top
+@comment node-name, next, previous, up
+
+@chapter About pcl-cvs
+@cindex About pcl-cvs
+
+Pcl-cvs is a front-end to CVS versions 1.5 through 1.7 and newer; and
+possibly verison 1.3 and 1.4A2. It integrates the most frequently used
+CVS commands into an emacs interface.
+
+@menu
+* Contributors:: Contributors to pcl-cvs.
+* Archives:: Where can I get a copy of Pcl-Cvs?
+@end menu
+
+
+@node Contributors, Archives, About pcl-cvs, About pcl-cvs
+@comment node-name, next, previous, up
+
+@section Contributors to pcl-cvs
+@cindex Contributors
+@cindex Authors
+
+Contributions to the package are welcome. I have limited time to work
+on this project, but I will gladly add any code that you contribute to
+me to this package (@pxref{Bugs}).
+
+The following persons have made contributions to pcl-cvs.
+
+@itemize @bullet
+@item
+Brian Berliner wrote CVS, together with some other contributors.
+Without his work on CVS this package would be useless@dots{}
+
+@item
+Per Cederqvist wrote most of the otherwise unattributed functions in
+pcl-cvs as well as all documentation.
+
+@item
+Inge Wallin (@samp{inge@@lysator.liu.se}) wrote the skeleton to
+@file{pcl-cvs.texinfo}, and gave useful comments on it. He also wrote
+the files @file{elib-node.el} and @file{compile-all.el}. The file
+@file{cookie.el} was inspired by Inge.@refill
+
+@item
+Linus Tolke (@samp{linus@@lysator.liu.se}) contributed useful comments
+on both the functionality and the documentation.@refill
+
+@item
+Jamie Zawinski (@samp{jwz@@lucid.com}) contributed
+@file{pcl-cvs-lucid.el}.
+
+@item
+Leif Lonnblad contributed RCVS support. (Since superceded by the new
+remote CVS support.)
+
+@item
+Jim Blandy (@samp{jimb@@cyclic.com}) contributed hooks to automatically
+guess CVS log entries from ChangeLog contents; and initial support of
+the new Cygnus / Cyclic remote CVS; as well as various sundry bug fixes
+and cleanups.
+
+@item
+Jim Kingdon (@samp{kingdon@@cyclic.com}) contributed lots of fixes to
+the build and install procedure.
+
+@item
+Greg A. Woods (@samp{woods@@planix.com}) contributed code to implement
+the use of per-file diff buffers; and vendor join diffs with emerge and
+ediff; as well as various an sundry bug fixes and cleanups.
+@end itemize
+
+Apart from these, a lot of people have send me suggestions, ideas,
+requests, bug reports and encouragement. Thanks a lot! Without your
+there would be no new releases of pcl-cvs.
+
+
+@node Archives, , Contributors, About pcl-cvs
+@comment node-name, next, previous, up
+
+@section Where can I get pcl-cvs?
+@cindex Sites
+@cindex Archives
+@cindex Ftp-sites
+@cindex Getting pcl-cvs
+@cindex Email archives
+
+The current release of pcl-cvs is included in CVS-1.7.
+
+The author's release of pcl-cvs can be fetched via anonymous ftp from
+@code{ftp.lysator.liu.se}, (IP no. 130.236.254.1) in the directory
+@code{pub/emacs}. If you don't live in Scandinavia you should probably
+check with archie to see if there is a site closer to you that archives
+pcl-cvs.
+
+New releases will be announced to appropriate newsgroups. If you send
+your email address to me I will add you to my list of people to mail
+when I make a new release.
+
+
+@node Getting started, Buffer contents, About pcl-cvs, Top
+@comment node-name, next, previous, up
+
+@chapter Getting started
+@cindex Introduction
+@cindex Example run
+
+This document assumes that you know what CVS is, and that you at least
+knows the fundamental concepts of CVS. If that is not the case you
+should read the man page for CVS.
+
+Pcl-cvs is only useful once you have checked out a module. So before
+you invoke it you must have a copy of a module somewhere in the file
+system.
+
+You invoke pcl-cvs by typing @kbd{M-x cvs-update RET}. If your emacs
+responds with @samp{[No match]} your system administrator has not
+installed pcl-cvs properly. Try @kbd{M-x load-library RET pcl-cvs RET}.
+If that also fails - talk to your root. If it succeeds you might put
+this line in your @file{.emacs} file so that you don't have to type the
+@samp{load-library} command every time you wish to use pcl-cvs:
+
+@example
+(autoload 'cvs-update "pcl-cvs" nil t)
+@end example
+
+The function @code{cvs-update} will ask for a directory. The command
+@samp{cvs update} will be run in that directory. (It should contain
+files that have been checked out from a CVS archive.) The output from
+@code{cvs} will be parsed and presented in a table in a buffer called
+@samp{*cvs*}. It might look something like this:
+
+@example
+PCL-CVS release 1.05-CVS-$Name: $.
+@comment -release-
+
+In directory /users/ceder/FOO/test:
+ Updated bar
+ Updated file.txt
+ Modified ci namechange
+ Updated newer
+
+In directory /users/ceder/FOO/test/sub:
+ Modified ci ChangeLog
+---------- End -----
+@end example
+
+In this example the two files (@file{bar}, @file{file.txt}, and
+@file{newer}) that are marked with @samp{Updated} have been copied from
+the CVS repository to @file{/users/ceder/FOO/test/} since someone else
+have checked in newer versions of them. Two files (@file{namechange}
+and @file{sub/ChangeLog}) have been modified locally, and needs to be
+checked in.
+
+You can move the cursor up and down in the buffer with @kbd{C-n} and
+@kbd{C-p} or @kbd{n} and @kbd{p}. If you press @kbd{c} on one of the
+@samp{Modified} files that file will be checked in to the CVS
+repository. @xref{Committing changes}. You can press @kbd{x} to get rid
+of the "uninteresting" files that have only been @samp{Updated} (and
+don't require any further action from you).@refill
+
+You can also easily get a @samp{diff} between your modified file and the
+base version that you started from, and you can get the output from
+@samp{cvs log} and @samp{cvs status} on the listed files simply by
+pressing a key (@pxref{Getting info about files}).
+
+
+@node Buffer contents, Commands, Getting started, Top
+@comment node-name, next, previous, up
+
+@chapter Buffer contents
+@cindex Buffer contents
+
+The display contains four columns. They contain, from left to right:
+
+@itemize @bullet
+@item
+An asterisk when the file is @dfn{marked} (@pxref{Selected
+files}).@refill
+@item
+The status of the file. See @xref{File status}, for more
+information.@refill
+@item
+A "need to be checked in"-marker (@samp{ci}).
+@item
+The file name.
+@end itemize
+
+@menu
+* File status:: The meaning of the second field.
+* Selected files:: How selection works.
+@end menu
+
+
+@node File status, Selected files, Buffer contents, Buffer contents
+@comment node-name, next, previous, up
+
+@section File status
+@cindex File status
+@cindex Updated (file status)
+@cindex Patched (file status)
+@cindex Modified (file status)
+@cindex Merged (file status)
+@cindex Conflict (file status)
+@cindex Added (file status)
+@cindex Removed (file status)
+@cindex Unknown (file status)
+@cindex Removed from repository (file status)
+@cindex Removed from repository, changed by you (file status)
+@cindex Removed by you, changed in repository (file status)
+@cindex Move away @var{file} - it is in the way (file status)
+@cindex This repository is missing!@dots{} (file status)
+
+The @samp{file status} field can have the following values:
+
+@table @samp
+
+@item Updated
+The file was brought up to date with respect to the repository. This is
+done for any file that exists in the repository but not in your source,
+and for files that you haven't changed but are not the most recent
+versions available in the repository.@refill
+
+@item Patched
+The file was brought up to date with respect to a remote repository by
+way of fetching and applying a patch to the file in your source. This
+is done for any file that exists in a remote repository and in your
+source; of which you haven't changed locally but is not the most recent
+version available in the remote repository.@refill
+
+@item Modified
+The file is modified in your working directory, and there was no
+modification to the same file in the repository.@refill
+
+@item Merged
+The file is modified in your working directory, and there were
+modifications in the repository as well as in your copy, but they were
+merged successfully, without conflict, in your working directory.@refill
+
+@item Conflict
+A conflict was detected while trying to merge your changes to @var{file}
+with changes from the source repository. @var{file} (the copy in your
+working directory) is now the output of the @samp{rcsmerge} command on
+the two versions; an unmodified copy of your file is also in your
+working directory, with the name @file{.#@var{file}.@var{version}},
+where @var{version} is the RCS revision that your modified file started
+from. @xref{Viewing differences}, for more details.@refill
+
+@item Added
+The file has been added by you, but it still needs to be checked in to
+the repository.@refill
+
+@item Removed
+The file has been removed by you, but it needs to be checked in to the
+repository. You can resurrect it by typing @kbd{a} (@pxref{Adding and
+removing files}).@refill
+
+@item Unknown
+A file that was detected in your directory, but that neither appears in
+the repository, nor is present on the list of files that CVS should
+ignore.@refill
+
+@end table
+
+There are also a few special cases, that rarely occur, which have longer
+strings in the fields:
+
+@table @samp
+@item Removed from repository
+The file has been removed from your directory since someone has removed
+it from the repository. (It is still present in the Attic directory, so
+no permanent loss has occurred). This, unlike the other entries in this
+table, is not an error condition.@refill
+
+@item Removed from repository, changed by you
+You have modified a file that someone have removed from the repository.
+You can correct this situation by removing the file manually (see
+@pxref{Adding and removing files}).@refill
+
+@item Removed by you, changed in repository
+You have removed a file, and before you committed the removal someone
+committed a change to that file. You could use @kbd{a} to resurrect the
+file (see @pxref{Adding and removing files}).@refill
+
+@item Move away @var{file} - it is in the way
+For some reason CVS does not like the file @var{file}. Rename or remove
+it.@refill
+
+@item This repository is missing! Remove this dir manually.
+It is impossible to remove a directory in the CVS repository in a clean
+way. Someone have tried to remove one, and CVS gets confused. Remove
+your copy of the directory.@refill
+@end table
+
+
+@node Selected files, , File status, Buffer contents
+@comment node-name, next, previous, up
+
+@section Selected files
+@cindex Selected files
+@cindex Marked files
+@cindex File selection
+@cindex Active files
+
+Many of the commands works on the current set of @dfn{selected} files.
+
+@itemize @bullet
+@item
+If there are any files that are marked they constitute the set of
+selected files.@refill
+@item
+Otherwise, if the cursor points to a file, that file is the selected
+file.@refill
+@item
+Otherwise, if the cursor points to a directory, all the files in that
+directory that appears in the buffer are the selected files.
+@end itemize
+
+This scheme might seem a little complicated, but once one get used to
+it, it is quite powerful.
+
+@xref{Marking files} tells how you mark and unmark files.
+
+
+@node Commands, Customization, Buffer contents, Top
+@comment node-name, next, previous, up
+
+@chapter Commands
+
+@iftex
+This chapter describes all the commands that you can use in pcl-cvs.
+@end iftex
+@ifinfo
+The nodes in this menu contains explanations about all the commands that
+you can use in pcl-cvs. They are grouped together by type.
+@end ifinfo
+
+@menu
+* Updating the directory:: Commands to update the local directory
+* Movement commands:: How to move up and down in the buffer
+* Marking files:: How to mark files that other commands
+ will later operate on.
+* Committing changes:: Checking in your modifications to the
+ CVS repository.
+* Editing files:: Loading files into Emacs.
+* Getting info about files:: Display the log and status of files.
+* Adding and removing files:: Adding and removing files
+* Undoing changes:: Undoing changes
+* Removing handled entries:: Uninteresting lines can easily be removed.
+* Ignoring files:: Telling CVS to ignore generated files.
+* Viewing differences:: Commands to @samp{diff} different versions.
+* Invoking Ediff:: Running @samp{ediff} from @samp{*cvs*} buffer.
+* Invoking Emerge:: Running @samp{emerge} from @samp{*cvs*} buffer.
+* Reverting your buffers:: Reverting your buffers
+* Miscellaneous commands:: Miscellaneous commands
+@end menu
+
+
+@node Updating the directory, Movement commands, Commands, Commands
+@comment node-name, next, previous, up
+
+@section Updating the directory
+@findex cvs-update
+@findex cvs-mode-update-no-prompt
+@findex cvs-delete-lock
+@cindex Getting the *cvs* buffer
+@kindex g - Rerun @samp{cvs update}
+
+
+@table @kbd
+
+@item M-x cvs-update
+Run a @samp{cvs update} command. You will be asked for the directory in
+which the @samp{cvs update} will be run. The output will be parsed by
+pcl-cvs, and the result printed in the @samp{*cvs*} buffer (see
+@pxref{Buffer contents} for a description of the contents).@refill
+
+By default, @samp{cvs-update} will descend recursively into
+subdirectories. You can avoid that behavior by giving a prefix
+argument to it (e.g., by typing @kbd{C-u M-x cvs-update RET}).@refill
+
+All other commands in pcl-cvs requires that you have a @samp{*cvs*}
+buffer. This is the command that you use to get one.@refill
+
+CVS uses lock files in the repository to ensure the integrity of the
+data files in the repository. They might be left behind i.e. if a
+workstation crashes in the middle of a CVS operation. CVS outputs a
+message when it is waiting for a lock file to go away. Pcl-cvs will
+show the same message in the *cvs* buffer, together with instructions
+for deleting the lock files. You should normally not have to delete
+them manually --- just wait a little while and the problem should fix
+itself. But if the lock files doesn't disappear you can delete them
+with @kbd{M-x cvs-delete-lock RET}.@refill
+
+@item g
+This will run @samp{cvs update} again. It will always use the same
+buffer that was used with the previous @samp{cvs update}. Give a prefix
+argument to avoid descending into subdirectories. This runs the command
+@samp{cvs-mode-update-no-prompt}.@refill
+
+@item G
+This will run @samp{cvs update} and prompt for a new directory to
+update. This runs the command @samp{cvs-update}.@refill
+
+@end table
+
+
+@node Movement commands, Marking files, Updating the directory, Commands
+@comment node-name, next, previous, up
+
+@section Movement Commands
+@cindex Movement Commands
+@findex cookie-next-cookie
+@findex cookie-previous-cookie
+@kindex SPC - Move down one file
+@kindex C-n - Move down one file
+@kindex n - Move down one file
+@kindex C-p - Move up one file
+@kindex p - Move up on file
+
+You can use most normal Emacs commands to move forward and backward in
+the buffer. Some keys are rebound to functions that take advantage of
+the fact that the buffer is a pcl-cvs buffer:
+
+
+@table @kbd
+@item SPC
+@itemx C-n
+@itemx n
+These keys move the cursor one file forward, towards the end of the
+buffer (@code{cookie-next-cookie}).
+
+@item C-p
+@itemx p
+These keys move one file backward, towards the beginning of the buffer
+(@code{cookie-previous-cookie}).
+@end table
+
+
+@node Marking files, Committing changes, Movement commands, Commands
+@comment node-name, next, previous, up
+
+@section Marking files
+@cindex Selecting files (commands to mark files)
+@cindex Marking files
+@kindex m - marking a file
+@kindex M - marking all files
+@kindex u - unmark a file
+@kindex ESC DEL - unmark all files
+@kindex DEL - unmark previous file
+@findex cvs-mode-mark
+@findex cvs-mode-unmark
+@findex cvs-mode-mark-all-files
+@findex cvs-mode-unmark-all-files
+@findex cvs-mode-unmark-up
+
+Pcl-cvs works on a set of @dfn{selected files} (@pxref{Selected files}).
+You can mark and unmark files with these commands:
+
+@table @kbd
+@item m
+This marks the file that the cursor is positioned on. If the cursor is
+positioned on a directory all files in that directory will be marked.
+(@code{cvs-mode-mark}).
+
+@item u
+Unmark the file that the cursor is positioned on. If the cursor is on a
+directory, all files in that directory will be unmarked.
+(@code{cvs-mode-unmark}).@refill
+
+@item M
+Mark @emph{all} files in the buffer (@code{cvs-mode-mark-all-files}).
+
+@item @key{ESC} @key{DEL}
+Unmark @emph{all} files (@code{cvs-mode-unmark-all-files}).
+
+@item @key{DEL}
+Unmark the file on the previous line, and move point to that line
+(@code{cvs-mode-unmark-up}).
+@end table
+
+
+@node Committing changes, Editing files, Marking files, Commands
+@comment node-name, next, previous, up
+
+@section Committing changes
+@cindex Committing changes
+@cindex Ci
+@findex cvs-mode-commit
+@findex cvs-mode-changelog-commit
+@kindex c - commit files
+@kindex C - commit files with ChangeLog message
+@vindex cvs-erase-input-buffer (variable)
+@vindex cvs-auto-revert-after-commit (variable)
+@cindex Commit buffer
+@cindex Edit buffer
+@cindex Erasing commit message
+@cindex Reverting buffers after commit
+
+@table @kbd
+
+@item c
+All files that have a "need to be checked in"-marker (@pxref{Buffer
+contents}) can be checked in with the @kbd{c} command. It checks in all
+selected files (@pxref{Selected files}) (except those who lack the
+"ci"-marker - they are ignored). Pressing @kbd{c} causes
+@code{cvs-mode-commit} to be run.@refill
+
+When you press @kbd{c} you will get a buffer called
+@samp{*cvs-commit-message*}. Enter the log message for the file(s) in
+it. When you are ready you should press @kbd{C-c C-c} to actually
+commit the files (using @code{cvs-edit-done}).
+
+Normally the @samp{*cvs-commit-message*} buffer will retain the log
+message from the previous commit, but if the variable
+@code{cvs-erase-input-buffer} is set to a non-@code{nil} value the
+buffer will be erased. Point and mark will always be located around the
+entire buffer so that you can easily erase it with @kbd{C-w}
+(@samp{kill-region}).@refill
+
+If you are editing the files in your emacs an automatic
+@samp{revert-buffer} will be performed. (If the file contains
+@samp{$@asis{Id}$} keywords @samp{cvs commit} will write a new file with
+the new values substituted. The auto-revert makes sure that you get
+them into your buffer). The revert will not occur if you have modified
+your buffer, or if @samp{cvs-auto-revert-after-commit} is set to
+@samp{nil}.@refill
+
+@item C
+This is just like @samp{cvs-mode-commit}, except that it tries to
+provide appropriate default log messages by looking at the
+@samp{ChangeLog}s in the current directory. The idea is to write your
+ChangeLog entries first, and then use this command to commit your
+changes. Pressing @kbd{C} causes @code{cvs-mode-changelog-commit} to be
+run.@refill
+
+To select default log text, pcl-cvs:
+@itemize @minus
+@item
+finds the ChangeLogs for the files to be checked in;
+@item
+verifies that the top entry in the ChangeLog is on the current date and
+by the current user; if not, no default text is provided;
+@item
+search the ChangeLog entry for paragraphs containing the names of the
+files we're checking in; and finally
+@item
+uses those paragraphs as the default log text in the
+@samp{*cvs-commit-message*} buffer.
+@end itemize
+
+You can then commit the @samp{ChangeLog} file once per day without any
+log message.@refill
+
+@end table
+
+
+@node Editing files, Getting info about files, Committing changes, Commands
+@comment node-name, next, previous, up
+
+@section Editing files
+@cindex Editing files
+@cindex Finding files
+@cindex Loading files
+@cindex Dired
+@cindex Invoking dired
+@findex cvs-mode-find-file
+@findex cvs-mode-find-file-other-window
+@findex cvs-mode-add-change-log-entry-other-window
+@kindex f - find file or directory
+@kindex o - find file in other window
+@kindex A - add ChangeLog entry
+
+There are currently three commands that can be used to find a file (that
+is, load it into a buffer and start editing it there). These commands
+work on the line that the cursor is situated at. They ignore any marked
+files.
+
+@table @kbd
+@item f
+Find the file that the cursor points to. Run @samp{dired}
+@ifinfo
+(@pxref{Dired,,,Emacs})
+@end ifinfo
+if the cursor points to a directory (@code{cvs-mode-find-file}).@refill
+
+@item o
+Like @kbd{f}, but use another window
+(@code{cvs-mode-find-file-other-window}).@refill
+
+@item A
+Invoke @samp{add-change-log-entry-other-window} to edit a
+@samp{ChangeLog} file. The @samp{ChangeLog} will be found in the
+directory of the file the cursor points to.
+(@code{cvs-mode-add-change-log-entry-other-window}).@refill
+@end table
+
+
+@node Getting info about files, Adding and removing files, Editing files, Commands
+@comment node-name, next, previous, up
+
+@section Getting info about files
+@cindex Status (cvs command)
+@cindex Log (RCS/cvs command)
+@cindex Getting status
+@kindex l - run @samp{cvs log}
+@kindex s - run @samp{cvs status}
+@findex cvs-mode-log
+@findex cvs-mode-status
+
+Both of the following commands can be customized.
+@xref{Customization}.@refill
+
+@table @kbd
+@item l
+Run @samp{cvs log} on all selected files, and show the result in a
+temporary buffer (@code{cvs-mode-log}).
+
+@item s
+Run @samp{cvs status} on all selected files, and show the result in a
+temporary buffer (@code{cvs-mode-status}).
+@end table
+
+
+@node Adding and removing files, Undoing changes, Getting info about files, Commands
+@comment node-name, next, previous, up
+
+@section Adding and removing files
+@cindex Adding files
+@cindex Removing files
+@cindex Resurrecting files
+@cindex Deleting files
+@cindex Putting files under CVS control
+@kindex a - add a file
+@kindex r - remove a file
+@findex cvs-mode-add
+@findex cvs-mode-remove-file
+
+The following commands are available to make it easy to add and remove
+files from the CVS repository.
+
+@table @kbd
+@item a
+Add all selected files. This command can be used on @samp{Unknown}
+files (see @pxref{File status}). The status of the file will change to
+@samp{Added}, and you will have to use @kbd{c} (@samp{cvs-mode-commit}, see
+@pxref{Committing changes}) to really add the file to the
+repository.@refill
+
+This command can also be used on @samp{Removed} files (before you commit
+them) to resurrect them.
+
+Selected files that are neither @samp{Unknown} nor @samp{Removed} will
+be ignored by this command.
+
+The command that is run is @code{cvs-mode-add}.
+
+@item r
+This command removes the selected files (after prompting for
+confirmation). The files are @samp{rm}ed from your directory and
+(unless the status was @samp{Unknown}; @pxref{File status}) they will
+also be @samp{cvs remove}d. If the files were @samp{Unknown} they will
+disappear from the buffer. Otherwise their status will change to
+@samp{Removed}, and you must use @kbd{c} (@samp{cvs-mode-commit},
+@pxref{Committing changes}) to commit the removal.@refill
+
+The command that is run is @code{cvs-mode-remove-file}.
+@end table
+
+
+@node Undoing changes, Removing handled entries, Adding and removing files, Commands
+@comment node-name, next, previous, up
+
+@section Undoing changes
+@cindex Undo changes
+@cindex Flush changes
+@kindex U - undo changes
+@findex cvs-mode-undo-local-changes
+
+@table @kbd
+@item U
+If you have modified a file, and for some reason decide that you don't
+want to keep the changes, you can undo them with this command. It works
+by removing your working copy of the file and then getting the latest
+version from the repository (@code{cvs-mode-undo-local-changes}.
+@end table
+
+
+@node Removing handled entries, Ignoring files, Undoing changes, Commands
+@comment node-name, next, previous, up
+
+@section Removing handled entries
+@cindex Expunging uninteresting entries
+@cindex Uninteresting entries, getting rid of them
+@cindex Getting rid of uninteresting lines
+@cindex Removing uninteresting (processed) lines
+@cindex Handled lines, removing them
+@kindex x - remove processed entries
+@kindex C-k - remove selected entries
+@findex cvs-mode-remove-handled
+@findex cvs-mode-acknowledge
+
+@table @kbd
+@item x
+This command allows you to remove all entries that you have processed.
+More specifically, the lines for @samp{Updated} files (@pxref{File
+status} and files that have been checked in (@pxref{Committing changes})
+are removed from the buffer. If a directory becomes empty the heading
+for that directory is also removed. This makes it easier to get an
+overview of what needs to be done.
+
+The command is called @code{cvs-mode-remove-handled}. If
+@samp{cvs-auto-remove-handled} is set to non-@code{nil} this will
+automatically be performed after every commit.@refill
+
+@item C-k
+This command can be used for lines that @samp{cvs-mode-remove-handled} would
+not delete, but that you want to delete (@code{cvs-mode-acknowledge}).
+@end table
+
+
+@node Ignoring files, Viewing differences, Removing handled entries, Commands
+@comment node-name, next, previous, up
+
+@section Ignoring files
+@kindex i - ignoring files
+@findex cvs-mode-ignore
+
+@table @kbd
+@item i
+Arrange so that CVS will ignore the selected files. The file names are
+added to the @file{.cvsignore} file in the corresponding directory. If
+the @file{.cvsignore} doesn't exist it will be created.
+
+The @file{.cvsignore} file should normally be added to the repository,
+but you could ignore it also if you like it better that way.
+
+This runs @code{cvs-mode-ignore}.
+@end table
+
+
+@node Viewing differences, Invoking Ediff, Ignoring files, Commands
+@comment node-name, next, previous, up
+
+@section Viewing differences
+@cindex Diff
+@cindex Ediff
+@cindex Invoking ediff
+@cindex Conflicts, how to resolve them
+@cindex Viewing differences
+@kindex d - run @samp{cvs diff}
+@kindex b - diff backup file
+@findex cvs-mode-diff-cvs
+@findex cvs-mode-diff-backup
+@vindex cvs-diff-ignore-marks (variable)
+
+@table @kbd
+@item d
+Display a @samp{cvs diff} between the selected files and the RCS version
+that they are based on. @xref{Customization} describes how you can send
+flags to @samp{cvs diff}. If @var{cvs-diff-ignore-marks} is set to a
+non-@code{nil} value or if a prefix argument is given (but not both) any
+marked files will not be considered to be selected.
+(@code{cvs-mode-diff-cvs}).@refill
+
+@item b
+If CVS finds a conflict while merging two versions of a file (during a
+@samp{cvs update}, @pxref{Updating the directory}) it will save the
+original file in a file called @file{.#@var{FILE}.@var{VERSION}} where
+@var{FILE} is the name of the file, and @var{VERSION} is the RCS version
+number that your file was based on.@refill
+
+With the @kbd{b} command you can run a @samp{diff} on the files
+@file{.#@var{FILE}.@var{VERSION}} and @file{@var{FILE}}. You can get a
+context- or Unidiff by setting @samp{cvs-diff-flags} -
+@pxref{Customization}. This command only works on files that have
+status @samp{Conflict} or @samp{Merged}.@refill
+
+If @var{cvs-diff-ignore-marks} is set to a non-@code{nil} value or if a
+prefix argument is given (but not both) any marked files will not be
+considered to be selected. (@code{cvs-mode-diff-backup}).@refill
+@end table
+
+
+@node Invoking Ediff, Invoking Emerge, Viewing differences, Commands
+@comment node-name, next, previous, up
+
+@section Running ediff
+@cindex Ediff
+@cindex Invoking ediff
+@cindex Viewing differences
+@cindex Conflicts, resolving
+@cindex Resolving conflicts
+@kindex e - invoke @samp{ediff}
+@findex cvs-mode-ediff
+@findex run-ediff-from-cvs-buffer
+@findex cvs-old-ediff-interface
+
+@table @kbd
+@item e
+This command works
+slightly different depending on the version of @samp{ediff} and the file
+status.@refill
+
+With modern versions of @samp{ediff}, this command invokes
+@samp{run-ediff-from-cvs-buffer} on one file.@refill
+
+@strong{Note:} When the file status is @samp{Merged} or @samp{Conflict},
+CVS has already performed a merge. The resulting file is not used in
+any way if you use this command. If you use the @kbd{q} command inside
+@samp{ediff} (to successfully terminate a merge) the file that CVS
+created will be overwritten.@refill
+
+Older versions of @samp{ediff} use an interface similar to
+@samp{emerge}. The function @samp{cvs-old-ediff-interface} is invoked
+if the version of @samp{ediff} you have doesn't support
+@samp{run-ediff-from-cvs-buffer}. These older versions do not support
+merging of revisions.@refill
+
+@table @asis
+@item @samp{Modified}
+Run @samp{ediff-files} with your working file as file A, and the latest
+revision in the repository as file B.
+
+@item @samp{Merged}
+@itemx @samp{Conflict}
+Run @samp{ediff-files3} with your working file (as it was prior to your
+invocation of @samp{cvs-update}) as file A, the latest revision in the
+repository as file B, and the revision that you based your local
+modifications on as ancestor.
+
+@item @samp{Updated}
+@itemx @samp{Patched}
+Run @samp{ediff-files} with your working file as file A, and a given
+revision in the repository as file B. You are prompted for the revision
+to ediff against, and you may specify either a tag name or a numerical
+revision number (@pxref{Getting info about files}).
+@end table
+
+@end table
+
+@node Invoking Emerge, Reverting your buffers, Invoking Ediff, Commands
+@comment node-name, next, previous, up
+
+@section Running emerge
+@cindex Emerge
+@cindex Ediff
+@cindex Viewing differences
+@cindex Invoking emerge
+@cindex Conflicts, resolving
+@cindex Resolving conflicts
+@kindex E - invoke @samp{emerge}
+@findex cvs-mode-emerge
+
+@table @kbd
+@item E
+Invoke @samp{emerge} on one file. This command works slightly different
+depending on the file status.
+
+@table @asis
+@item @samp{Modified}
+Run @samp{emerge-files} with your working file as file A, and the latest
+revision in the repository as file B.
+
+@item @samp{Merged}
+@itemx @samp{Conflict}
+Run @samp{emerge-files-with-ancestor} with your working file (as it was
+prior to your invocation of @samp{cvs-update}) as file A, the latest
+revision in the repository as file B, and the revision that you based
+your local modifications on as ancestor.
+@end table
+
+@strong{Note:} When the file status is @samp{Merged} or @samp{Conflict},
+CVS has already performed a merge. The resulting file is not used in
+any way if you use this command. If you use the @kbd{q} command inside
+@samp{emerge} (to successfully terminate the merge) the file that CVS
+created will be overwritten.
+
+@end table
+
+
+@node Reverting your buffers, Miscellaneous commands, Invoking Emerge, Commands
+@comment node-name, next, previous, up
+
+@section Reverting your buffers
+@findex cvs-mode-revert-updated-buffers
+@kindex R - revert buffers
+@cindex Syncing buffers
+@cindex Reverting buffers
+
+@table @kbd
+@item R
+If you are editing (or just viewing) a file in a buffer, and that file
+is changed by CVS during a @samp{cvs-update}, all you have to do is type
+@kbd{R} in the *cvs* buffer to read in the new versions of the
+files.@refill
+
+All files that are @samp{Updated}, @samp{Merged} or in @samp{Conflict}
+are reverted from the disk. Any other files are ignored. Only files
+that you were already editing are read.@refill
+
+An error is signalled if you have modified the buffer since it was last
+changed. (@code{cvs-mode-revert-updated-buffers}).@refill
+@end table
+
+
+@node Miscellaneous commands, , Reverting your buffers, Commands
+@comment node-name, next, previous, up
+
+@section Miscellaneous commands
+@findex cvs-byte-compile-files
+@cindex Recompiling elisp files
+@cindex Byte compilation
+@cindex Getting rid of lock files
+@cindex Lock files
+@kindex q - bury the *cvs* buffer
+@findex bury-buffer
+
+@table @kbd
+@item M-x cvs-byte-compile-files
+Byte compile all selected files that end in .el.
+
+@item M-x cvs-delete-lock
+This command can be used in any buffer, and deletes the lock files that
+the *cvs* buffer informs you about. You should normally never have to
+use this command since CVS tries very carefully to always remove the
+lock files itself.
+
+You can only use this command when a message in the *cvs* buffer tells
+you so. You should wait a while before using this command in case
+someone else is running a cvs command.
+
+@item q
+Bury the *cvs* buffer. (@code{bury-buffer}).
+
+@end table
+
+
+@node Customization, Future enhancements, Commands, Top
+@comment node-name, next, previous, up
+
+@chapter Customization
+@vindex cvs-erase-input-buffer (variable)
+@vindex cvs-inhibit-copyright-message (variable)
+@vindex cvs-diff-flags (variable)
+@vindex cvs-diff-ignore-marks (variable)
+@vindex cvs-log-flags (variable)
+@vindex cvs-status-flags (variable)
+@vindex cvs-auto-remove-handled (variable)
+@vindex cvs-update-prog-output-skip-regexp (variable)
+@vindex cvs-cvsroot (variable)
+@vindex TMPDIR (environment variable)
+@vindex cvs-auto-revert-after-commit (variable)
+@vindex cvs-commit-buffer-require-final-newline (variable)
+@vindex cvs-sort-ignore-file (variable)
+@cindex Inhibiting the Copyright message.
+@cindex Copyright message, getting rid of it
+@cindex Getting rid of the Copyright message.
+@cindex Customization
+@cindex Variables, list of all
+@cindex Erasing the input buffer
+@cindex Context diff, how to get
+@cindex Unidiff, how to get
+@cindex Automatically remove handled files
+@cindex -u option in modules file
+@cindex Modules file (-u option)
+@cindex Update program (-u option in modules file)
+@cindex Reverting buffers after commit
+@cindex Require final newline
+@cindex Automatically inserting newline
+@cindex Commit message, inserting newline
+@cindex Sorting the .cvsignore file
+@cindex .cvsignore file, sorting
+@cindex Automatically sorting .cvsignore
+
+If you have an idea about any customization that would be handy but
+isn't present in this list, please tell me! @xref{Bugs} for info on how
+to reach me.@refill
+
+@table @samp
+@item cvs-erase-input-buffer
+If set to anything else than @code{nil} the edit buffer will be erased
+before you write the log message (@pxref{Committing changes}).
+
+@item cvs-inhibit-copyright-message
+The copyright message that is displayed on startup can be annoying after
+a while. Set this variable to @samp{t} if you want to get rid of it.
+(But don't set this to @samp{t} in the system defaults file - new users
+should see this message at least once).
+
+@item cvs-diff-flags
+A list of strings to pass as arguments to the @samp{cvs diff} and
+@samp{diff} programs. This is used by @samp{cvs-mode-diff-cvs} and
+@samp{cvs-mode-diff-backup} (key @kbd{b}, @pxref{Viewing differences}). If
+you prefer the Unidiff format you could add this line to your
+@file{.emacs} file:@refill
+
+@example
+(setq cvs-diff-flags '("-u"))
+@end example
+
+@item cvs-diff-ignore-marks
+If this variable is non-@code{nil} or if a prefix argument is given (but
+not both) to @samp{cvs-mode-diff-cvs} or @samp{cvs-mode-diff-backup}
+marked files are not considered selected.
+
+@item cvs-log-flags
+List of strings to send to @samp{cvs log}. Used by @samp{cvs-mode-log}
+(key @kbd{l}, @pxref{Getting info about files}).
+
+@item cvs-status-flags
+List of strings to send to @samp{cvs status}. Used by @samp{cvs-mode-status}
+(key @kbd{s}, @pxref{Getting info about files}).
+
+@item cvs-auto-remove-handled
+If this variable is set to any non-@code{nil} value
+@samp{cvs-mode-remove-handled} will be called every time you check in
+files, after the check-in is ready. @xref{Removing handled
+entries}.@refill
+
+@item cvs-auto-revert-after-commit
+If this variable is set to any non-@samp{nil} value any buffers you have
+that visit a file that is committed will be automatically reverted.
+This variable is default @samp{t}. @xref{Committing changes}.@refill
+
+@item cvs-update-prog-output-skip-regexp
+The @samp{-u} flag in the @file{modules} file can be used to run a command
+whenever a @samp{cvs update} is performed (see cvs(5)). This regexp
+is used to search for the last line in that output. It is normally set
+to @samp{"$"}. That setting is only correct if the command outputs
+nothing. Note that pcl-cvs will get very confused if the command
+outputs @emph{anything} to @samp{stderr}.
+
+@item cvs-cvsroot
+This variable can be set to override @samp{CVSROOT}. It should be a
+string. If it is set then everytime a cvs command is run it will be
+called as @samp{cvs -d @var{cvs-cvsroot}@dots{}} This can be useful if
+your site has several repositories.
+
+@item TMPDIR
+Pcl-cvs uses this @emph{environment variable} to decide where to put the
+temporary files it needs. It defaults to @file{/tmp} if it is not set.
+
+@item cvs-commit-buffer-require-final-newline
+When you enter a log message in the @samp{*cvs-commit-message*} buffer
+pcl-cvs will normally automatically insert a trailing newline, unless
+there already is one. This behavior can be controlled via
+@samp{cvs-commit-buffer-require-final-newline}. If it is @samp{t} (the
+default behavior), a newline will always be appended. If it is
+@samp{nil}, newlines will never be appended. Any other value causes
+pcl-cvs to ask the user whenever there is no trailing newline in the
+commit message buffer.
+
+@item cvs-sort-ignore-file
+If this variable is set to any non-@samp{nil} value the
+@file{.cvsignore} will always be sorted whenever you use
+@samp{cvs-mode-ignore} to add a file to it. This option is on by
+default.
+
+@end table
+
+
+@node Future enhancements, Bugs, Customization, Top
+@comment node-name, next, previous, up
+
+@chapter Future enhancements
+@cindex Enhancements
+
+Pcl-cvs is still under development and needs a number of enhancements to
+be called complete. Below is my current wish-list for future releases
+of pcl-cvs. Please, let me know which of these features you want most.
+They are listed below in approximately the order that I currently think
+I will implement them in.
+
+@itemize @bullet
+@item
+Rewritten parser code. There are many situations where pcl-cvs will
+fail to recognize the output from CVS. The situation could be greatly
+increased.
+
+@item
+@samp{cvs-status}. This will run @samp{cvs status} in a directory and
+produce a buffer that looks pretty much like the current *cvs* buffer.
+That buffer will include information for all version-controlled files.
+(There will be a simple keystroke to remove all "uninteresting" files,
+that is, files that are "Up-to-date"). In this new buffer you will be
+able to update a file, commit a file, et c. The big win with this is
+that you will be able to watch the differences between your current
+working file and the head revision in the repository before you update
+the file, and you can then choose to update it or let it wait for a
+while longer.
+
+@item
+Log mode. When this mode is finished you will be able to move around
+(using @kbd{n} and @kbd{p}) between the revisions of a file, mark two of
+them, and run a diff between them. You will be able to hide branches
+(similar to the way you can hide sub-paragraphs in outline-mode) and do
+merges between revisions. Other ideas about this are welcome.
+
+@item
+The current model for marks in the *cvs* buffer seems to be confusing.
+I am considering to use the VM model instead, where marks are normally
+inactive. To activate the mark, you issue a command like
+@samp{cvs-mode-next-command-uses-marks}. I might implement a flag so
+that you can use either version. Feedback on this before I start coding
+it is very welcome.
+
+@item
+It should be possible to run commands such as @samp{cvs log}, @samp{cvs
+status} and @samp{cvs commit} directly from a buffer containing a file,
+instead of having to @samp{cvs-update}. If the directory contains many
+files the @samp{cvs-update} can take quite some time, especially on a
+slow machine. I planed to put these kind of commands on the prefix
+@kbd{C-c C-v}, but that turned out to be used by for instance c++-mode.
+If you have any suggestions for a better prefix key, please let me know.
+
+@item
+Increased robustness. For instance, you can not currently press
+@kbd{C-g} when you are entering the description of a file that you are
+adding without confusing pcl-cvs.
+
+@item
+Support for multiple active *cvs* buffers.
+
+@item
+Dired support. I have an experimental @file{dired-cvs.el} that works
+together with CVS 1.2. Unfortunately I wrote it on top of a
+non-standard @file{dired.el}, so it must be rewritten.@refill
+
+@item
+An ability to send user-supplied options to all the cvs commands.
+
+@item
+Pcl-cvs is not at all clever about what it should do when @samp{cvs
+update} runs a program (due to the @samp{-u} option in the
+@file{modules} file --- see @samp{cvs(5)}). The current release uses a
+regexp to search for the end. At the very least that regexp should be
+configured for different modules. Tell me if you have any idea about
+what is the right thing to do. In a perfect world the program should
+also be allowed to print to @samp{stderr} without causing pcl-cvs to
+crash.
+@end itemize
+
+
+If you miss something in this wish-list, let me know! I don't promise
+that I will write it, but I will at least try to coordinate the efforts
+of making a good Emacs front end to CVS. See @xref{Bugs} for
+information about how to reach me.@refill
+
+So far, I have written most of pcl-cvs in my all-to-rare spare time. If
+you want pcl-cvs to be developed faster you can write a contract with
+Signum Support to do the extension. You can reach Signum Support by
+email to @samp{info@@signum.se} or via mail to Signum Support AB, Box
+2044, S-580 02 Linkoping, Sweden. Phone: +46 (0) 13 - 21 46 00. Fax:
++46 (0) 13 - 21 47 00.
+
+
+@node Bugs, COPYING, Future enhancements, Top
+@comment node-name, next, previous, up
+
+@chapter Bugs (known and unknown)
+@cindex Reporting bugs and ideas
+@cindex Bugs, how to report them
+@cindex Author, how to reach
+@cindex Email to the author
+@cindex Known bugs
+@cindex Bugs, known
+@cindex FAQ
+@cindex Problems, list of common
+
+If you find a bug or misfeature, don't hesitate to tell me! Send email
+to @samp{ceder@@lysator.liu.se}.
+
+If you have ideas for improvements, or if you have written some
+extensions to this package, I would like to hear from you. I hope that
+you find this package useful!
+
+Below is a partial list of currently known problems with pcl-cvs version
+1.05.
+
+@table @asis
+@item Commit causes Emacs to hang
+Emacs waits for the @samp{cvs commit} command to finish before you can
+do anything. If you start a background job from the loginfo file you
+must take care that it closes @samp{stdout} and @samp{stderr} if you do
+not want to wait for it. (You do that with @samp{background-command &>-
+2&>- &} if you are starting @samp{background-command} from a
+@samp{/bin/sh} shell script).
+
+Your emacs will also hang if there was a lock file in the repository.
+In this case you can type @kbd{C-g} to get control over your emacs
+again.
+
+@item Name clash in Emacs 19
+This is really a bug in Elib or the Emacs 19 distribution. Both Elib and
+Emacs 19.6 through at least 19.10 contains a file named
+@file{cookie.el}. One of the files will have to be renamed, and we are
+currently negotiating about which of the files to rename.
+
+@item Commands while cvs-update is running
+It is possible to type commands in the *cvs* buffer while the update is
+running, but error messages is all that you will get. The error
+messages should be better.
+
+@item Unexpected output from CVS
+Unexpected output from CVS confuses pcl-cvs. It will currently create a
+bug report that you can mail to me. It should do something more
+civilized.
+@end table
+
+
+@node COPYING, Function and Variable Index, Bugs, Top
+@comment node-name, next, previous, up
+
+@appendix GNU GENERAL PUBLIC LICENSE
+@c @include gpl.texinfo
+
+
+@node Function and Variable Index, Concept Index, COPYING, Top
+@comment node-name, next, previous, up
+
+@unnumbered Function and Variable Index
+
+@printindex fn
+
+
+@node Concept Index, Key Index, Function and Variable Index, Top
+@comment node-name, next, previous, up
+
+@unnumbered Concept Index
+
+@printindex cp
+
+
+@node Key Index, , Concept Index, Top
+@comment node-name, next, previous, up
+
+@unnumbered Key Index
+
+@printindex ky
+
+@summarycontents
+@contents
+@bye
OpenPOWER on IntegriCloud