diff options
author | peter <peter@FreeBSD.org> | 1996-08-20 23:46:10 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1996-08-20 23:46:10 +0000 |
commit | 8982e501c77217c860f79bba431f46a62b607a21 (patch) | |
tree | 70187fdf5be4cbefd0baf46bddac7e5e32c13c24 /contrib/cvs/tools | |
parent | 01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5 (diff) | |
download | FreeBSD-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/ChangeLog | 7 | ||||
-rw-r--r-- | contrib/cvs/tools/Makefile.in | 76 | ||||
-rw-r--r-- | contrib/cvs/tools/README | 5 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/ChangeLog | 891 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/INSTALL | 94 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/Makefile.in | 238 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/NEWS | 149 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/README | 25 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/pcl-cvs-lucid.el | 134 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/pcl-cvs-startup.el | 17 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/pcl-cvs.el | 3450 | ||||
-rw-r--r-- | contrib/cvs/tools/pcl-cvs/pcl-cvs.texinfo | 1565 |
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 |