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/contrib | |
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/contrib')
-rw-r--r-- | contrib/cvs/contrib/ChangeLog | 193 | ||||
-rw-r--r-- | contrib/cvs/contrib/Makefile.in | 134 | ||||
-rw-r--r-- | contrib/cvs/contrib/README | 106 | ||||
-rw-r--r-- | contrib/cvs/contrib/clmerge.pl | 152 | ||||
-rw-r--r-- | contrib/cvs/contrib/cln_hist.pl | 92 | ||||
-rw-r--r-- | contrib/cvs/contrib/commit_prep.pl | 216 | ||||
-rw-r--r-- | contrib/cvs/contrib/cvs_acls.pl | 143 | ||||
-rw-r--r-- | contrib/cvs/contrib/cvscheck.man | 53 | ||||
-rw-r--r-- | contrib/cvs/contrib/cvscheck.sh | 84 | ||||
-rw-r--r-- | contrib/cvs/contrib/cvshelp.man | 562 | ||||
-rw-r--r-- | contrib/cvs/contrib/descend.man | 115 | ||||
-rw-r--r-- | contrib/cvs/contrib/descend.sh | 116 | ||||
-rw-r--r-- | contrib/cvs/contrib/dirfns.shar | 481 | ||||
-rw-r--r-- | contrib/cvs/contrib/intro.doc | 112 | ||||
-rw-r--r-- | contrib/cvs/contrib/log.pl | 169 | ||||
-rw-r--r-- | contrib/cvs/contrib/log_accum.pl | 560 | ||||
-rw-r--r-- | contrib/cvs/contrib/mfpipe.pl | 88 | ||||
-rw-r--r-- | contrib/cvs/contrib/rcs-to-cvs.sh | 185 | ||||
-rw-r--r-- | contrib/cvs/contrib/rcs2log.sh | 592 | ||||
-rw-r--r-- | contrib/cvs/contrib/rcs2sccs.sh | 143 | ||||
-rw-r--r-- | contrib/cvs/contrib/rcslock.pl | 235 | ||||
-rw-r--r-- | contrib/cvs/contrib/sccs2rcs.csh | 277 |
22 files changed, 4808 insertions, 0 deletions
diff --git a/contrib/cvs/contrib/ChangeLog b/contrib/cvs/contrib/ChangeLog new file mode 100644 index 0000000..80db5b8 --- /dev/null +++ b/contrib/cvs/contrib/ChangeLog @@ -0,0 +1,193 @@ +Sun Apr 14 11:30:36 1996 Karl Fogel <kfogel@floss.red-bean.com> + + * Removed pcl-cvs/ subdir; see tools/ subdir in the top-level from + now on. + Added elib/ subdir. + + * Makefile.in (dist-dir): Removed all references to pcl-cvs/ + subdir. + +Wed Mar 6 10:20:28 1996 Greg A. Woods <woods@most.weird.com> + + * log_accum.pl: ($MAILER): use sendmail directly to allow other + headers to be included + * log_accum.pl (mail_notification): add support to allow settting + of Reply-To and Date header fields in the sent mail; remove $mailto + argument and use the global variable (as with $replyto). + * log_accum.pl: add -R option for mail_notification()'s optional + Reply-To value [default to $login] + +Fri Mar 1 01:51:56 1996 Benjamin J. Lee <benjamin@cyclic.com> + + * listener.c: added as mentioned in ../README.VMS + +Mon Feb 19 13:37:36 1996 Jim Kingdon <kingdon@harvey.cyclic.com> + + * README: Don't just tell people "we don't want your script"; tell + them what to do instead. + +Thu Feb 1 14:28:16 1996 Karl Fogel <kfogel@floss.red-bean.com> + + * Makefile.in (DISTFILES): added `rcs2sccs.sh', as mentioned in + README. + +Thu Jan 18 09:39:16 1996 Jim Kingdon <kingdon@harvey.cyclic.com> + + * README: Talk about submitting changes to contrib directory. + +Tue Nov 14 15:28:25 1995 Greg A. Woods <woods@most.weird.com> + + * README: fix some spelling and other typos + + * Makefile.in: if I need reminding to run cvsinit.... + +Tue Nov 14 13:47:40 1995 Greg A. Woods <woods@most.weird.com> + + * log_accum.pl: + - Fix 'cvs status' to use global -Qq options + - fix up a couple of comments, incl., my proper address + + * log.pl: add a CVSid and fix a couple of comments + +Sun Oct 1 02:02:57 1995 Peter Wemm <peter@haywire.dialix.com> + + * Makefile.in: supply a suffix rule to deal with .sh "source" + +Sat Jul 29 17:29:13 1995 James Kingdon <kingdon@harvey.cyclic.com> + + * log.pl: Use global options -Qq, not command options -Qq. + + * Makefile.in (install): Look for $(PROGS) and + $(CONTRIB_PROGS) in build dir, not srcdir. + +Fri Jul 28 19:48:45 1995 Paul Eggert <eggert@twinsun.com> + + * rcs2log.sh: Sync with latest Emacs snapshot. + +Thu Jul 27 20:29:30 1995 Jim Blandy <jimb@totoro.cyclic.com> + + * rcs2log.sh: import of initial WNT port work + +Fri Jul 14 22:38:44 1995 Jim Blandy <jimb@totoro.cyclic.com> + + * rcs-to-cvs.sh: Changes from David J. Mackenzie. + Set permissions on new repository files correctly. + Ignore *~ files. + +Thu Jul 13 23:04:12 CDT 1995 Jim Meyering (meyering@comco.com) + + * Makefile.in (.pl, .csh): *Never* redirect output directly to + the target (usu $@) of a rule. Instead, redirect to a temporary + file, and then move that temporary to the target. I chose to + name temporary files $@-t. Remember to be careful that the length + of the temporary file name not exceed the 14-character limit. + +Sun Jul 9 21:16:53 1995 Karl Fogel <kfogel@floss.cyclic.com> + + These are actually Greg Woods' changes: + + * clmerge.pl, cvscheck.sh, descend.sh, dirfns.shar, rcs-to-cvs.sh, + rcs2log.sh, sccs2rcs.csh: renamed from the corresponding files + sans extensions. + + * rcs2sccs.sh: new file. + +Sun Jul 9 19:03:00 1995 Greg A. Woods <woods@most.weird.com> + + * rcs2log.sh: oops, one more thing that should not have been + there. + - fix interpreter file syntax. + - remove "fix" for separating filenames and comments + + * Makefile.in: hmm... thought rcs2log was in RCS-5.7 for some + reason -- it's not, so we'll install it from here.... + - fix typo -- that's what you get for re-doing changes by hand! + - updates to support proper transformation and installation of + renamed files (from previous local changes) + + * .cvsignore: one more target noted... + + * sccs2rcs.csh: set up the interpreter file for updating by + Makefile (from previous local changes) + + * log_accum.pl, log.pl, commit_prep.pl: + - set up the interpreter file for updating by Makefile + - various modifications, updates, and enhancements + (from previous local changes) + + * rcslock.pl, mfpipe.pl, cvs_acls.pl, cln_hist.pl, clmerge.pl: + - set up the interpreter file for updating by Makefile + (from previous local changes) + - include changes from 1.5 here too, if any + + * README: + - remove extensions from filenames to match installed names + (from previous local changes) + + * .cvsignore: - added $(CONTRIB_PROGS) (from previous local changes) + + +Thu Jun 29 10:43:07 1995 James Kingdon <kingdon@harvey.cyclic.com> + + * Makefile.in (distclean): Also remove pcl-cvs/Makefile. + +Thu Jun 8 15:32:29 1995 Jim Kingdon (kingdon@lioth.cygnus.com) + + * intro.doc: Added. + * Makefile.in (DISTFILES): Add intro.doc. + +Sat May 27 08:46:00 1995 Jim Meyering (meyering@comco.com) + + * Makefile.in (Makefile): Regenerate only Makefile in current + directory when Makefile.in is out of date. Depend on ../config.status. + +Mon May 8 13:06:29 1995 Bryan O'Sullivan <bos@serpentine.com> + + * README: added an entry for ccvs-rsh.pl. + +Sun Apr 30 23:50:32 1995 Bryan O'Sullivan <bos@serpentine.com> + + * ccvs-rsh.pl: fixed a typo and added more flexible use of + CVS_PROXY_USER. + +Sun Apr 30 14:56:21 1995 Jim Blandy <jimb@totoro.bio.indiana.edu> + + * clmerge: Changes from Tom Tromey --- fix bug in date comparison + function. + +Sat Apr 29 20:53:08 1995 Bryan O'Sullivan <bos@serpentine.com> + + * ccvs-rsh.pl: created. See the file itself for documentation. + + * Makefile.in (DISTFILES): added ccvs-rsh.pl to the list of + files to install. + +Fri Apr 28 22:32:45 1995 Jim Blandy <jimb@totoro.bio.indiana.edu> + + * Makefile.in (DISTFILES): Brought up-to-date with current + directory contents. + (dist-dir): Renamed from dist-dir; use DISTDIR variable, passed + from parent. + +Mon Feb 13 13:32:07 1995 Jim Blandy <jimb@totoro.bio.indiana.edu> + + * rcs2log: rcs2log was originally in this tree; how did it get + deleted? Anyway, this is the version distributed with Emacs + 19.28, hacked to support CVS and Remote CVS. + +Mon Jul 26 13:18:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * rcs-to-cvs: Rewrite in sh. + +Wed Jul 14 21:16:40 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * rcs-to-cvs: Don't source .cshrc or hardcode paths. + Make respository dir if needed. Don't suppress errors + (such as prompts) from co. + +Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in, configure.in: removed traces of namesubdir, + -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced + copyrights to '92, changed some from Cygnus to FSF. + diff --git a/contrib/cvs/contrib/Makefile.in b/contrib/cvs/contrib/Makefile.in new file mode 100644 index 0000000..a29dec0 --- /dev/null +++ b/contrib/cvs/contrib/Makefile.in @@ -0,0 +1,134 @@ +# Makefile for GNU CVS contributed sources. +# 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 install the executables. +bindir = $(exec_prefix)/bin + +# Where to put the system-wide .cvsrc file +libdir = $(prefix)/lib + +# Where to put the manual pages. +mandir = $(prefix)/man + +# where to find command interpreters +perl_path = @perl_path@ +csh_path = @csh_path@ + +# Use cp if you don't have install. +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +DISTFILES = \ + ChangeLog README .cvsignore intro.doc \ + Makefile.in clmerge.pl cln_hist.pl commit_prep.pl cvs_acls.pl \ + cvscheck.sh cvscheck.man cvshelp.man descend.sh descend.man \ + dirfns.shar log.pl log_accum.pl mfpipe.pl rcs-to-cvs.sh rcs2log.sh \ + rcslock.pl sccs2rcs.csh rcs2sccs.sh + +# files installed in $(libdir)/cvs/contrib +# +CONTRIB_FILES = README intro.doc cvscheck.man + +# things we actually build and install.... +# +PROGS = rcs2log +CONTRIB_PROGS = clmerge cln_hist commit_prep cvs_acls cvscheck log log_accum \ + mfpipe rcs-to-cvs rcs2log rcslock sccs2rcs + +.SUFFIXES: .pl .sh .csh + +.pl: + rm -f $@ + sed -e 's,xPERL_PATHx,$(perl_path),' $< > $@-t + mv $@-t $@ + chmod +x $@ + +.csh: + rm -f $@ + sed -e 's,xCSH_PATHx,$(csh_path),' $< > $@-t + mv $@-t $@ + chmod +x $@ + +.sh: + rm -f $@ + cp $< $@ + chmod +x $@ + +all: Makefile $(PROGS) $(CONTRIB_PROGS) +.PHONY: all + +install: all $(libdir)/cvs/contrib + for f in $(CONTRIB_FILES) ; do\ + $(INSTALL_DATA) $(srcdir)/$$f $(libdir)/cvs/contrib/$$f; \ + done + for f in $(CONTRIB_PROGS) ; do\ + $(INSTALL_PROGRAM) $$f $(libdir)/cvs/contrib/$$f; \ + done + for f in $(PROGS) ; do\ + $(INSTALL_PROGRAM) $$f $(bindir)/$$f; \ + done + @echo "You might consider running 'cvsinit' to upgrade your repository(s)...." +.PHONY: install + +$(libdir)/cvs/contrib: + $(top_srcdir)/mkinstalldirs $(libdir)/cvs/contrib + +tags: +.PHONY: tags + +TAGS: +.PHONY: TAGS + +ls: + @echo $(DISTFILES) +.PHONY: ls + +clean: + /bin/rm -f *.o core +.PHONY: clean + +distclean: clean + rm -f Makefile elib/Makefile $(PROGS) $(CONTRIB_PROGS) +.PHONY: distclean + +realclean: distclean +.PHONY: realclean + +dist-dir: + mkdir ${DISTDIR} + for i in ${DISTFILES}; do \ + ln $(srcdir)/$${i} ${DISTDIR}; \ + done + cd elib; ${MAKE} dist-dir DISTDIR="../${DISTDIR}/elib" +.PHONY: dist-dir + +subdir = contrib +Makefile: ../config.status Makefile.in + cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status diff --git a/contrib/cvs/contrib/README b/contrib/cvs/contrib/README new file mode 100644 index 0000000..d453f8d --- /dev/null +++ b/contrib/cvs/contrib/README @@ -0,0 +1,106 @@ +$CVSid: @(#)README 1.12 94/09/25 $ + +This "contrib" directory is a place holder for code/scripts sent to +me by contributors around the world. This README file will be kept +up-to-date from release to release. BUT, I must point out that these +contributions are really, REALLY UNSUPPORTED. In fact, I probably +don't even know what they do. Nor do I guarantee to have tried them, +or ported them to work with this CVS distribution. If you have questions, +you might contact the author, but you should not necessarily expect +a reply. USE AT YOUR OWN RISK -- and all that stuff. + +"Unsupported" also means that noone has volunteered to accept and +check in changes to this directory. So submissions for new scripts to +add here are unlikely to be accepted. Suggested changes to the +existing scripts here conceivably might, but that isn't clear either. +The exception is pcl-cvs; that is more actively maintained (see +pcl-cvs/README). If you have some software that works with CVS that +you wish to offer it is suggested that you make it available by FTP or +HTTP and then announce it on the info-cvs mailing list. There is also +a web page of software related to CVS at +http://www.loria.fr/~molli/cvs-index.html which would presumably be +willing to list your software. + +Contents of this directory: + + README This file. + log A perl script suitable for including in your + $CVSROOT/CVSROOT/loginfo file for logging commit + changes. Includes the RCS revision of the change + as part of the log. + Contributed by Kevin Samborn <samborn@sunrise.com>. + pcl-cvs A directory that contains GNU Emacs lisp code which + implements a CVS-mode for emacs. + Contributed by Per Cederqvist <ceder@lysator.liu.se>. + commit_prep A perl script, to be combined with log_accum.pl, to + log_accum provide for a way to combine the individual log + messages of a multi-directory "commit" into a + single log message, and mail the result somewhere. + Can also do other checks for $Id and that you are + committing the correct revision of the file. + Read the comments carefully. + Contributed by David Hampton <hampton@cisco.com>. + mfpipe Another perl script for logging. Allows you to + pipe the log message to a file and/or send mail + to some alias. + Contributed by John Clyne <clyne@niwot.scd.ucar.edu>. + rcs-to-cvs Script to import sources that may have been under + RCS control already. + Contributed by Per Cederqvist <ceder@lysator.liu.se>. + cvscheck Identifies files added, changed, or removed in a + cvscheck.man checked out CVS tree; also notices unknown files. + Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net> + cvshelp.man An introductory manual page written by Lowell Skoog + <fluke!lowell@uunet.uu.net>. It is most likely + out-of-date relative to CVS 1.3, but still may be + useful. + dirfns A shar file which contains some code that might + help your system support opendir/readdir/closedir, + if it does not already. + Copied from the C-News distribution. + rcslock A perl script that can be added to your commitinfo + file that tries to determine if your RCS file is + currently locked by someone else, as might be the + case for a binary file. + Contributed by John Rouillard <rouilj@cs.umb.edu>. + ccvs-rsh A Perl script which allows "rsh pipelines" to + be built in order to use Cyclic CVS from + behind some varieties of firewall. + cvs_acls A perl script that implements Access Control Lists + by using the "commitinfo" hook provided with the + "cvs commit" command. + Contributed by David G. Grubbs <dgg@ksr.com>. + descend A shell script that can be used to recursively + descend.man descend through a directory. In CVS 1.2, this was + very useful, since many of the commands were not + recursive. In CVS 1.3 (and later), however, most of + the commands are recursive. However, this may still + come in handy. + Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net> + cln_hist A perl script to compress your + $CVSROOT/CVSROOT/history file, as it can grow quite + large after extended use. + Contributed by David G. Grubbs <dgg@ksr.com> + sccs2rcs A C-shell script that can convert (some) SCCS files + into RCS files, retaining the info contained in the + SCCS file (like dates, author, and log message). + Contributed by Ken Cox <kenstir@viewlogic.com>. + intro.doc A user's view of what you need to know to get + started with CVS. + Contributed by <Steven.Pemberton@cwi.nl>. + rcs2sccs A shell script to convert simple RCS files into + SCCS files, originally gleaned off the network + somewhere (originally by "kenc") and modified by + Jerry Jelinek <jerry@rmtc.Central.Sun.COM> and + Brian Berliner <berliner@sun.com> to increase + robustness and add support for one-level of branches. + rcs2log A shell script to create a ChangeLog-format file + given only a set of RCS files. + Contributed by Paul Eggert <eggert@twinsun.com>. + clmerge A perl script to handle merge conflicts in GNU + style ChangeLog files . + Contributed by Tom Tromey <tromey@busco.lanl.gov>. + listener A program which listens to a TCP port, authenticates + by hostname, then runs a subprocess whose input/output + is redirected through the port. + Contributed by Benjamin J. Lee <benjamin@cyclic.com> diff --git a/contrib/cvs/contrib/clmerge.pl b/contrib/cvs/contrib/clmerge.pl new file mode 100644 index 0000000..ac81371 --- /dev/null +++ b/contrib/cvs/contrib/clmerge.pl @@ -0,0 +1,152 @@ +#! xPERL_PATHx + +# Merge conflicted ChangeLogs +# tromey Mon Aug 15 1994 + +# Usage is: +# +# cl-merge [-i] file ... +# +# With -i, it works in place (backups put in a ~ file). Otherwise the +# merged ChangeLog is printed to stdout. + +# Please report any bugs to me. I wrote this yesterday, so there are no +# guarantees about its performance. I recommend checking its output +# carefully. If you do send a bug report, please include the failing +# ChangeLog, so I can include it in my test suite. +# +# Tom +# --- +# tromey@busco.lanl.gov Member, League for Programming Freedom +# Sadism and farce are always inexplicably linked. +# -- Alexander Theroux + + +# Month->number mapping. Used for sorting. +%months = ('Jan', 0, + 'Feb', 1, + 'Mar', 2, + 'Apr', 3, + 'May', 4, + 'Jun', 5, + 'Jul', 6, + 'Aug', 7, + 'Sep', 8, + 'Oct', 9, + 'Nov', 10, + 'Dec', 11); + +# If '-i' is given, do it in-place. +if ($ARGV[0] eq '-i') { + shift (@ARGV); + $^I = '~'; +} + +$lastkey = ''; +$lastval = ''; +$conf = 0; +%conflist = (); + +$tjd = 0; + +# Simple state machine. The states: +# +# 0 Not in conflict. Just copy input to output. +# 1 Beginning an entry. Next non-blank line is key. +# 2 In entry. Entry beginner transitions to state 1. +while (<>) { + if (/^<<<</ || /^====/) { + # Start of a conflict. + + # Copy last key into array. + if ($lastkey ne '') { + $conflist{$lastkey} = $lastval; + + $lastkey = ''; + $lastval = ''; + } + + $conf = 1; + } elsif (/^>>>>/) { + # End of conflict. Output. + + # Copy last key into array. + if ($lastkey ne '') { + $conflist{$lastkey} = $lastval; + + $lastkey = ''; + $lastval = ''; + } + + foreach (reverse sort clcmp keys %conflist) { + print STDERR "doing $_" if $tjd; + print $_; + print $conflist{$_}; + } + + $lastkey = ''; + $lastval = ''; + $conf = 0; + %conflist = (); + } elsif ($conf == 1) { + # Beginning an entry. Skip empty lines. Error if not a real + # beginner. + if (/^$/) { + # Empty line; just skip at this point. + } elsif (/^[MTWFS]/) { + # Looks like the name of a day; assume opener and move to + # "in entry" state. + $lastkey = $_; + $conf = 2; + print STDERR "found $_" if $tjd; + } else { + die ("conflict crosses entry boundaries: $_"); + } + } elsif ($conf == 2) { + # In entry. Copy into variable until we see beginner line. + if (/^[MTWFS]/) { + # Entry beginner line. + + # Copy last key into array. + if ($lastkey ne '') { + $conflist{$lastkey} = $lastval; + + $lastkey = ''; + $lastval = ''; + } + + $lastkey = $_; + print STDERR "found $_" if $tjd; + $lastval = ''; + } else { + $lastval .= $_; + } + } else { + # Just copy. + print; + } +} + +# Compare ChangeLog time strings like <=>. +# +# 0 1 2 3 +# Thu Aug 11 13:22:42 1994 Tom Tromey (tromey@creche.colorado.edu) +# 0123456789012345678901234567890 +# +sub clcmp { + # First check year. + $r = substr ($a, 20, 4) <=> substr ($b, 20, 4); + + # Now check month. + $r = $months{substr ($a, 4, 3)} <=> $months{substr ($b, 4, 3)} if !$r; + + # Now check day. + $r = substr ($a, 8, 2) <=> substr ($b, 8, 2) if !$r; + + # Now check time (3 parts). + $r = substr ($a, 11, 2) <=> substr ($b, 11, 2) if !$r; + $r = substr ($a, 14, 2) <=> substr ($b, 14, 2) if !$r; + $r = substr ($a, 17, 2) <=> substr ($b, 17, 2) if !$r; + + $r; +} diff --git a/contrib/cvs/contrib/cln_hist.pl b/contrib/cvs/contrib/cln_hist.pl new file mode 100644 index 0000000..ff49d0a --- /dev/null +++ b/contrib/cvs/contrib/cln_hist.pl @@ -0,0 +1,92 @@ +#! xPERL_PATHx +# -*-Perl-*- +# +# $Id: cln_hist.pl,v 1.2 1995/07/10 02:01:26 kfogel Exp $ +# Contributed by David G. Grubbs <dgg@ksr.com> +# +# Clean up the history file. 10 Record types: MAR OFT WUCG +# +# WUCG records are thrown out. +# MAR records are retained. +# T records: retain only last tag with same combined tag/module. +# +# Two passes: Walk through the first time and remember the +# 1. Last Tag record with same "tag" and "module" names. +# 2. Last O record with unique user/module/directory, unless followed +# by a matching F record. +# + +$r = $ENV{"CVSROOT"}; +$c = "$r/CVSROOT"; +$h = "$c/history"; + +eval "print STDERR \$die='Unknown parameter $1\n' if !defined \$$1; \$$1=\$';" + while ($ARGV[0] =~ /^(\w+)=/ && shift(@ARGV)); +exit 255 if $die; # process any variable=value switches + +%tags = (); +%outs = (); + +# +# Move history file to safe place and re-initialize a new one. +# +rename($h, "$h.bak"); +open(XX, ">$h"); +close(XX); + +# +# Pass1 -- remember last tag and checkout. +# +open(HIST, "$h.bak"); +while (<HIST>) { + next if /^[MARWUCG]/; + + # Save whole line keyed by tag|module + if (/^T/) { + @tmp = split(/\|/, $_); + $tags{$tmp[4] . '|' . $tmp[5]} = $_; + } + # Save whole line + if (/^[OF]/) { + @tmp = split(/\|/, $_); + $outs{$tmp[1] . '|' . $tmp[2] . '|' . $tmp[5]} = $_; + } +} + +# +# Pass2 -- print out what we want to save. +# +open(SAVE, ">$h.work"); +open(HIST, "$h.bak"); +while (<HIST>) { + next if /^[FWUCG]/; + + # If whole line matches saved (i.e. "last") one, print it. + if (/^T/) { + @tmp = split(/\|/, $_); + next if $tags{$tmp[4] . '|' . $tmp[5]} ne $_; + } + # Save whole line + if (/^O/) { + @tmp = split(/\|/, $_); + next if $outs{$tmp[1] . '|' . $tmp[2] . '|' . $tmp[5]} ne $_; + } + + print SAVE $_; +} + +# +# Put back the saved stuff +# +system "cat $h >> $h.work"; + +if (-s $h) { + rename ($h, "$h.interim"); + print "history.interim has non-zero size.\n"; +} else { + unlink($h); +} + +rename ("$h.work", $h); + +exit(0); diff --git a/contrib/cvs/contrib/commit_prep.pl b/contrib/cvs/contrib/commit_prep.pl new file mode 100644 index 0000000..5272c04 --- /dev/null +++ b/contrib/cvs/contrib/commit_prep.pl @@ -0,0 +1,216 @@ +#! xPERL_PATHx +# -*-Perl-*- +# +#ident "@(#)cvs/contrib:$Name: $:$Id: commit_prep.pl,v 1.2 1995/07/10 02:01:29 kfogel Exp $" +# +# Perl filter to handle pre-commit checking of files. This program +# records the last directory where commits will be taking place for +# use by the log_accum.pl script. For new files, it forces the +# existence of a RCS "Id" keyword in the first ten lines of the file. +# For existing files, it checks version number in the "Id" line to +# prevent losing changes because an old version of a file was copied +# into the direcory. +# +# Possible future enhancements: +# +# Check for cruft left by unresolved conflicts. Search for +# "^<<<<<<<$", "^-------$", and "^>>>>>>>$". +# +# Look for a copyright and automagically update it to the +# current year. [[ bad idea! -- woods ]] +# +# +# Contributed by David Hampton <hampton@cisco.com> +# +# Hacked on lots by Greg A. Woods <woods@web.net> + +# +# Configurable options +# + +# Constants (remember to protect strings from RCS keyword substitution) +# +$LAST_FILE = "/tmp/#cvs.lastdir"; # must match name in log_accum.pl +$ENTRIES = "CVS/Entries"; + +# Patterns to find $Log keywords in files +# +$LogString1 = "\\\$\\Log: .* \\\$"; +$LogString2 = "\\\$\\Log\\\$"; +$NoLog = "%s - contains an RCS \$Log keyword. It must not!\n"; + +# pattern to match an RCS Id keyword line with an existing ID +# +$IDstring = "\"@\\(#\\)[^:]*:.*\\\$\Id: .*\\\$\""; +$NoId = " +%s - Does not contain a properly formatted line with the keyword \"Id:\". + I.e. no lines match \"" . $IDstring . "\". + Please see the template files for an example.\n"; + +# pattern to match an RCS Id keyword line for a new file (i.e. un-expanded) +# +$NewId = "\"@(#)[^:]*:.*\\$\Id\\$\""; + +$NoName = " +%s - The ID line should contain only \"@(#)module/path:\$Name\$:\$\Id\$\" + for a newly created file.\n"; + +$BadName = " +%s - The file name '%s' in the ID line does not match + the actual filename.\n"; + +$BadVersion = " +%s - How dare you!!! You replaced your copy of the file '%s', + which was based upon version %s, with an %s version based + upon %s. Please move your '%s' out of the way, perform an + update to get the current version, and them merge your changes + into that file, then try the commit again.\n"; + +# +# Subroutines +# + +sub write_line { + local($filename, $line) = @_; + open(FILE, ">$filename") || die("Cannot open $filename, stopped"); + print(FILE $line, "\n"); + close(FILE); +} + +sub check_version { + local($i, $id, $rname, $version); + local($filename, $cvsversion) = @_; + + open(FILE, "<$filename") || return(0); + + @all_lines = (); + $idpos = -1; + $newidpos = -1; + for ($i = 0; <FILE>; $i++) { + chop; + push(@all_lines, $_); + if ($_ =~ /$IDstring/) { + $idpos = $i; + } + if ($_ =~ /$NewId/) { + $newidpos = $i; + } + } + + if (grep(/$LogString1/, @all_lines) || grep(/$LogString2/, @all_lines)) { + print STDERR sprintf($NoLog, $filename); + return(1); + } + + if ($debug != 0) { + print STDERR sprintf("file = %s, version = %d.\n", $filename, $cvsversion{$filename}); + } + + if ($cvsversion{$filename} == 0) { + if ($newidpos != -1 && $all_lines[$newidpos] !~ /$NewId/) { + print STDERR sprintf($NoName, $filename); + return(1); + } + return(0); + } + + if ($idpos == -1) { + print STDERR sprintf($NoId, $filename); + return(1); + } + + $line = $all_lines[$idpos]; + $pos = index($line, "Id: "); + if ($debug != 0) { + print STDERR sprintf("%d in '%s'.\n", $pos, $line); + } + ($id, $rname, $version) = split(' ', substr($line, $pos)); + if ($rname ne "$filename,v") { + print STDERR sprintf($BadName, $filename, substr($rname, 0, length($rname)-2)); + return(1); + } + if ($cvsversion{$filename} < $version) { + print STDERR sprintf($BadVersion, $filename, $filename, $cvsversion{$filename}, + "newer", $version, $filename); + return(1); + } + if ($cvsversion{$filename} > $version) { + print STDERR sprintf($BadVersion, $filename, $filename, $cvsversion{$filename}, + "older", $version, $filename); + return(1); + } + return(0); +} + +# +# Main Body +# + +$id = getpgrp(); # You *must* use a shell that does setpgrp()! + +# Check each file (except dot files) for an RCS "Id" keyword. +# +$check_id = 0; + +# Record the directory for later use by the log_accumulate stript. +# +$record_directory = 0; + +# parse command line arguments +# +while (@ARGV) { + $arg = shift @ARGV; + + if ($arg eq '-d') { + $debug = 1; + print STDERR "Debug turned on...\n"; + } elsif ($arg eq '-c') { + $check_id = 1; + } elsif ($arg eq '-r') { + $record_directory = 1; + } else { + push(@files, $arg); + } +} + +$directory = shift @files; + +if ($debug != 0) { + print STDERR "dir - ", $directory, "\n"; + print STDERR "files - ", join(":", @files), "\n"; + print STDERR "id - ", $id, "\n"; +} + +# Suck in the CVS/Entries file +# +open(ENTRIES, $ENTRIES) || die("Cannot open $ENTRIES.\n"); +while (<ENTRIES>) { + local($filename, $version) = split('/', substr($_, 1)); + $cvsversion{$filename} = $version; +} + +# Now check each file name passed in, except for dot files. Dot files +# are considered to be administrative files by this script. +# +if ($check_id != 0) { + $failed = 0; + foreach $arg (@files) { + if (index($arg, ".") == 0) { + next; + } + $failed += &check_version($arg); + } + if ($failed) { + print STDERR "\n"; + exit(1); + } +} + +# Record this directory as the last one checked. This will be used +# by the log_accumulate script to determine when it is processing +# the final directory of a multi-directory commit. +# +if ($record_directory != 0) { + &write_line("$LAST_FILE.$id", $directory); +} +exit(0); diff --git a/contrib/cvs/contrib/cvs_acls.pl b/contrib/cvs/contrib/cvs_acls.pl new file mode 100644 index 0000000..bcb544d --- /dev/null +++ b/contrib/cvs/contrib/cvs_acls.pl @@ -0,0 +1,143 @@ +#! xPERL_PATHx +# -*-Perl-*- +# +# $Id: cvs_acls.pl,v 1.2 1995/07/10 02:01:33 kfogel Exp $ +# +# Access control lists for CVS. dgg@ksr.com (David G. Grubbs) +# +# CVS "commitinfo" for matching repository names, running the program it finds +# on the same line. More information is available in the CVS man pages. +# +# ==== INSTALLATION: +# +# To use this program as I intended, do the following four things: +# +# 0. Install PERL. :-) +# +# 1. Put one line, as the *only* non-comment line, in your commitinfo file: +# +# DEFAULT /usr/local/bin/cvs_acls +# +# 2. Install this file as /usr/local/bin/cvs_acls and make it executable. +# +# 3. Create a file named $CVSROOT/CVSROOT/avail. +# +# ==== FORMAT OF THE avail FILE: +# +# The avail file determines whether you may commit files. It contains lines +# read from top to bottom, keeping track of a single "bit". The "bit" +# defaults to "on". It can be turned "off" by "unavail" lines and "on" by +# "avail" lines. ==> Last one counts. +# +# Any line not beginning with "avail" or "unavail" is ignored. +# +# Lines beginning with "avail" or "unavail" are assumed to be '|'-separated +# triples: (All spaces and tabs are ignored in a line.) +# +# {avail.*,unavail.*} [| user,user,... [| repos,repos,...]] +# +# 1. String starting with "avail" or "unavail". +# 2. Optional, comma-separated list of usernames. +# 3. Optional, comma-separated list of repository pathnames. +# These are pathnames relative to $CVSROOT. They can be directories or +# filenames. A directory name allows access to all files and +# directories below it. +# +# Example: (Text from the ';;' rightward may not appear in the file.) +# +# unavail ;; Make whole repository unavailable. +# avail|dgg ;; Except for user "dgg". +# avail|fred, john|bin/ls ;; Except when "fred" or "john" commit to +# ;; the module whose repository is "bin/ls" +# +# PROGRAM LOGIC: +# +# CVS passes to @ARGV an absolute directory pathname (the repository +# appended to your $CVSROOT variable), followed by a list of filenames +# within that directory. +# +# We walk through the avail file looking for a line that matches both +# the username and repository. +# +# A username match is simply the user's name appearing in the second +# column of the avail line in a space-or-comma separate list. +# +# A repository match is either: +# - One element of the third column matches $ARGV[0], or some +# parent directory of $ARGV[0]. +# - Otherwise *all* file arguments ($ARGV[1..$#ARGV]) must be +# in the file list in one avail line. +# - In other words, using directory names in the third column of +# the avail file allows committing of any file (or group of +# files in a single commit) in the tree below that directory. +# - If individual file names are used in the third column of +# the avail file, then files must be committed individually or +# all files specified in a single commit must all appear in +# third column of a single avail line. +# + +$debug = 0; +$cvsroot = $ENV{'CVSROOT'}; +$availfile = $cvsroot . "/CVSROOT/avail"; +$myname = $ENV{"USER"} if !($myname = $ENV{"LOGNAME"}); + +eval "print STDERR \$die='Unknown parameter $1\n' if !defined \$$1; \$$1=\$';" + while ($ARGV[0] =~ /^(\w+)=/ && shift(@ARGV)); +exit 255 if $die; # process any variable=value switches + +die "Must set CVSROOT\n" if !$cvsroot; +($repos = shift) =~ s:^$cvsroot/::; +grep($_ = $repos . '/' . $_, @ARGV); + +print "$$ Repos: $repos\n","$$ ==== ",join("\n$$ ==== ",@ARGV),"\n" if $debug; + +$exit_val = 0; # Good Exit value + +$universal_off = 0; +open (AVAIL, $availfile) || exit(0); # It is ok for avail file not to exist +while (<AVAIL>) { + chop; + next if /^\s*\#/; + next if /^\s*$/; + ($flagstr, $u, $m) = split(/[\s,]*\|[\s,]*/, $_); + + # Skip anything not starting with "avail" or "unavail" and complain. + (print "Bad avail line: $_\n"), next + if ($flagstr !~ /^avail/ && $flagstr !~ /^unavail/); + + # Set which bit we are playing with. ('0' is OK == Available). + $flag = (($& eq "avail") ? 0 : 1); + + # If we find a "universal off" flag (i.e. a simple "unavail") remember it + $universal_off = 1 if ($flag && !$u && !$m); + + # $myname considered "in user list" if actually in list or is NULL + $in_user = (!$u || grep ($_ eq $myname, split(/[\s,]+/,$u))); + print "$$ \$myname($myname) in user list: $_\n" if $debug && $in_user; + + # Module matches if it is a NULL module list in the avail line. If module + # list is not null, we check every argument combination. + if (!($in_repo = !$m)) { + @tmp = split(/[\s,]+/,$m); + for $j (@tmp) { + # If the repos from avail is a parent(or equal) dir of $repos, OK + $in_repo = 1, last if ($repos eq $j || $repos =~ /^$j\//); + } + if (!$in_repo) { + $in_repo = 1; + for $j (@ARGV) { + last if !($in_repo = grep ($_ eq $j, @tmp)); + } + } + } + print "$$ \$repos($repos) in repository list: $_\n" if $debug && $in_repo; + + $exit_val = $flag if ($in_user && $in_repo); + print "$$ ==== \$exit_val = $exit_val\n$$ ==== \$flag = $flag\n" if $debug; +} +close(AVAIL); +print "$$ ==== \$exit_val = $exit_val\n" if $debug; +print "**** Access denied: Insufficient Karma ($myname|$repos)\n" if $exit_val; +print "**** Access allowed: Personal Karma exceeds Environmental Karma.\n" + if $universal_off && !$exit_val; +exit($exit_val); diff --git a/contrib/cvs/contrib/cvscheck.man b/contrib/cvs/contrib/cvscheck.man new file mode 100644 index 0000000..61a064a --- /dev/null +++ b/contrib/cvs/contrib/cvscheck.man @@ -0,0 +1,53 @@ +.\" $Id: cvscheck.man,v 1.1.1.3 1995/08/28 16:20:24 jimb Exp $ +.\" Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net> +.TH CVSCHECK LOCAL "4 March 1991" FLUKE +.SH NAME +cvscheck \- identify files added, changed, or removed in a CVS working +directory +.SH SYNOPSIS +.B cvscheck +.SH DESCRIPTION +This command is a housekeeping aid. It should be run in a working +directory that has been checked out using CVS. It identifies files +that have been added, changed, or removed in the working directory, but +not CVS +.BR commit ted. +It also determines whether the files have been CVS +.BR add ed +or CVS +.BR remove d. +For directories, this command determines only whether they have been +.BR add ed. +It operates in the current directory only. +.LP +This command provides information that is available using CVS +.B status +and CVS +.BR diff . +The advantage of +.B cvscheck +is that its output is very concise. It saves you the strain (and +potential error) of interpreting the output of CVS +.B status +and +.BR diff . +.LP +See +.BR cvs (local) +or +.BR cvshelp (local) +for instructions on how to add or remove a file or directory in a +CVS-controlled package. +.SH DIAGNOSTICS +The exit status is 0 if no files have been added, changed, or removed +from the current directory. Otherwise, the command returns a count of +the adds, changes, and deletes. +.SH SEE ALSO +.BR cvs (local), +.BR cvshelp (local) +.SH AUTHOR +Lowell Skoog +.br +Software Technology Group +.br +Technical Computing diff --git a/contrib/cvs/contrib/cvscheck.sh b/contrib/cvs/contrib/cvscheck.sh new file mode 100644 index 0000000..96dba6e --- /dev/null +++ b/contrib/cvs/contrib/cvscheck.sh @@ -0,0 +1,84 @@ +#! /bin/sh +# $Id: cvscheck.sh,v 1.1 1995/07/10 02:26:29 kfogel Exp $ +# +# cvscheck - identify files added, changed, or removed +# in CVS working directory +# +# Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net> +# +# This program should be run in a working directory that has been +# checked out using CVS. It identifies files that have been added, +# changed, or removed in the working directory, but not "cvs +# committed". It also determines whether the files have been "cvs +# added" or "cvs removed". For directories, it is only practical to +# determine whether they have been added. + +name=cvscheck +changes=0 + +# If we can't run CVS commands in this directory +cvs status . > /dev/null 2>&1 +if [ $? != 0 ] ; then + + # Bail out + echo "$name: there is no version here; bailing out" 1>&2 + exit 1 +fi + +# Identify files added to working directory +for file in .* * ; do + + # Skip '.' and '..' + if [ $file = '.' -o $file = '..' ] ; then + continue + fi + + # If a regular file + if [ -f $file ] ; then + if cvs status $file | grep -s '^From:[ ]*New file' ; then + echo "file added: $file - not CVS committed" + changes=`expr $changes + 1` + elif cvs status $file | grep -s '^From:[ ]*no entry for' ; then + echo "file added: $file - not CVS added, not CVS committed" + changes=`expr $changes + 1` + fi + + # Else if a directory + elif [ -d $file -a $file != CVS.adm ] ; then + + # Move into it + cd $file + + # If CVS commands don't work inside + cvs status . > /dev/null 2>&1 + if [ $? != 0 ] ; then + echo "directory added: $file - not CVS added" + changes=`expr $changes + 1` + fi + + # Move back up + cd .. + fi +done + +# Identify changed files +changedfiles=`cvs diff | egrep '^diff' | awk '{print $3}'` +for file in $changedfiles ; do + echo "file changed: $file - not CVS committed" + changes=`expr $changes + 1` +done + +# Identify files removed from working directory +removedfiles=`cvs status | egrep '^File:[ ]*no file' | awk '{print $4}'` + +# Determine whether each file has been cvs removed +for file in $removedfiles ; do + if cvs status $file | grep -s '^From:[ ]*-' ; then + echo "file removed: $file - not CVS committed" + else + echo "file removed: $file - not CVS removed, not CVS committed" + fi + changes=`expr $changes + 1` +done + +exit $changes diff --git a/contrib/cvs/contrib/cvshelp.man b/contrib/cvs/contrib/cvshelp.man new file mode 100644 index 0000000..2cfae1f --- /dev/null +++ b/contrib/cvs/contrib/cvshelp.man @@ -0,0 +1,562 @@ +.\" $Id: cvshelp.man,v 1.1.1.3 1995/08/28 16:20:28 jimb Exp $ +.\" Contributed by Lowell Skoog <fluke!lowell@uunet.uu.net> +.\" Full space in nroff; half space in troff +.de SP +.if n .sp +.if t .sp .5 +.. +.\" Start a command example +.de XS +.SP +.in +.5i +.ft B +.nf +.. +.\" End a command example +.de XE +.fi +.ft P +.in -.5i +.SP +.. +.TH CVSHELP LOCAL "17 March 1991" FLUKE +.SH NAME +cvshelp \- advice on using the Concurrent Versions System +.SH DESCRIPTION +This man page is based on experience using CVS. +It is bound to change as we gain more experience. +If you come up with better advice than is found here, +contact the Software Technology +Group and we will add it to this page. +.SS "Getting Started" +Use the following steps to prepare to use CVS: +.TP +\(bu +Take a look at the CVS manual page to see what it can do for you, and +if it fits your environment (or can possibly be made to fit your +environment). +.XS +man cvs +.XE +If things look good, continue on... +.TP +\(bu +Setup the master source repository. Choose a directory with +ample disk space available for source files. This is where the RCS +`,v' files will be stored. Say you choose +.B /src/master +as the root +of your source repository. Make the +.SB CVSROOT.adm +directory in the root of the source repository: +.XS +mkdir /src/master/CVSROOT.adm +.XE +.TP +\(bu +Populate this directory with the +.I loginfo +and +.I modules +files from the +.B "/usr/doc/local/cvs" +directory. Edit these files to reflect your local source repository +environment \- they may be quite small initially, but will grow as +sources are added to your source repository. Turn these files into +RCS controlled files: +.XS +cd /src/master/CVSROOT.adm +ci \-m'Initial loginfo file' loginfo +ci \-m'Initial modules file' modules +.XE +.TP +\(bu +Run the command: +.XS +mkmodules /src/master/CVSROOT.adm +.XE +This will build the +.BR ndbm (3) +file for the modules database. +.TP +\(bu +Remember to edit the +.I modules +file manually when sources are checked +in with +.B checkin +or CVS +.BR add . +A copy of the +.I modules +file for editing can be retrieved with the command: +.XS +cvs checkout CVSROOT.adm +.XE +.TP +\(bu +Have all users of the CVS system set the +.SM CVSROOT +environment variable appropriately to reflect the placement of your +source repository. If the above example is used, the following +commands can be placed in a +.I .login +or +.I .profile +file: +.XS +setenv CVSROOT /src/master +.XE +for csh users, and +.XS +CVSROOT=/src/master; export CVSROOT +.XE +for sh users. +.SS "Placing Locally Written Sources Under CVS Control" +Say you want to place the `whizbang' sources under +CVS control. Say further that the sources have never +been under revision control before. +.TP +\(bu +Move the source hierarchy (lock, stock, and barrel) +into the master source repository: +.XS +mv ~/whizbang $CVSROOT +.XE +.TP +\(bu +Clean out unwanted object files: +.XS +cd $CVSROOT/whizbang +make clean +.XE +.TP +\(bu +Turn every file in the hierarchy into an RCS controlled file: +.XS +descend \-f 'ci \-t/dev/null \-m"Placed under CVS control" \-nV\fR\fIx\fR\fB_\fR\fIy\fR\fB *' +.XE +In this example, the initial release tag is \fBV\fIx\fB_\fIy\fR, +representing version \fIx\fR.\fIy\fR. +.LP +You can use CVS on sources that are already under RCS control. +The following example shows how. +In this example, the source package is called `skunkworks'. +.TP +\(bu +Move the source hierarchy into the master source +repository: +.XS +mv ~/skunkworks $CVSROOT +.XE +.TP +\(bu +Clean out unwanted object files: +.XS +cd $CVSROOT/skunkworks +make clean +.XE +.TP +\(bu +Clean out unwanted working files, leaving only the RCS `,v' files: +.XS +descend \-r rcsclean +.XE +Note: If any working files have been checked out and changed, +.B rcsclean +will fail. Check in the modified working files +and run the command again. +.TP +\(bu +Get rid of +.SB RCS +subdirectories. CVS does not use them. +.XS +descend \-r \-f 'mv RCS/*,v .' +descend \-r \-f 'rmdir RCS' +.XE +.TP +\(bu +Delete any unwanted files that remain in the source hierarchy. Then +make sure all files are under RCS control: +.XS +descend \-f 'ci \-t/dev/null \-m"Placed under CVS control" \-n\fR\fItag\fR\fB *' +.XE +.I tag +is the latest symbolic revision tag that you applied to your package +(if any). Note: This command will probably generate lots of error +messages (for directories and existing RCS files) that you can +ignore. +.SS "Placing a Third-Party Source Distribution Under CVS Control" +The +.B checkin +command checks third-party sources into CVS. The +difference between third-party sources and locally +written sources is that third-party sources must be checked into a +separate branch (called the +.IR "vendor branch" ) +of the RCS tree. This makes it possible to merge local changes to +the sources with later releases from the vendor. +.TP +\(bu +Save the original distribution kit somewhere. For example, if the +master source repository is +.B /src/master +the distribution kit could be saved in +.BR /src/dist . +Organize the distribution directory so that each release +is clearly identifiable. +.TP +\(bu +Unpack the package in a scratch directory, for example +.BR ~/scratch . +.TP +\(bu +Create a repository for the package. +In this example, the package is called `Bugs-R-Us 4.3'. +.XS +mkdir $CVSROOT/bugs +.XE +.TP +\(bu +Check in the unpacked files: +.XS +cd ~/scratch +checkin \-m 'Bugs-R-Us 4.3 distribution' bugs VENDOR V4_3 +.XE +There is nothing magic about the tag `VENDOR', which is applied to +the vendor branch. You can use whatever tag you want. `VENDOR' is a +useful convention. +.TP +\(bu +Never modify vendor files before checking them in. +Check in the files +.I exactly +as you unpacked them. +If you check in locally modified files, future vendor releases may +wipe out your local changes. +.SS "Working With CVS-Controlled Sources" +To use or edit the sources, you must check out a private copy. +For the following examples, the master files are assumed to reside in +.BR "$CVSROOT/behemoth" . +The working directory is +.BR "~/work" . +See +.BR cvs (local) +for more details on the commands mentioned below. +.TP +.I "To Check Out Working Files +Use CVS +.BR checkout : +.XS +cd ~/work +cvs checkout behemoth +.XE +There is nothing magic about the working directory. CVS will check +out sources anywhere you like. Once you have a working copy of the +sources, you can compile or edit them as desired. +.TP +.I "To Display Changes You Have Made" +Use CVS +.BR diff +to display detailed changes, equivalent to +.BR rcsdiff (local). +You can also use +.BR cvscheck (local) +to list files added, changed, and removed in +the directory, but not yet +.BR commit ted. +You must be in a directory containing working files. +.TP +.I "To Display Revision Information" +Use CVS +.BR log , +which is equivalent to +.BR rlog (local). +You must be in a directory containing working files. +.TP +.I "To Update Working Files" +Use CVS +.BR update +in a directory containing working files. +This command brings your working files up +to date with changes checked into the +master repository since you last checked out or updated +your files. +.TP +.I "To Check In Your Changes" +Use CVS +.BR commit +in a directory containing working files. +This command checks your changes into the master repository. +You can specify files by name or use +.XS +cvs commit \-a +.XE +to +.B commit +all the files you have changed. +.TP +.I "To Add a File" +Add the file to the working directory. +Use CVS +.B add +to mark the file as added. +Use CVS +.B commit +to add the file to the master repository. +.TP +.I "To Remove a File" +Remove the file from the working directory. +Use CVS +.B remove +to mark the file as removed. +Use CVS +.B commit +to move the file from its current location in the master repository +to the CVS +.IR Attic +directory. +.TP +.I "To Add a Directory" +Add the directory to the working directory. +Use CVS +.B add +to add the directory to the master repository. +.TP +.I "To Remove a Directory" +.br +You shouldn't remove directories under CVS. You should instead remove +their contents and then prune them (using the +.B \-f +and +.B \-p +options) when you +.B checkout +or +.B update +your working files. +.TP +.I "To Tag a Release" +Use CVS +.B tag +to apply a symbolic tag to the latest revision of each file in the +master repository. For example: +.XS +cvs tag V2_1 behemoth +.XE +.TP +.I "To Retrieve an Exact Copy of a Previous Release" +During a CVS +.B checkout +or +.BR update , +use the +.B \-r +option to retrieve revisions associated with a symbolic tag. +Use the +.B \-f +option to ignore all RCS files that do not contain the +tag. +Use the +.B \-p +option to prune directories that wind up empty because none +of their files matched the tag. Example: +.XS +cd ~/work +cvs checkout \-r V2_1 \-f \-p behemoth +.XE +.SS "Logging Changes" +It is a good idea to keep a change log together with the +sources. As a minimum, the change log should name and describe each +tagged release. The change log should also be under CVS control and +should be tagged along with the sources. +.LP +.BR cvslog (local) +can help. This command logs +changes reported during CVS +.B commit +operations. It automatically +updates a change log file in your working directory. When you are +finished making changes, you (optionally) edit the change log file and +then commit it to the master repository. +.LP +Note: You must edit the change log to describe a new release +and +.B commit +it to the master repository +.I before +.BR tag ging +the release using CVS. Otherwise, the release description will not be +included in the tagged package. +.LP +See +.BR cvslog (local) +for more information. +.SS "Merging a Subsequent Third-Party Distribution" +The initial steps in this process are identical to placing a +third-party distribution under CVS for the first time: save the +distribution kit and unpack the package in a scratch directory. From +that point the steps diverge. +The following example considers release 5.0 of the +Bugs-R-Us package. +.TP +\(bu +Check in the sources after unpacking them: +.XS +cd ~/scratch +checkin \-m 'Bugs-R-Us 5.0 distribution' bugs VENDOR V5_0 \\ + | tee ~/WARNINGS +.XE +It is important to save the output of +.B checkin +in a file +because it lists the sources that have been locally modified. +It is best to save the file in a different directory (for example, +your home directory). Otherwise, +.B checkin +will try to check it into the master repository. +.TP +\(bu +In your usual working directory, check out a fresh copy of the +distribution that you just checked in. +.XS +cd ~/work +cvs checkout \-r VENDOR bugs +.XE +The +.B checkout +command shown above retrieves the latest revision on the vendor branch. +.TP +\(bu +See the `WARNINGS' file for a list of all locally modified +sources. +For each locally modified source, +look at the differences between +the new distribution and the latest local revision: +.XS +cvs diff \-r \fR\fILocalRev file\fR\fB +.XE +In this command, +.I LocalRev +is the latest +numeric or symbolic revision +on the RCS trunk of +.IR file . +You can use CVS +.B log +to get the revision history. +.TP +\(bu +If your local modifications to a file have been incorporated into +the vendor's distribution, then you should reset the default RCS +branch for that file to the vendor branch. CVS doesn't provide a +mechanism to do this. You have to do it by hand in the master +repository: +.XS +rcs \-bVENDOR \fR\fIfile\fR\fB,v +.XE +.TP +\(bu +If your local modifications need to be merged with the +new distribution, use CVS +.B join +to do it: +.XS +cvs join \-r VENDOR \fR\fIfile\fR\fB +.XE +The resulting file will be placed in your working directory. +Edit it to resolve any overlaps. +.TP +\(bu +Test the merged package. +.TP +\(bu +Commit all modified files to the repository: +.XS +cvs commit \-a +.XE +.TP +\(bu +Tag the repository with a new local tag. +.SS "Applying Patches to Third-Party Sources" +Patches are handled in a manner very similar to complete +third-party distributions. This example considers patches applied to +Bugs-R-Us release 5.0. +.TP +\(bu +Save the patch files together with the distribution kit +to which they apply. +The patch file names should clearly indicate the patch +level. +.TP +\(bu +In a scratch directory, check out the last `clean' vendor copy \- the +highest revision on the vendor branch with +.IR "no local changes" : +.XS +cd ~/scratch +cvs checkout \-r VENDOR bugs +.XE +.TP +\(bu +Use +.BR patch (local) +to apply the patches. You should now have an image of the +vendor's software just as though you had received a complete, +new release. +.TP +\(bu +Proceed with the steps described for merging a subsequent third-party +distribution. +.TP +\(bu +Note: When you get to the step that requires you +to check out the new distribution after you have +checked it into the vendor branch, you should move to a different +directory. Do not attempt to +.B checkout +files in the directory in +which you applied the patches. If you do, CVS will try to merge the +changes that you made during patching with the version being checked +out and things will get very confusing. Instead, +go to a different directory (like your working directory) and +check out the files there. +.SS "Advice to Third-Party Source Hackers" +As you can see from the preceding sections, merging local changes +into third-party distributions remains difficult, and probably +always will. This fact suggests some guidelines: +.TP +\(bu +Minimize local changes. +.I Never +make stylistic changes. +Change makefiles only as much as needed for installation. Avoid +overhauling anything. Pray that the vendor does the same. +.TP +\(bu +Avoid renaming files or moving them around. +.TP +\(bu +Put independent, locally written files like help documents, local +tools, or man pages in a sub-directory called `local-additions'. +Locally written files that are linked into an existing executable +should be added right in with the vendor's sources (not in a +`local-additions' directory). +If, in the future, +the vendor distributes something +equivalent to your locally written files +you can CVS +.B remove +the files from the `local-additions' directory at that time. +.SH SEE ALSO +.BR cvs (local), +.BR checkin (local), +.BR cvslog (local), +.BR cvscheck (local) +.SH AUTHOR +Lowell Skoog +.br +Software Technology Group +.br +Technical Computing diff --git a/contrib/cvs/contrib/descend.man b/contrib/cvs/contrib/descend.man new file mode 100644 index 0000000..5ac46f4 --- /dev/null +++ b/contrib/cvs/contrib/descend.man @@ -0,0 +1,115 @@ +.\" $Id: descend.man,v 1.1.1.3 1995/08/28 16:20:31 jimb Exp $ +.TH DESCEND 1 "31 March 1992" +.SH NAME +descend \- walk directory tree and execute a command at each node +.SH SYNOPSIS +.B descend +[ +.B \-afqrv +] +.I command +[ +.I directory +\&.\|.\|. +] +.SH DESCRIPTION +.B descend +walks down a directory tree and executes a command at each node. It +is not as versatile as +.BR find (1), +but it has a simpler syntax. If no +.I directory +is specified, +.B descend +starts at the current one. +.LP +Unlike +.BR find , +.B descend +can be told to skip the special directories associated with RCS, +CVS, and SCCS. This makes +.B descend +especially handy for use with these packages. It can be used with +other commands too, of course. +.LP +.B descend +is a poor man's way to make any command recursive. Note: +.B descend +does not follow symbolic links to directories unless they are +specified on the command line. +.SH OPTIONS +.TP 15 +.B \-a +.I All. +Descend into directories that begin with '.'. +.TP +.B \-f +.I Force. +Ignore errors during descent. Normally, +.B descend +quits when an error occurs. +.TP +.B \-q +.I Quiet. +Suppress the message `In directory +.IR directory ' +that is normally printed during the descent. +.TP +.B \-r +.I Restricted. +Don't descend into the special directories +.SB RCS, +.SB CVS, +.SB CVS.adm, +and +.SB SCCS. +.TP +.B \-v +.I Verbose. +Print +.I command +before executing it. +.SH EXAMPLES +.TP 15 +.B "descend ls" +Cheap substitute for `ls -R'. +.TP 15 +.B "descend -f 'rm *' tree" +Strip `tree' of its leaves. This command descends the `tree' +directory, removing all regular files. Since +.BR rm (1) +does not remove directories, this command leaves the directory +structure of `tree' intact, but denuded. The +.B \-f +option is required to keep +.B descend +from quitting. You could use `rm \-f' instead. +.TP +.B "descend -r 'co RCS/*'" /project/src/ +Check out every RCS file under the directory +.BR "/project/src" . +.TP +.B "descend -r 'cvs diff'" +Perform CVS `diff' operation on every directory below (and including) +the current one. +.SH DIAGNOSTICS +Returns 1 if errors occur (and the +.B \-f +option is not used). Otherwise returns 0. +.SH SEE ALSO +.BR find (1), +.BR rcsintro (1), +.BR cvs (1), +.BR sccs (1) +.SH AUTHOR +Lowell Skoog +.br +Software Technology Group +.br +John Fluke Mfg. Co., Inc. +.SH BUGS +Shell metacharacters in +.I command +may have bizarre effects. In particular, compound commands +(containing ';', '[', and ']' characters) will not work. It is best +to enclose complicated commands in single quotes \(aa\ \(aa. diff --git a/contrib/cvs/contrib/descend.sh b/contrib/cvs/contrib/descend.sh new file mode 100644 index 0000000..e6a7880 --- /dev/null +++ b/contrib/cvs/contrib/descend.sh @@ -0,0 +1,116 @@ +#! /bin/sh +# $Id: descend.sh,v 1.1 1995/07/10 02:26:32 kfogel Exp $ +# +# descend - walk down a directory tree and execute a command at each node + +fullname=$0 +name=descend +usage="Usage: $name [-afqrv] command [directory ...]\n +\040\040-a\040\040All: descend into directories starting with '.'\n +\040\040-f\040\040Force: ignore errors during descent\n +\040\040-q\040\040Quiet: don't print directory names\n +\040\040-r\040\040Restricted: don't descend into RCS, CVS.adm, SCCS directories\n +\040\040-v\040\040Verbose: print command before executing it" + +# Scan for options +while getopts afqrv option; do + case $option in + a) + alldirs=$option + options=$options" "-$option + ;; + f) + force=$option + options=$options" "-$option + ;; + q) + verbose= + quiet=$option + options=$options" "-$option + ;; + r) + restricted=$option + options=$options" "-$option + ;; + v) + verbose=$option + quiet= + options=$options" "-$option + ;; + \?) + /usr/5bin/echo $usage 1>&2 + exit 1 + ;; + esac +done +shift `expr $OPTIND - 1` + +# Get command to execute +if [ $# -lt 1 ] ; then + /usr/5bin/echo $usage 1>&2 + exit 1 +else + command=$1 + shift +fi + +# If no directory specified, use '.' +if [ $# -lt 1 ] ; then + default_dir=. +fi + +# For each directory specified +for dir in $default_dir "$@" ; do + + # Spawn sub-shell so we return to starting directory afterward + (cd $dir + + # Execute specified command + if [ -z "$quiet" ] ; then + echo In directory `hostname`:`pwd` + fi + if [ -n "$verbose" ] ; then + echo $command + fi + eval "$command" || if [ -z "$force" ] ; then exit 1; fi + + # Collect dot file names if necessary + if [ -n "$alldirs" ] ; then + dotfiles=.* + else + dotfiles= + fi + + # For each file in current directory + for file in $dotfiles * ; do + + # Skip '.' and '..' + if [ "$file" = "." -o "$file" = ".." ] ; then + continue + fi + + # If a directory but not a symbolic link + if [ -d "$file" -a ! -h "$file" ] ; then + + # If not skipping this type of directory + if [ \( "$file" != "RCS" -a \ + "$file" != "SCCS" -a \ + "$file" != "CVS" -a \ + "$file" != "CVS.adm" \) \ + -o -z "$restricted" ] ; then + + # Recursively descend into it + $fullname $options "$command" "$file" \ + || if [ -z "$force" ] ; then exit 1; fi + fi + + # Else if a directory AND a symbolic link + elif [ -d "$file" -a -h "$file" ] ; then + + if [ -z "$quiet" ] ; then + echo In directory `hostname`:`pwd`/$file: symbolic link: skipping + fi + fi + done + ) || if [ -z "$force" ] ; then exit 1; fi +done diff --git a/contrib/cvs/contrib/dirfns.shar b/contrib/cvs/contrib/dirfns.shar new file mode 100644 index 0000000..8324c41 --- /dev/null +++ b/contrib/cvs/contrib/dirfns.shar @@ -0,0 +1,481 @@ +echo 'directory.3': +sed 's/^X//' >'directory.3' <<'!' +X.TH DIRECTORY 3 imported +X.DA 9 Oct 1985 +X.SH NAME +Xopendir, readdir, telldir, seekdir, rewinddir, closedir \- high-level directory operations +X.SH SYNOPSIS +X.B #include <sys/types.h> +X.br +X.B #include <ndir.h> +X.PP +X.SM +X.B DIR +X.B *opendir(filename) +X.br +X.B char *filename; +X.PP +X.SM +X.B struct direct +X.B *readdir(dirp) +X.br +X.B DIR *dirp; +X.PP +X.SM +X.B long +X.B telldir(dirp) +X.br +X.B DIR *dirp; +X.PP +X.SM +X.B seekdir(dirp, loc) +X.br +X.B DIR *dirp; +X.br +X.B long loc; +X.PP +X.SM +X.B rewinddir(dirp) +X.br +X.B DIR *dirp; +X.PP +X.SM +X.B closedir(dirp) +X.br +X.B DIR *dirp; +X.SH DESCRIPTION +XThis library provides high-level primitives for directory scanning, +Xsimilar to those available for 4.2BSD's (very different) directory system. +X.\"The purpose of this library is to simulate +X.\"the new flexible length directory names of 4.2bsd UNIX +X.\"on top of the old directory structure of v7. +XIt incidentally provides easy portability to and from 4.2BSD (insofar +Xas such portability is not compromised by other 4.2/VAX dependencies). +X.\"It allows programs to be converted immediately +X.\"to the new directory access interface, +X.\"so that they need only be relinked +X.\"when moved to 4.2bsd. +X.\"It is obtained with the loader option +X.\".BR \-lndir . +X.PP +X.I Opendir +Xopens the directory named by +X.I filename +Xand associates a +X.I directory stream +Xwith it. +X.I Opendir +Xreturns a pointer to be used to identify the +X.I directory stream +Xin subsequent operations. +XThe pointer +X.SM +X.B NULL +Xis returned if +X.I filename +Xcannot be accessed or is not a directory. +X.PP +X.I Readdir +Xreturns a pointer to the next directory entry. +XIt returns +X.B NULL +Xupon reaching the end of the directory or detecting +Xan invalid +X.I seekdir +Xoperation. +X.PP +X.I Telldir +Xreturns the current location associated with the named +X.I directory stream. +X.PP +X.I Seekdir +Xsets the position of the next +X.I readdir +Xoperation on the +X.I directory stream. +XThe new position reverts to the one associated with the +X.I directory stream +Xwhen the +X.I telldir +Xoperation was performed. +XValues returned by +X.I telldir +Xare good only for the lifetime of the DIR pointer from +Xwhich they are derived. +XIf the directory is closed and then reopened, +Xthe +X.I telldir +Xvalue may be invalidated +Xdue to undetected directory compaction in 4.2BSD. +XIt is safe to use a previous +X.I telldir +Xvalue immediately after a call to +X.I opendir +Xand before any calls to +X.I readdir. +X.PP +X.I Rewinddir +Xresets the position of the named +X.I directory stream +Xto the beginning of the directory. +X.PP +X.I Closedir +Xcauses the named +X.I directory stream +Xto be closed, +Xand the structure associated with the DIR pointer to be freed. +X.PP +XA +X.I direct +Xstructure is as follows: +X.PP +X.RS +X.nf +Xstruct direct { +X /* unsigned */ long d_ino; /* inode number of entry */ +X unsigned short d_reclen; /* length of this record */ +X unsigned short d_namlen; /* length of string in d_name */ +X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ +X}; +X.fi +X.RE +X.PP +XThe +X.I d_reclen +Xfield is meaningless in non-4.2BSD systems and should be ignored. +XThe use of a +X.I long +Xfor +X.I d_ino +Xis also a 4.2BSDism; +X.I ino_t +X(see +X.IR types (5)) +Xshould be used elsewhere. +XThe macro +X.I DIRSIZ(dp) +Xgives the minimum memory size needed to hold the +X.I direct +Xvalue pointed to by +X.IR dp , +Xwith the minimum necessary allocation for +X.IR d_name . +X.PP +XThe preferred way to search the current directory for entry ``name'' is: +X.PP +X.RS +X.nf +X len = strlen(name); +X dirp = opendir("."); +X if (dirp == NULL) { +X fprintf(stderr, "%s: can't read directory .\\n", argv[0]); +X return NOT_FOUND; +X } +X while ((dp = readdir(dirp)) != NULL) +X if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) { +X closedir(dirp); +X return FOUND; +X } +X closedir(dirp); +X return NOT_FOUND; +X.RE +X.\".SH LINKING +X.\"This library is accessed by specifying ``-lndir'' as the +X.\"last argument to the compile line, e.g.: +X.\".PP +X.\" cc -I/usr/include/ndir -o prog prog.c -lndir +X.SH "SEE ALSO" +Xopen(2), +Xclose(2), +Xread(2), +Xlseek(2) +X.SH HISTORY +XWritten by +XKirk McKusick at Berkeley (ucbvax!mckusick). +XMiscellaneous bug fixes from elsewhere. +XThe size of the data structure has been decreased to avoid excessive +Xspace waste under V7 (where filenames are 14 characters at most). +XFor obscure historical reasons, the include file is also available +Xas +X.IR <ndir/sys/dir.h> . +XThe Berkeley version lived in a separate library (\fI\-lndir\fR), +Xwhereas ours is +Xpart of the C library, although the separate library is retained to +Xmaximize compatibility. +X.PP +XThis manual page has been substantially rewritten to be informative in +Xthe absence of a 4.2BSD manual. +X.SH BUGS +XThe +X.I DIRSIZ +Xmacro actually wastes a bit of space due to some padding requirements +Xthat are an artifact of 4.2BSD. +X.PP +XThe returned value of +X.I readdir +Xpoints to a static area that will be overwritten by subsequent calls. +X.PP +XThere are some unfortunate name conflicts with the \fIreal\fR V7 +Xdirectory structure definitions. +! +echo 'dir.h': +sed 's/^X//' >'dir.h' <<'!' +X/* dir.h 4.4 82/07/25 */ +X +X/* +X * A directory consists of some number of blocks of DIRBLKSIZ +X * bytes, where DIRBLKSIZ is chosen such that it can be transferred +X * to disk in a single atomic operation (e.g. 512 bytes on most machines). +X * +X * Each DIRBLKSIZ byte block contains some number of directory entry +X * structures, which are of variable length. Each directory entry has +X * a struct direct at the front of it, containing its inode number, +X * the length of the entry, and the length of the name contained in +X * the entry. These are followed by the name padded to a 4 byte boundary +X * with null bytes. All names are guaranteed null terminated. +X * The maximum length of a name in a directory is MAXNAMLEN. +X * +X * The macro DIRSIZ(dp) gives the amount of space required to represent +X * a directory entry. Free space in a directory is represented by +X * entries which have dp->d_reclen >= DIRSIZ(dp). All DIRBLKSIZ bytes +X * in a directory block are claimed by the directory entries. This +X * usually results in the last entry in a directory having a large +X * dp->d_reclen. When entries are deleted from a directory, the +X * space is returned to the previous entry in the same directory +X * block by increasing its dp->d_reclen. If the first entry of +X * a directory block is free, then its dp->d_ino is set to 0. +X * Entries other than the first in a directory do not normally have +X * dp->d_ino set to 0. +X */ +X#define DIRBLKSIZ 512 +X#ifdef VMUNIX +X#define MAXNAMLEN 255 +X#else +X#define MAXNAMLEN 14 +X#endif +X +Xstruct direct { +X /* unsigned */ long d_ino; /* inode number of entry */ +X unsigned short d_reclen; /* length of this record */ +X unsigned short d_namlen; /* length of string in d_name */ +X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ +X}; +X +X/* +X * The DIRSIZ macro gives the minimum record length which will hold +X * the directory entry. This requires the amount of space in struct direct +X * without the d_name field, plus enough space for the name with a terminating +X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. +X */ +X#undef DIRSIZ +X#define DIRSIZ(dp) \ +X ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) +X +X#ifndef KERNEL +X/* +X * Definitions for library routines operating on directories. +X */ +Xtypedef struct _dirdesc { +X int dd_fd; +X long dd_loc; +X long dd_size; +X char dd_buf[DIRBLKSIZ]; +X} DIR; +X#ifndef NULL +X#define NULL 0 +X#endif +Xextern DIR *opendir(); +Xextern struct direct *readdir(); +Xextern long telldir(); +X#ifdef void +Xextern void seekdir(); +Xextern void closedir(); +X#endif +X#define rewinddir(dirp) seekdir((dirp), (long)0) +X#endif KERNEL +! +echo 'makefile': +sed 's/^X//' >'makefile' <<'!' +XDIR = closedir.o opendir.o readdir.o seekdir.o telldir.o +XCFLAGS=-O -I. -Dvoid=int +XDEST=.. +X +Xall: $(DIR) +X +Xmv: $(DIR) +X mv $(DIR) $(DEST) +X +Xcpif: dir.h +X cp dir.h /usr/include/ndir.h +X +Xclean: +X rm -f *.o +! +echo 'closedir.c': +sed 's/^X//' >'closedir.c' <<'!' +Xstatic char sccsid[] = "@(#)closedir.c 4.2 3/10/82"; +X +X#include <sys/types.h> +X#include <dir.h> +X +X/* +X * close a directory. +X */ +Xvoid +Xclosedir(dirp) +X register DIR *dirp; +X{ +X close(dirp->dd_fd); +X dirp->dd_fd = -1; +X dirp->dd_loc = 0; +X free((char *)dirp); +X} +! +echo 'opendir.c': +sed 's/^X//' >'opendir.c' <<'!' +X/* Copyright (c) 1982 Regents of the University of California */ +X +Xstatic char sccsid[] = "@(#)opendir.c 4.4 11/12/82"; +X +X#include <sys/types.h> +X#include <sys/stat.h> +X#include <dir.h> +X +X/* +X * open a directory. +X */ +XDIR * +Xopendir(name) +X char *name; +X{ +X register DIR *dirp; +X register int fd; +X struct stat statbuf; +X char *malloc(); +X +X if ((fd = open(name, 0)) == -1) +X return NULL; +X if (fstat(fd, &statbuf) == -1 || !(statbuf.st_mode & S_IFDIR)) { +X close(fd); +X return NULL; +X } +X if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { +X close (fd); +X return NULL; +X } +X dirp->dd_fd = fd; +X dirp->dd_loc = 0; +X dirp->dd_size = 0; /* so that telldir will work before readdir */ +X return dirp; +X} +! +echo 'readdir.c': +sed 's/^X//' >'readdir.c' <<'!' +X/* Copyright (c) 1982 Regents of the University of California */ +X +Xstatic char sccsid[] = "@(#)readdir.c 4.3 8/8/82"; +X +X#include <sys/types.h> +X#include <dir.h> +X +X/* +X * read an old stlye directory entry and present it as a new one +X */ +X#define ODIRSIZ 14 +X +Xstruct olddirect { +X ino_t od_ino; +X char od_name[ODIRSIZ]; +X}; +X +X/* +X * get next entry in a directory. +X */ +Xstruct direct * +Xreaddir(dirp) +X register DIR *dirp; +X{ +X register struct olddirect *dp; +X static struct direct dir; +X +X for (;;) { +X if (dirp->dd_loc == 0) { +X dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, +X DIRBLKSIZ); +X if (dirp->dd_size <= 0) { +X dirp->dd_size = 0; +X return NULL; +X } +X } +X if (dirp->dd_loc >= dirp->dd_size) { +X dirp->dd_loc = 0; +X continue; +X } +X dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); +X dirp->dd_loc += sizeof(struct olddirect); +X if (dp->od_ino == 0) +X continue; +X dir.d_ino = dp->od_ino; +X strncpy(dir.d_name, dp->od_name, ODIRSIZ); +X dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ +X dir.d_namlen = strlen(dir.d_name); +X dir.d_reclen = DIRBLKSIZ; +X return (&dir); +X } +X} +! +echo 'seekdir.c': +sed 's/^X//' >'seekdir.c' <<'!' +Xstatic char sccsid[] = "@(#)seekdir.c 4.9 3/25/83"; +X +X#include <sys/param.h> +X#include <dir.h> +X +X/* +X * seek to an entry in a directory. +X * Only values returned by "telldir" should be passed to seekdir. +X */ +Xvoid +Xseekdir(dirp, loc) +X register DIR *dirp; +X long loc; +X{ +X long curloc, base, offset; +X struct direct *dp; +X extern long lseek(); +X +X curloc = telldir(dirp); +X if (loc == curloc) +X return; +X base = loc & ~(DIRBLKSIZ - 1); +X offset = loc & (DIRBLKSIZ - 1); +X (void) lseek(dirp->dd_fd, base, 0); +X dirp->dd_size = 0; +X dirp->dd_loc = 0; +X while (dirp->dd_loc < offset) { +X dp = readdir(dirp); +X if (dp == NULL) +X return; +X } +X} +! +echo 'telldir.c': +sed 's/^X//' >'telldir.c' <<'!' +Xstatic char sccsid[] = "@(#)telldir.c 4.1 2/21/82"; +X +X#include <sys/types.h> +X#include <dir.h> +X +X/* +X * return a pointer into a directory +X */ +Xlong +Xtelldir(dirp) +X DIR *dirp; +X{ +X long lseek(); +X +X return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc); +X} +! +echo done diff --git a/contrib/cvs/contrib/intro.doc b/contrib/cvs/contrib/intro.doc new file mode 100644 index 0000000..a6d4ec1 --- /dev/null +++ b/contrib/cvs/contrib/intro.doc @@ -0,0 +1,112 @@ +Date: Tue, 16 Jun 1992 17:05:23 +0200 +From: Steven.Pemberton@cwi.nl +Message-Id: <9206161505.AA06927.steven@sijs.cwi.nl> +To: berliner@Sun.COM +Subject: cvs + +INTRODUCTION TO USING CVS + + CVS is a system that lets groups of people work simultaneously on + groups of files (for instance program sources). + + It works by holding a central 'repository' of the most recent version + of the files. You may at any time create a personal copy of these + files; if at a later date newer versions of the files are put in the + repository, you can 'update' your copy. + + You may edit your copy of the files freely. If new versions of the + files have been put in the repository in the meantime, doing an update + merges the changes in the central copy into your copy. + (It can be that when you do an update, the changes in the + central copy clash with changes you have made in your own + copy. In this case cvs warns you, and you have to resolve the + clash in your copy.) + + When you are satisfied with the changes you have made in your copy of + the files, you can 'commit' them into the central repository. + (When you do a commit, if you haven't updated to the most + recent version of the files, cvs tells you this; then you have + to first update, resolve any possible clashes, and then redo + the commit.) + +USING CVS + + Suppose that a number of repositories have been stored in + /usr/src/cvs. Whenever you use cvs, the environment variable + CVSROOT must be set to this (for some reason): + + CVSROOT=/usr/src/cvs + export CVSROOT + +TO CREATE A PERSONAL COPY OF A REPOSITORY + + Suppose you want a copy of the files in repository 'views' to be + created in your directory src. Go to the place where you want your + copy of the directory, and do a 'checkout' of the directory you + want: + + cd $HOME/src + cvs checkout views + + This creates a directory called (in this case) 'views' in the src + directory, containing a copy of the files, which you may now work + on to your heart's content. + +TO UPDATE YOUR COPY + + Use the command 'cvs update'. + + This will update your copy with any changes from the central + repository, telling you which files have been updated (their names + are displayed with a U before them), and which have been modified + by you and not yet committed (preceded by an M). You will be + warned of any files that contain clashes, the clashes will be + marked in the file surrounded by lines of the form <<<< and >>>>. + +TO COMMIT YOUR CHANGES + + Use the command 'cvs commit'. + + You will be put in an editor to make a message that describes the + changes that you have made (for future reference). Your changes + will then be added to the central copy. + +ADDING AND REMOVING FILES + + It can be that the changes you want to make involve a completely + new file, or removing an existing one. The commands to use here + are: + + cvs add <filename> + cvs remove <filename> + + You still have to do a commit after these commands. You may make + any number of new files in your copy of the repository, but they + will not be committed to the central copy unless you do a 'cvs add'. + +OTHER USEFUL COMMANDS AND HINTS + + To see the commit messages for files, and who made them, use: + + cvs log [filenames] + + To see the differences between your version and the central version: + + cvs diff [filenames] + + To give a file a new name, rename it and do an add and a remove. + + To lose your changes and go back to the version from the + repository, delete the file and do an update. + + After an update where there have been clashes, your original + version of the file is saved as .#file.version. + + All the cvs commands mentioned accept a flag '-n', that doesn't do + the action, but lets you see what would happen. For instance, you + can use 'cvs -n update' to see which files would be updated. + +MORE INFORMATION + + This is necessarily a very brief introduction. See the manual page + (man cvs) for full details. diff --git a/contrib/cvs/contrib/log.pl b/contrib/cvs/contrib/log.pl new file mode 100644 index 0000000..5e3bf48 --- /dev/null +++ b/contrib/cvs/contrib/log.pl @@ -0,0 +1,169 @@ +#! xPERL_PATHx +# -*-Perl-*- +# +#ident "$CVSid$" +# +# XXX: FIXME: handle multiple '-f logfile' arguments +# +# XXX -- I HATE Perl! This *will* be re-written in shell/awk/sed soon! +# + +# Usage: log.pl [[-m user] ...] [-s] -f logfile 'dirname file ...' +# +# -m user - for each user to receive cvs log reports +# (multiple -m's permitted) +# -s - to prevent "cvs status -v" messages +# -f logfile - for the logfile to append to (mandatory, +# but only one logfile can be specified). + +# here is what the output looks like: +# +# From: woods@kuma.domain.top +# Subject: CVS update: testmodule +# +# Date: Wednesday November 23, 1994 @ 14:15 +# Author: woods +# +# Update of /local/src-CVS/testmodule +# In directory kuma:/home/kuma/woods/work.d/testmodule +# +# Modified Files: +# test3 +# Added Files: +# test6 +# Removed Files: +# test4 +# Log Message: +# - wow, what a test +# +# (and for each file the "cvs status -v" output is appended unless -s is used) +# +# ================================================================== +# File: test3 Status: Up-to-date +# +# Working revision: 1.41 Wed Nov 23 14:15:59 1994 +# Repository revision: 1.41 /local/src-CVS/cvs/testmodule/test3,v +# Sticky Options: -ko +# +# Existing Tags: +# local-v2 (revision: 1.7) +# local-v1 (revision: 1.1.1.2) +# CVS-1_4A2 (revision: 1.1.1.2) +# local-v0 (revision: 1.2) +# CVS-1_4A1 (revision: 1.1.1.1) +# CVS (branch: 1.1.1) + +$cvsroot = $ENV{'CVSROOT'}; + +# turn off setgid +# +$) = $(; + +$dostatus = 1; + +# parse command line arguments +# +while (@ARGV) { + $arg = shift @ARGV; + + if ($arg eq '-m') { + $users = "$users " . shift @ARGV; + } elsif ($arg eq '-f') { + ($logfile) && die "Too many '-f' args"; + $logfile = shift @ARGV; + } elsif ($arg eq '-s') { + $dostatus = 0; + } else { + ($donefiles) && die "Too many arguments!\n"; + $donefiles = 1; + @files = split(/ /, $arg); + } +} + +# the first argument is the module location relative to $CVSROOT +# +$modulepath = shift @files; + +$mailcmd = "| Mail -s 'CVS update: $modulepath'"; + +# Initialise some date and time arrays +# +@mos = (January,February,March,April,May,June,July,August,September, + October,November,December); +@days = (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday); + +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; + +# get a login name for the guy doing the commit.... +# +$login = getlogin || (getpwuid($<))[0] || "nobody"; + +# open log file for appending +# +open(OUT, ">>" . $logfile) || die "Could not open(" . $logfile . "): $!\n"; + +# send mail, if there's anyone to send to! +# +if ($users) { + $mailcmd = "$mailcmd $users"; + open(MAIL, $mailcmd) || die "Could not Exec($mailcmd): $!\n"; +} + +# print out the log Header +# +print OUT "\n"; +print OUT "****************************************\n"; +print OUT "Date:\t$days[$wday] $mos[$mon] $mday, 19$year @ $hour:" . sprintf("%02d", $min) . "\n"; +print OUT "Author:\t$login\n\n"; + +if (MAIL) { + print MAIL "\n"; + print MAIL "Date:\t$days[$wday] $mos[$mon] $mday, 19$year @ $hour:" . sprintf("%02d", $min) . "\n"; + print MAIL "Author:\t$login\n\n"; +} + +# print the stuff from logmsg that comes in on stdin to the logfile +# +open(IN, "-"); +while (<IN>) { + print OUT $_; + if (MAIL) { + print MAIL $_; + } +} +close(IN); + +print OUT "\n"; + +# after log information, do an 'cvs -Qq status -v' on each file in the arguments. +# +if ($dostatus != 0) { + while (@files) { + $file = shift @files; + if ($file eq "-") { + print OUT "[input file was '-']\n"; + if (MAIL) { + print MAIL "[input file was '-']\n"; + } + last; + } + open(RCS, "-|") || exec 'cvs', '-nQq', 'status', '-v', $file; + while (<RCS>) { + print OUT; + if (MAIL) { + print MAIL; + } + } + close(RCS); + } +} + +close(OUT); +die "Write to $logfile failed" if $?; + +close(MAIL); +die "Pipe to $mailcmd failed" if $?; + +## must exit cleanly +## +exit 0; diff --git a/contrib/cvs/contrib/log_accum.pl b/contrib/cvs/contrib/log_accum.pl new file mode 100644 index 0000000..d5c6783 --- /dev/null +++ b/contrib/cvs/contrib/log_accum.pl @@ -0,0 +1,560 @@ +#! xPERL_PATHx +# -*-Perl-*- +# +#ident "@(#)ccvs/contrib:$Name: $:$Id: log_accum.pl,v 1.4 1996/03/06 15:27:09 woods Exp $" +# +# Perl filter to handle the log messages from the checkin of files in +# a directory. This script will group the lists of files by log +# message, and mail a single consolidated log message at the end of +# the commit. +# +# This file assumes a pre-commit checking program that leaves the +# names of the first and last commit directories in a temporary file. +# +# Contributed by David Hampton <hampton@cisco.com> +# +# hacked greatly by Greg A. Woods <woods@planix.com> + +# Usage: log_accum.pl [-d] [-s] [-M module] [[-m mailto] ...] [[-R replyto] ...] [-f logfile] +# -d - turn on debugging +# -m mailto - send mail to "mailto" (multiple) +# -R replyto - set the "Reply-To:" to "replyto" (multiple) +# -M modulename - set module name to "modulename" +# -f logfile - write commit messages to logfile too +# -s - *don't* run "cvs status -v" for each file + +# +# Configurable options +# + +# set this to something that takes a whole message on stdin +$MAILER = "/usr/lib/sendmail -t"; + +# +# End user configurable options. +# + +# Constants (don't change these!) +# +$STATE_NONE = 0; +$STATE_CHANGED = 1; +$STATE_ADDED = 2; +$STATE_REMOVED = 3; +$STATE_LOG = 4; + +$LAST_FILE = "/tmp/#cvs.lastdir"; + +$CHANGED_FILE = "/tmp/#cvs.files.changed"; +$ADDED_FILE = "/tmp/#cvs.files.added"; +$REMOVED_FILE = "/tmp/#cvs.files.removed"; +$LOG_FILE = "/tmp/#cvs.files.log"; + +$FILE_PREFIX = "#cvs.files"; + +# +# Subroutines +# + +sub cleanup_tmpfiles { + local($wd, @files); + + $wd = `pwd`; + chdir("/tmp") || die("Can't chdir('/tmp')\n"); + opendir(DIR, "."); + push(@files, grep(/^$FILE_PREFIX\..*\.$id$/, readdir(DIR))); + closedir(DIR); + foreach (@files) { + unlink $_; + } + unlink $LAST_FILE . "." . $id; + + chdir($wd); +} + +sub write_logfile { + local($filename, @lines) = @_; + + open(FILE, ">$filename") || die("Cannot open log file $filename.\n"); + print FILE join("\n", @lines), "\n"; + close(FILE); +} + +sub append_to_logfile { + local($filename, @lines) = @_; + + open(FILE, ">$filename") || die("Cannot open log file $filename.\n"); + print FILE join("\n", @lines), "\n"; + close(FILE); +} + +sub format_names { + local($dir, @files) = @_; + local(@lines); + + $format = "\t%-" . sprintf("%d", length($dir)) . "s%s "; + + $lines[0] = sprintf($format, $dir, ":"); + + if ($debug) { + print STDERR "format_names(): dir = ", $dir, "; files = ", join(":", @files), ".\n"; + } + foreach $file (@files) { + if (length($lines[$#lines]) + length($file) > 65) { + $lines[++$#lines] = sprintf($format, " ", " "); + } + $lines[$#lines] .= $file . " "; + } + + @lines; +} + +sub format_lists { + local(@lines) = @_; + local(@text, @files, $lastdir); + + if ($debug) { + print STDERR "format_lists(): ", join(":", @lines), "\n"; + } + @text = (); + @files = (); + $lastdir = shift @lines; # first thing is always a directory + if ($lastdir !~ /.*\/$/) { + die("Damn, $lastdir doesn't look like a directory!\n"); + } + foreach $line (@lines) { + if ($line =~ /.*\/$/) { + push(@text, &format_names($lastdir, @files)); + $lastdir = $line; + @files = (); + } else { + push(@files, $line); + } + } + push(@text, &format_names($lastdir, @files)); + + @text; +} + +sub append_names_to_file { + local($filename, $dir, @files) = @_; + + if (@files) { + open(FILE, ">>$filename") || die("Cannot open file $filename.\n"); + print FILE $dir, "\n"; + print FILE join("\n", @files), "\n"; + close(FILE); + } +} + +sub read_line { + local($line); + local($filename) = @_; + + open(FILE, "<$filename") || die("Cannot open file $filename.\n"); + $line = <FILE>; + close(FILE); + chop($line); + $line; +} + +sub read_logfile { + local(@text); + local($filename, $leader) = @_; + + open(FILE, "<$filename"); + while (<FILE>) { + chop; + push(@text, $leader.$_); + } + close(FILE); + @text; +} + +sub build_header { + local($header); + local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + $header = sprintf("CVSROOT:\t%s\nModule name:\t%s\nChanges by:\t%s@%s\t%02d/%02d/%02d %02d:%02d:%02d", + $cvsroot, + $modulename, + $login, $hostdomain, + $year%100, $mon+1, $mday, + $hour, $min, $sec); +} + +sub mail_notification { + local(@text) = @_; + + # if only we had strftime()... stuff stolen from perl's ctime.pl: + local($[) = 0; + + @DoW = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); + @MoY = ('Jan','Feb','Mar','Apr','May','Jun', + 'Jul','Aug','Sep','Oct','Nov','Dec'); + + # Determine what time zone is in effect. + # Use GMT if TZ is defined as null, local time if TZ undefined. + # There's no portable way to find the system default timezone. + # + $TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : ''; + + # Hack to deal with 'PST8PDT' format of TZ + # Note that this can't deal with all the esoteric forms, but it + # does recognize the most common: [:]STDoff[DST[off][,rule]] + # + if ($TZ =~ /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/) { + $TZ = $isdst ? $4 : $1; + $tzoff = sprintf("%05d", -($2) * 100); + } + + # perl-4.036 doesn't have the $zone or $gmtoff... + ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst, $zone, $gmtoff) = + ($TZ eq 'GMT') ? gmtime(time) : localtime(time); + + $year += ($year < 70) ? 2000 : 1900; + + if ($gmtoff != 0) { + $tzoff = sprintf("%05d", ($gmtoff / 60) * 100); + } + if ($zone ne '') { + $TZ = $zone; + } + + # ok, let's try.... + $rfc822date = sprintf("%s, %2d %s %4d %2d:%02d:%02d %s (%s)", + $DoW[$wday], $mday, $MoY[$mon], $year, + $hour, $min, $sec, $tzoff, $TZ); + + open(MAIL, "| $MAILER"); + print MAIL "Date: " . $rfc822date . "\n"; + print MAIL "Subject: CVS Update: " . $modulename . "\n"; + print MAIL "To: " . $mailto . "\n"; + print MAIL "From: " . $login . "@" . $hostdomain . "\n"; + print MAIL "Reply-To: " . $replyto . "\n"; + print MAIL "\n"; + print MAIL join("\n", @text), "\n"; + close(MAIL); +} + +sub write_commitlog { + local($logfile, @text) = @_; + + open(FILE, ">>$logfile"); + print FILE join("\n", @text), "\n"; + close(FILE); +} + +# +# Main Body +# + +# Initialize basic variables +# +$debug = 0; +$id = getpgrp(); # note, you *must* use a shell which does setpgrp() +$state = $STATE_NONE; +$login = getlogin || (getpwuid($<))[0] || "nobody"; +chop($hostname = `hostname`); +chop($domainname = `domainname`); +$hostdomain = $hostname . $domainname; +$cvsroot = $ENV{'CVSROOT'}; +$do_status = 1; +$modulename = ""; + +# parse command line arguments (file list is seen as one arg) +# +while (@ARGV) { + $arg = shift @ARGV; + + if ($arg eq '-d') { + $debug = 1; + print STDERR "Debug turned on...\n"; + } elsif ($arg eq '-m') { + if ($mailto eq '') { + $mailto = shift @ARGV; + } else { + $mailto = $mailto . ", " . shift @ARGV; + } + } elsif ($arg eq '-R') { + if ($replyto eq '') { + $replyto = shift @ARGV; + } else { + $replyto = $replyto . ", " . shift @ARGV; + } + } elsif ($arg eq '-M') { + $modulename = shift @ARGV; + } elsif ($arg eq '-s') { + $do_status = 0; + } elsif ($arg eq '-f') { + ($commitlog) && die("Too many '-f' args\n"); + $commitlog = shift @ARGV; + } else { + ($donefiles) && die("Too many arguments! Check usage.\n"); + $donefiles = 1; + @files = split(/ /, $arg); + } +} +($mailto) || die("No mail recipient specified (use -m)\n"); +if ($replyto eq '') { + $replyto = $login; +} + +# for now, the first "file" is the repository directory being committed, +# relative to the $CVSROOT location +# +@path = split('/', $files[0]); + +# XXX there are some ugly assumptions in here about module names and +# XXX directories relative to the $CVSROOT location -- really should +# XXX read $CVSROOT/CVSROOT/modules, but that's not so easy to do, since +# XXX we have to parse it backwards. +# +if ($modulename eq "") { + $modulename = $path[0]; # I.e. the module name == top-level dir +} +if ($#path == 0) { + $dir = "."; +} else { + $dir = join('/', @path); +} +$dir = $dir . "/"; + +if ($debug) { + print STDERR "module - ", $modulename, "\n"; + print STDERR "dir - ", $dir, "\n"; + print STDERR "path - ", join(":", @path), "\n"; + print STDERR "files - ", join(":", @files), "\n"; + print STDERR "id - ", $id, "\n"; +} + +# Check for a new directory first. This appears with files set as follows: +# +# files[0] - "path/name/newdir" +# files[1] - "-" +# files[2] - "New" +# files[3] - "directory" +# +if ($files[2] =~ /New/ && $files[3] =~ /directory/) { + local(@text); + + @text = (); + push(@text, &build_header()); + push(@text, ""); + push(@text, $files[0]); + push(@text, ""); + + while (<STDIN>) { + chop; # Drop the newline + push(@text, $_); + } + + &mail_notification($mailto, @text); + + exit 0; +} + +# Check for an import command. This appears with files set as follows: +# +# files[0] - "path/name" +# files[1] - "-" +# files[2] - "Imported" +# files[3] - "sources" +# +if ($files[2] =~ /Imported/ && $files[3] =~ /sources/) { + local(@text); + + @text = (); + push(@text, &build_header()); + push(@text, ""); + push(@text, $files[0]); + push(@text, ""); + + while (<STDIN>) { + chop; # Drop the newline + push(@text, $_); + } + + &mail_notification(@text); + + exit 0; +} + +# Iterate over the body of the message collecting information. +# +while (<STDIN>) { + chop; # Drop the newline + + if (/^In directory/) { + push(@log_lines, $_); + push(@log_lines, ""); + next; + } + + if (/^Modified Files/) { $state = $STATE_CHANGED; next; } + if (/^Added Files/) { $state = $STATE_ADDED; next; } + if (/^Removed Files/) { $state = $STATE_REMOVED; next; } + if (/^Log Message/) { $state = $STATE_LOG; next; } + + s/^[ \t\n]+//; # delete leading whitespace + s/[ \t\n]+$//; # delete trailing whitespace + + if ($state == $STATE_CHANGED) { push(@changed_files, split); } + if ($state == $STATE_ADDED) { push(@added_files, split); } + if ($state == $STATE_REMOVED) { push(@removed_files, split); } + if ($state == $STATE_LOG) { push(@log_lines, $_); } +} + +# Strip leading and trailing blank lines from the log message. Also +# compress multiple blank lines in the body of the message down to a +# single blank line. +# +while ($#log_lines > -1) { + last if ($log_lines[0] ne ""); + shift(@log_lines); +} +while ($#log_lines > -1) { + last if ($log_lines[$#log_lines] ne ""); + pop(@log_lines); +} +for ($i = $#log_lines; $i > 0; $i--) { + if (($log_lines[$i - 1] eq "") && ($log_lines[$i] eq "")) { + splice(@log_lines, $i, 1); + } +} + +if ($debug) { + print STDERR "Searching for log file index..."; +} +# Find an index to a log file that matches this log message +# +for ($i = 0; ; $i++) { + local(@text); + + last if (! -e "$LOG_FILE.$i.$id"); # the next available one + @text = &read_logfile("$LOG_FILE.$i.$id", ""); + last if ($#text == -1); # nothing in this file, use it + last if (join(" ", @log_lines) eq join(" ", @text)); # it's the same log message as another +} +if ($debug) { + print STDERR " found log file at $i.$id, now writing tmp files.\n"; +} + +# Spit out the information gathered in this pass. +# +&append_names_to_file("$CHANGED_FILE.$i.$id", $dir, @changed_files); +&append_names_to_file("$ADDED_FILE.$i.$id", $dir, @added_files); +&append_names_to_file("$REMOVED_FILE.$i.$id", $dir, @removed_files); +&write_logfile("$LOG_FILE.$i.$id", @log_lines); + +# Check whether this is the last directory. If not, quit. +# +if ($debug) { + print STDERR "Checking current dir against last dir.\n"; +} +$_ = &read_line("$LAST_FILE.$id"); + +if ($_ ne $cvsroot . "/" . $files[0]) { + if ($debug) { + print STDERR sprintf("Current directory %s is not last directory %s.\n", $cvsroot . "/" .$files[0], $_); + } + exit 0; +} +if ($debug) { + print STDERR sprintf("Current directory %s is last directory %s -- all commits done.\n", $files[0], $_); +} + +# +# End Of Commits! +# + +# This is it. The commits are all finished. Lump everything together +# into a single message, fire a copy off to the mailing list, and drop +# it on the end of the Changes file. +# + +# +# Produce the final compilation of the log messages +# +@text = (); +@status_txt = (); +push(@text, &build_header()); +push(@text, ""); + +for ($i = 0; ; $i++) { + last if (! -e "$LOG_FILE.$i.$id"); # we're done them all! + @lines = &read_logfile("$CHANGED_FILE.$i.$id", ""); + if ($#lines >= 0) { + push(@text, "Modified files:"); + push(@text, &format_lists(@lines)); + } + @lines = &read_logfile("$ADDED_FILE.$i.$id", ""); + if ($#lines >= 0) { + push(@text, "Added files:"); + push(@text, &format_lists(@lines)); + } + @lines = &read_logfile("$REMOVED_FILE.$i.$id", ""); + if ($#lines >= 0) { + push(@text, "Removed files:"); + push(@text, &format_lists(@lines)); + } + if ($#text >= 0) { + push(@text, ""); + } + @lines = &read_logfile("$LOG_FILE.$i.$id", "\t"); + if ($#lines >= 0) { + push(@text, "Log message:"); + push(@text, @lines); + push(@text, ""); + } + if ($do_status) { + local(@changed_files); + + @changed_files = (); + push(@changed_files, &read_logfile("$CHANGED_FILE.$i.$id", "")); + push(@changed_files, &read_logfile("$ADDED_FILE.$i.$id", "")); + push(@changed_files, &read_logfile("$REMOVED_FILE.$i.$id", "")); + + if ($debug) { + print STDERR "main: pre-sort changed_files = ", join(":", @changed_files), ".\n"; + } + sort(@changed_files); + if ($debug) { + print STDERR "main: post-sort changed_files = ", join(":", @changed_files), ".\n"; + } + + foreach $dofile (@changed_files) { + if ($dofile =~ /\/$/) { + next; # ignore the silly "dir" entries + } + if ($debug) { + print STDERR "main(): doing 'cvs -nQq status -v $dofile'\n"; + } + open(STATUS, "-|") || exec 'cvs', '-nQq', 'status', '-v', $dofile; + while (<STATUS>) { + chop; + push(@status_txt, $_); + } + } + } +} + +# Write to the commitlog file +# +if ($commitlog) { + &write_commitlog($commitlog, @text); +} + +if ($#status_txt >= 0) { + push(@text, @status_txt); +} + +# Mailout the notification. +# +&mail_notification(@text); + +# cleanup +# +if (! $debug) { + &cleanup_tmpfiles(); +} + +exit 0; diff --git a/contrib/cvs/contrib/mfpipe.pl b/contrib/cvs/contrib/mfpipe.pl new file mode 100644 index 0000000..bae7a72 --- /dev/null +++ b/contrib/cvs/contrib/mfpipe.pl @@ -0,0 +1,88 @@ +#! xPERL_PATHx +# -*-Perl-*- +# +# From: clyne@niwot.scd.ucar.EDU (John Clyne) +# Date: Fri, 28 Feb 92 09:54:21 MST +# +# BTW, i wrote a perl script that is similar to 'nfpipe' except that in +# addition to logging to a file it provides a command line option for mailing +# change notices to a group of users. Obviously you probably wouldn't want +# to mail every change. But there may be certain directories that are commonly +# accessed by a group of users who would benefit from an email notice. +# Especially if they regularly beat on the same directory. Anyway if you +# think anyone would be interested here it is. +# +# $Id: mfpipe.pl,v 1.2 1995/07/10 02:01:57 kfogel Exp $ +# +# +# File: mfpipe +# +# Author: John Clyne +# National Center for Atmospheric Research +# PO 3000, Boulder, Colorado +# +# Date: Wed Feb 26 18:34:53 MST 1992 +# +# Description: Tee standard input to mail a list of users and to +# a file. Used by CVS logging. +# +# Usage: mfpipe [-f file] [user@host...] +# +# Environment: CVSROOT +# Path to CVS root. +# +# Files: +# +# +# Options: -f file +# Capture output to 'file' +# + +$header = "Log Message:\n"; + +$mailcmd = "| mail -s 'CVS update notice'"; +$whoami = `whoami`; +chop $whoami; +$date = `date`; +chop $date; + +$cvsroot = $ENV{'CVSROOT'}; + +while (@ARGV) { + $arg = shift @ARGV; + + if ($arg eq '-f') { + $file = shift @ARGV; + } + else { + $users = "$users $arg"; + } +} + +if ($users) { + $mailcmd = "$mailcmd $users"; + open(MAIL, $mailcmd) || die "Execing $mail: $!\n"; +} + +if ($file) { + $logfile = "$cvsroot/LOG/$file"; + open(FILE, ">> $logfile") || die "Opening $logfile: $!\n"; +} + +print FILE "$whoami $date--------BEGIN LOG ENTRY-------------\n" if ($logfile); + +while (<>) { + print FILE $log if ($log && $logfile); + + print FILE $_ if ($logfile); + print MAIL $_ if ($users); + + $log = "log: " if ($_ eq $header); +} + +close FILE; +die "Write failed" if $?; +close MAIL; +die "Mail failed" if $?; + +exit 0; diff --git a/contrib/cvs/contrib/rcs-to-cvs.sh b/contrib/cvs/contrib/rcs-to-cvs.sh new file mode 100644 index 0000000..3af83d7 --- /dev/null +++ b/contrib/cvs/contrib/rcs-to-cvs.sh @@ -0,0 +1,185 @@ +#! /bin/sh +# +# $Id: rcs-to-cvs.sh,v 1.2 1995/07/15 03:40:34 jimb Exp $ +# Based on the CVS 1.0 checkin csh script. +# Contributed by Per Cederqvist <ceder@signum.se>. +# Rewritten in sh by David MacKenzie <djm@cygnus.com>. +# +# Copyright (c) 1989, Brian Berliner +# +# You may distribute under the terms of the GNU General Public License. +# +############################################################################# +# +# Check in sources that previously were under RCS or no source control system. +# +# The repository is the directory where the sources should be deposited. +# +# Traverses the current directory, ensuring that an +# identical directory structure exists in the repository directory. It +# then checks the files in in the following manner: +# +# 1) If the file doesn't yet exist, check it in as revision 1.1 +# +# The script also is somewhat verbose in letting the user know what is +# going on. It prints a diagnostic when it creates a new file, or updates +# a file that has been modified on the trunk. +# +# Bugs: doesn't put the files in branch 1.1.1 +# doesn't put in release and vendor tags +# +############################################################################# + +usage="Usage: rcs-to-cvs [-v] [-m message] [-f message_file] repository" +vbose=0 +message="" +message_file=/usr/tmp/checkin.$$ +got_one=0 + +if [ $# -lt 1 ]; then + echo "$usage" >&2 + exit 1 +fi + +while [ $# -ne 0 ]; do + case "$1" in + -v) + vbose=1 + ;; + -m) + shift + echo $1 > $message_file + got_one=1 + ;; + -f) + shift + message_file=$1 + got_one=2 + ;; + *) + break + esac + shift +done + +if [ $# -lt 1 ]; then + echo "$usage" >&2 + exit 1 +fi + +repository=$1 +shift + +if [ -z "$CVSROOT" ]; then + echo "Please the environmental variable CVSROOT to the root" >&2 + echo " of the tree you wish to update" >&2 + exit 1 +fi + +if [ $got_one -eq 0 ]; then + echo "Please Edit this file to contain the RCS log information" >$message_file + echo "to be associated with this directory (please remove these lines)">>$message_file + ${EDITOR-/usr/ucb/vi} $message_file + got_one=1 +fi + +# Ya gotta share. +umask 0 + +update_dir=${CVSROOT}/${repository} +[ ! -d ${update_dir} ] && mkdir $update_dir + +if [ -d SCCS ]; then + echo SCCS files detected! >&2 + exit 1 +fi +if [ -d RCS ]; then + co RCS/* +fi + +for name in * .[a-zA-Z0-9]* +do + case "$name" in + RCS | *~ | \* | .\[a-zA-Z0-9\]\* ) continue ;; + esac + echo $name + if [ $vbose -ne 0 ]; then + echo "Updating ${repository}/${name}" + fi + if [ -d "$name" ]; then + if [ ! -d "${update_dir}/${name}" ]; then + echo "WARNING: Creating new directory ${repository}/${name}" + mkdir "${update_dir}/${name}" + if [ $? -ne 0 ]; then + echo "ERROR: mkdir failed - aborting" >&2 + exit 1 + fi + fi + cd "$name" + if [ $? -ne 0 ]; then + echo "ERROR: Couldn\'t cd to $name - aborting" >&2 + exit 1 + fi + if [ $vbose -ne 0 ]; then + $0 -v -f $message_file "${repository}/${name}" + else + $0 -f $message_file "${repository}/${name}" + fi + if [ $? -ne 0 ]; then + exit 1 + fi + cd .. + else # if not directory + if [ ! -f "$name" ]; then + echo "WARNING: $name is neither a regular file" + echo " nor a directory - ignored" + continue + fi + file="${update_dir}/${name},v" + comment="" + if grep -s '\$Log.*\$' "${name}"; then # If $Log keyword + myext=`echo $name | sed 's,.*\.,,'` + [ "$myext" = "$name" ] && myext= + case "$myext" in + c | csh | e | f | h | l | mac | me | mm | ms | p | r | red | s | sh | sl | cl | ml | el | tex | y | ye | yr | "" ) + ;; + + * ) + echo "For file ${file}:" + grep '\$Log.*\$' "${name}" + echo -n "Please insert a comment leader for file ${name} > " + read comment + ;; + esac + fi + if [ ! -f "$file" ]; then # If not exists in repository + if [ ! -f "${update_dir}/Attic/${name},v" ]; then + echo "WARNING: Creating new file ${repository}/${name}" + if [ -f RCS/"${name}",v ]; then + echo "MSG: Copying old rcs file." + cp RCS/"${name}",v "$file" + else + if [ -n "${comment}" ]; then + rcs -q -i -c"${comment}" -t${message_file} -m'.' "$file" + fi + ci -q -u1.1 -t${message_file} -m'.' "$file" + if [ $? -ne 0 ]; then + echo "ERROR: Initial check-in of $file failed - aborting" >&2 + exit 1 + fi + fi + else + file="${update_dir}/Attic/${name},v" + echo "WARNING: IGNORED: ${repository}/Attic/${name}" + continue + fi + else # File existed + echo "ERROR: File exists in repository: Ignored: $file" + continue + fi + fi +done + +[ $got_one -eq 1 ] && rm -f $message_file + +exit 0 diff --git a/contrib/cvs/contrib/rcs2log.sh b/contrib/cvs/contrib/rcs2log.sh new file mode 100644 index 0000000..ccea907 --- /dev/null +++ b/contrib/cvs/contrib/rcs2log.sh @@ -0,0 +1,592 @@ +#! /bin/sh + +# RCS to ChangeLog generator + +# Generate a change log prefix from RCS files and the ChangeLog (if any). +# Output the new prefix to standard output. +# You can edit this prefix by hand, and then prepend it to ChangeLog. + +# Ignore log entries that start with `#'. +# Clump together log entries that start with `{topic} ', +# where `topic' contains neither white space nor `}'. + +# Author: Paul Eggert <eggert@twinsun.com> + +# $Id: rcs2log.sh,v 1.2 1995/07/28 19:48:45 eggert Exp $ + +# Copyright 1992, 1993, 1994, 1995 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; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +tab=' ' +nl=' +' + +# Parse options. + +# defaults +: ${AWK=awk} +: ${TMPDIR=/tmp} +hostname= # name of local host (if empty, will deduce it later) +indent=8 # indent of log line +length=79 # suggested max width of log line +logins= # login names for people we know fullnames and mailaddrs of +loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets +recursive= # t if we want recursive rlog +rlog_options= # options to pass to rlog +tabwidth=8 # width of horizontal tab + +while : +do + case $1 in + -i) indent=${2?}; shift;; + -h) hostname=${2?}; shift;; + -l) length=${2?}; shift;; + -[nu]) # -n is obsolescent; it is replaced by -u. + case $1 in + -n) case ${2?}${3?}${4?} in + *"$tab"* | *"$nl"*) + echo >&2 "$0: -n '$2' '$3' '$4': tabs, newlines not allowed" + exit 1 + esac + loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2$tab$3$tab$4 + shift; shift; shift;; + -u) + # If $2 is not tab-separated, use colon for separator. + case ${2?} in + *"$nl"*) + echo >&2 "$0: -u '$2': newlines not allowed" + exit 1;; + *"$tab"*) + t=$tab;; + *) + t=: + esac + case $2 in + *"$t"*"$t"*"$t"*) + echo >&2 "$0: -u '$2': too many fields" + exit 1;; + *"$t"*"$t"*) + ;; + *) + echo >&2 "$0: -u '$2': not enough fields" + exit 1 + esac + loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2 + shift + esac + logins=$logins$nl$login + ;; + -r) rlog_options=$rlog_options$nl${2?}; shift;; + -R) recursive=t;; + -t) tabwidth=${2?}; shift;; + -*) echo >&2 "$0: usage: $0 [options] [file ...] +Options: + [-h hostname] [-i indent] [-l length] [-R] [-r rlog_option] + [-t tabwidth] [-u 'login<TAB>fullname<TAB>mailaddr']..." + exit 1;; + *) break + esac + shift +done + +month_data=' + m[0]="Jan"; m[1]="Feb"; m[2]="Mar" + m[3]="Apr"; m[4]="May"; m[5]="Jun" + m[6]="Jul"; m[7]="Aug"; m[8]="Sep" + m[9]="Oct"; m[10]="Nov"; m[11]="Dec" + + # days in non-leap year thus far, indexed by month (0-12) + mo[0]=0; mo[1]=31; mo[2]=59; mo[3]=90 + mo[4]=120; mo[5]=151; mo[6]=181; mo[7]=212 + mo[8]=243; mo[9]=273; mo[10]=304; mo[11]=334 + mo[12]=365 +' + + +# Put rlog output into $rlogout. + +# If no rlog options are given, +# log the revisions checked in since the first ChangeLog entry. +case $rlog_options in +'') + date=1970 + if test -s ChangeLog + then + # Add 1 to seconds to avoid duplicating most recent log. + e=' + /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{ + '"$month_data"' + year = $5 + for (i=0; i<=11; i++) if (m[i] == $2) break + dd = $3 + hh = substr($0,12,2) + mm = substr($0,15,2) + ss = substr($0,18,2) + ss++ + if (ss == 60) { + ss = 0 + mm++ + if (mm == 60) { + mm = 0 + hh++ + if (hh == 24) { + hh = 0 + dd++ + monthdays = mo[i+1] - mo[i] + if (i == 1 && year%4 == 0 && (year%100 != 0 || year%400 == 0)) monthdays++ + if (dd == monthdays + 1) { + dd = 1 + i++ + if (i == 12) { + i = 0 + year++ + } + } + } + } + } + # Output comma instead of space to avoid CVS 1.5 bug. + printf "%d/%02d/%02d,%02d:%02d:%02d\n", year,i+1,dd,hh,mm,ss + exit + } + ' + d=`$AWK "$e" <ChangeLog` || exit + case $d in + ?*) date=$d + esac + fi + datearg="-d>$date" +esac + +# If CVS is in use, examine its repository, not the normal RCS files. +if test ! -f CVS/Repository +then + rlog=rlog + repository= +else + rlog='cvs log' + repository=`sed 1q <CVS/Repository` || exit + test ! -f CVS/Root || CVSROOT=`cat <CVS/Root` || exit + case $CVSROOT in + *:/*) + # remote repository + ;; + *) + # local repository + case $repository in + /*) ;; + *) repository=${CVSROOT?}/$repository + esac + if test ! -d "$repository" + then + echo >&2 "$0: $repository: bad repository (see CVS/Repository)" + exit 1 + fi + esac +fi + +# With no arguments, examine all files under the RCS directory. +case $# in +0) + case $repository in + '') + oldIFS=$IFS + IFS=$nl + case $recursive in + t) + RCSdirs=`find . -name RCS -type d -print` + filesFromRCSfiles='s|,v$||; s|/RCS/|/|; s|^\./||' + files=` + { + case $RCSdirs in + ?*) find $RCSdirs -type f -print + esac + find . -name '*,v' -print + } | + sort -u | + sed "$filesFromRCSfiles" + `;; + *) + files= + for file in RCS/.* RCS/* .*,v *,v + do + case $file in + RCS/. | RCS/..) continue;; + RCS/.\* | RCS/\* | .\*,v | \*,v) test -f "$file" || continue + esac + files=$files$nl$file + done + case $files in + '') exit 0 + esac + esac + set x $files + shift + IFS=$oldIFS + esac +esac + +llogout=$TMPDIR/rcs2log$$l +rlogout=$TMPDIR/rcs2log$$r +trap exit 1 2 13 15 +trap "rm -f $llogout $rlogout; exit 1" 0 + +case $rlog_options in +?*) $rlog $rlog_options ${1+"$@"} >$rlogout;; +'') $rlog "$datearg" ${1+"$@"} >$rlogout +esac || exit + + +# Get the full name of each author the logs mention, and set initialize_fullname +# to awk code that initializes the `fullname' awk associative array. +# Warning: foreign authors (i.e. not known in the passwd file) are mishandled; +# you have to fix the resulting output by hand. + +initialize_fullname= +initialize_mailaddr= + +case $loginFullnameMailaddrs in +?*) + case $loginFullnameMailaddrs in + *\"* | *\\*) + sed 's/["\\]/\\&/g' >$llogout <<EOF || exit +$loginFullnameMailaddrs +EOF + loginFullnameMailaddrs=`cat $llogout` + esac + + oldIFS=$IFS + IFS=$nl + for loginFullnameMailaddr in $loginFullnameMailaddrs + do + case $loginFullnameMailaddr in + *"$tab"*) IFS=$tab;; + *) IFS=: + esac + set x $loginFullnameMailaddr + login=$2 + fullname=$3 + mailaddr=$4 + initialize_fullname="$initialize_fullname + fullname[\"$login\"] = \"$fullname\"" + initialize_mailaddr="$initialize_mailaddr + mailaddr[\"$login\"] = \"$mailaddr\"" + done + IFS=$oldIFS +esac + +case $llogout in +?*) sort -u -o $llogout <<EOF || exit +$logins +EOF +esac +output_authors='/^date: / { + if ($2 ~ /^[0-9]*[-\/][0-9][0-9][-\/][0-9][0-9]$/ && $3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][-+0-9:]*;$/ && $4 == "author:" && $5 ~ /^[^;]*;$/) { + print substr($5, 1, length($5)-1) + } +}' +authors=` + $AWK "$output_authors" <$rlogout | + case $llogout in + '') sort -u;; + ?*) sort -u | comm -23 - $llogout + esac +` +case $authors in +?*) + cat >$llogout <<EOF || exit +$authors +EOF + initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/' + initialize_author=`sed -e "$initialize_author_script" <$llogout` + awkscript=' + BEGIN { + alphabet = "abcdefghijklmnopqrstuvwxyz" + ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + '"$initialize_author"' + } + { + if (author[$1]) { + fullname = $5 + if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) { + # Remove the junk from fullnames like "0000-Admin(0000)". + fullname = substr(fullname, index(fullname, "-") + 1) + fullname = substr(fullname, 1, index(fullname, "(") - 1) + } + if (fullname ~ /,[^ ]/) { + # Some sites put comma-separated junk after the fullname. + # Remove it, but leave "Bill Gates, Jr" alone. + fullname = substr(fullname, 1, index(fullname, ",") - 1) + } + abbr = index(fullname, "&") + if (abbr) { + a = substr($1, 1, 1) + A = a + i = index(alphabet, a) + if (i) A = substr(ALPHABET, i, 1) + fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1) + } + + # Quote quotes and backslashes properly in full names. + # Do not use gsub; traditional awk lacks it. + quoted = "" + rest = fullname + for (;;) { + p = index(rest, "\\") + q = index(rest, "\"") + if (p) { + if (q && q<p) p = q + } else { + if (!q) break + p = q + } + quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1) + rest = substr(rest, p+1) + } + + printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest + author[$1] = 0 + } + } + ' + + initialize_fullname=` + (cat /etc/passwd; ypmatch $authors passwd) 2>/dev/null | + $AWK -F: "$awkscript" + `$initialize_fullname +esac + + +# Function to print a single log line. +# We don't use awk functions, to stay compatible with old awk versions. +# `Log' is the log message (with \n replaced by \r). +# `files' contains the affected files. +printlogline='{ + + # Following the GNU coding standards, rewrite + # * file: (function): comment + # to + # * file (function): comment + if (Log ~ /^\([^)]*\): /) { + i = index(Log, ")") + files = files " " substr(Log, 1, i) + Log = substr(Log, i+3) + } + + # If "label: comment" is too long, break the line after the ":". + sep = " " + if ('"$length"' <= '"$indent"' + 1 + length(files) + index(Log, CR)) sep = "\n" indent_string + + # Print the label. + printf "%s*%s:", indent_string, files + + # Print each line of the log, transliterating \r to \n. + while ((i = index(Log, CR)) != 0) { + logline = substr(Log, 1, i-1) + if (logline ~ /[^'"$tab"' ]/) { + printf "%s%s\n", sep, logline + } else { + print "" + } + sep = indent_string + Log = substr(Log, i+1) + } +}' + +case $hostname in +'') + hostname=`( + hostname || uname -n || uuname -l || cat /etc/whoami + ) 2>/dev/null` || { + echo >&2 "$0: cannot deduce hostname" + exit 1 + } +esac + + +# Process the rlog output, generating ChangeLog style entries. + +# First, reformat the rlog output so that each line contains one log entry. +# Transliterate \n to \r so that multiline entries fit on a single line. +# Discard irrelevant rlog output. +$AWK <$rlogout ' + BEGIN { repository = "'"$repository"'" } + /^RCS file:/ { + if (repository != "") { + filename = $3 + if (substr(filename, 1, length(repository) + 1) == repository "/") { + filename = substr(filename, length(repository) + 2) + } + if (filename ~ /,v$/) { + filename = substr(filename, 1, length(filename) - 2) + } + } + } + /^Working file:/ { if (repository == "") filename = $3 } + /^date: /, /^(-----------*|===========*)$/ { + if ($0 ~ /^branches: /) { next } + if ($0 ~ /^date: [0-9][- +\/0-9:]*;/) { + date = $2 + if (date ~ /-/) { + # An ISO format date. Replace all "-"s with "/"s. + newdate = "" + while ((i = index(date, "-")) != 0) { + newdate = newdate substr(date, 1, i-1) "/" + date = substr(date, i+1) + } + date = newdate date + } + # Ignore any time zone; ChangeLog has no room for it. + time = substr($3, 1, 8) + author = substr($5, 1, length($5)-1) + printf "%s %s %s %s %c", filename, date, time, author, 13 + next + } + if ($0 ~ /^(-----------*|===========*)$/) { print ""; next } + printf "%s%c", $0, 13 + } +' | + +# Now each line is of the form +# FILENAME YYYY/MM/DD HH:MM:SS AUTHOR \rLOG +# where \r stands for a carriage return, +# and each line of the log is terminated by \r instead of \n. +# Sort the log entries, first by date+time (in reverse order), +# then by author, then by log entry, and finally by file name (just in case). +sort +1 -3r +3 +0 | + +# Finally, reformat the sorted log entries. +$AWK ' + BEGIN { + # Some awk variants do not understand "\r" or "\013", so we have to + # put a carriage return directly in the file. + CR="
" # <-- There is a single CR between the " chars here. + + # Initialize the fullname and mailaddr associative arrays. + '"$initialize_fullname"' + '"$initialize_mailaddr"' + + # Initialize indent string. + indent_string = "" + i = '"$indent"' + if (0 < '"$tabwidth"') + for (; '"$tabwidth"' <= i; i -= '"$tabwidth"') + indent_string = indent_string "\t" + while (1 <= i--) + indent_string = indent_string " " + + # Set up date conversion tables. + # RCS uses a nice, clean, sortable format, + # but ChangeLog wants the traditional, ugly ctime format. + + # January 1, 0 AD (Gregorian) was Saturday = 6 + EPOCH_WEEKDAY = 6 + # Of course, there was no 0 AD, but the algorithm works anyway. + + w[0]="Sun"; w[1]="Mon"; w[2]="Tue"; w[3]="Wed" + w[4]="Thu"; w[5]="Fri"; w[6]="Sat" + + '"$month_data"' + } + + { + newlog = substr($0, 1 + index($0, CR)) + + # Ignore log entries prefixed by "#". + if (newlog ~ /^#/) { next } + + if (Log != newlog || date != $2 || author != $4) { + + # The previous log and this log differ. + + # Print the old log. + if (date != "") '"$printlogline"' + + # Logs that begin with "{clumpname} " should be grouped together, + # and the clumpname should be removed. + # Extract the new clumpname from the log header, + # and use it to decide whether to output a blank line. + newclumpname = "" + sep = "\n" + if (date == "") sep = "" + if (newlog ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) { + i = index(newlog, "}") + newclumpname = substr(newlog, 1, i) + while (substr(newlog, i+1) ~ /^['"$tab"' ]/) i++ + newlog = substr(newlog, i+1) + if (clumpname == newclumpname) sep = "" + } + printf sep + clumpname = newclumpname + + # Get ready for the next log. + Log = newlog + if (files != "") + for (i in filesknown) + filesknown[i] = 0 + files = "" + } + if (date != $2 || author != $4) { + # The previous date+author and this date+author differ. + # Print the new one. + date = $2 + author = $4 + + # Convert nice RCS date like "1992/01/03 00:03:44" + # into ugly ctime date like "Fri Jan 3 00:03:44 1992". + # Calculate day of week from Gregorian calendar. + i = index($2, "/") + year = substr($2, 1, i-1) + 0 + monthday = substr($2, i+1) + i = index(monthday, "/") + month = substr(monthday, 1, i-1) + 0 + day = substr(monthday, i+1) + 0 + leap = 0 + if (2 < month && year%4 == 0 && (year%100 != 0 || year%400 == 0)) leap = 1 + days_since_Sunday_before_epoch = EPOCH_WEEKDAY + year * 365 + int((year + 3) / 4) - int((year + 99) / 100) + int((year + 399) / 400) + mo[month-1] + leap + day - 1 + + # Print "date fullname (email address)". + # Get fullname and email address from associative arrays; + # default to author and author@hostname if not in arrays. + if (fullname[author]) + auth = fullname[author] + else + auth = author + printf "%s %s %2d %s %d %s ", w[days_since_Sunday_before_epoch%7], m[month-1], day, $3, year, auth + if (mailaddr[author]) + printf "<%s>\n\n", mailaddr[author] + else + printf "<%s@%s>\n\n", author, "'"$hostname"'" + } + if (! filesknown[$1]) { + filesknown[$1] = 1 + if (files == "") files = " " $1 + else files = files ", " $1 + } + } + END { + # Print the last log. + if (date != "") { + '"$printlogline"' + printf "\n" + } + } +' && + + +# Exit successfully. + +exec rm -f $llogout $rlogout diff --git a/contrib/cvs/contrib/rcs2sccs.sh b/contrib/cvs/contrib/rcs2sccs.sh new file mode 100644 index 0000000..af70138 --- /dev/null +++ b/contrib/cvs/contrib/rcs2sccs.sh @@ -0,0 +1,143 @@ +#! /bin/sh +# +# +# OrigId: rcs2sccs,v 1.12 90/10/04 20:52:23 kenc Exp Locker: kenc +# $Id: rcs2sccs.sh,v 1.1 1995/07/10 02:26:45 kfogel Exp $ + +############################################################ +# Error checking +# +if [ ! -d SCCS ] ; then + mkdir SCCS +fi + +logfile=/tmp/rcs2sccs_$$_log +rm -f $logfile +tmpfile=/tmp/rcs2sccs_$$_tmp +rm -f $tmpfile +emptyfile=/tmp/rcs2sccs_$$_empty +echo -n "" > $emptyfile +initialfile=/tmp/rcs2sccs_$$_init +echo "Initial revision" > $initialfile +sedfile=/tmp/rcs2sccs_$$_sed +rm -f $sedfile +revfile=/tmp/rcs2sccs_$$_rev +rm -f $revfile +commentfile=/tmp/rcs2sccs_$$_comment +rm -f $commentfile + +# create the sed script +cat > $sedfile << EOF +s,;Id;,%Z%%M% %I% %E%,g +s,;SunId;,%Z%%M% %I% %E%,g +s,;RCSfile;,%M%,g +s,;Revision;,%I%,g +s,;Date;,%E%,g +s,;Id:.*;,%Z%%M% %I% %E%,g +s,;SunId:.*;,%Z%%M% %I% %E%,g +s,;RCSfile:.*;,%M%,g +s,;Revision:.*;,%I%,g +s,;Date:.*;,%E%,g +EOF +sed -e 's/;/\\$/g' $sedfile > $tmpfile +cp $tmpfile $sedfile +############################################################ +# Loop over every RCS file in RCS dir +# +for vfile in *,v; do + # get rid of the ",v" at the end of the name + file=`echo $vfile | sed -e 's/,v$//'` + + # work on each rev of that file in ascending order + firsttime=1 + rlog $file | grep "^revision [0-9][0-9]*\." | awk '{print $2}' | sed -e 's/\./ /g' | sort -n -u +0 +1 +2 +3 +4 +5 +6 +7 +8 | sed -e 's/ /./g' > $revfile + for rev in `cat $revfile`; do + if [ $? != 0 ]; then + echo ERROR - revision + exit + fi + # get file into current dir and get stats + date=`rlog -r$rev $file | grep "^date: " | awk '{print $2; exit}' | sed -e 's/^19//'` + time=`rlog -r$rev $file | grep "^date: " | awk '{print $3; exit}' | sed -e 's/;//'` + author=`rlog -r$rev $file | grep "^date: " | awk '{print $5; exit}' | sed -e 's/;//'` + date="$date $time" + echo "" + rlog -r$rev $file | sed -e '/^branches: /d' -e '1,/^date: /d' -e '/^===========/d' -e 's/$/\\/' | awk '{if ((total += length($0) + 1) < 510) print $0}' > $commentfile + echo "==> file $file, rev=$rev, date=$date, author=$author" + rm -f $file + co -r$rev $file >> $logfile 2>&1 + if [ $? != 0 ]; then + echo ERROR - co + exit + fi + echo checked out of RCS + + # add SCCS keywords in place of RCS keywords + sed -f $sedfile $file > $tmpfile + if [ $? != 0 ]; then + echo ERROR - sed + exit + fi + echo performed keyword substitutions + rm -f $file + cp $tmpfile $file + + # check file into SCCS + if [ "$firsttime" = "1" ]; then + firsttime=0 + echo about to do sccs admin + echo sccs admin -n -i$file $file < $commentfile + sccs admin -n -i$file $file < $commentfile >> $logfile 2>&1 + if [ $? != 0 ]; then + echo ERROR - sccs admin + exit + fi + echo initial rev checked into SCCS + else + case $rev in + *.*.*.*) + brev=`echo $rev | sed -e 's/\.[0-9]*$//'` + sccs admin -fb $file 2>>$logfile + echo sccs get -e -p -r$brev $file + sccs get -e -p -r$brev $file >/dev/null 2>>$logfile + ;; + *) + echo sccs get -e -p $file + sccs get -e -p $file >/dev/null 2>> $logfile + ;; + esac + if [ $? != 0 ]; then + echo ERROR - sccs get + exit + fi + sccs delta $file < $commentfile >> $logfile 2>&1 + if [ $? != 0 ]; then + echo ERROR - sccs delta -r$rev $file + exit + fi + echo checked into SCCS + fi + sed -e "s;^d D $rev ../../.. ..:..:.. [^ ][^ ]*;d D $rev $date $author;" SCCS/s.$file > $tmpfile + rm -f SCCS/s.$file + cp $tmpfile SCCS/s.$file + chmod 444 SCCS/s.$file + sccs admin -z $file + if [ $? != 0 ]; then + echo ERROR - sccs admin -z + exit + fi + done + rm -f $file +done + + +############################################################ +# Clean up +# +echo cleaning up... +rm -f $tmpfile $emptyfile $initialfile $sedfile $commentfile +echo =================================================== +echo " Conversion Completed Successfully" +echo =================================================== + +rm -f *,v diff --git a/contrib/cvs/contrib/rcslock.pl b/contrib/cvs/contrib/rcslock.pl new file mode 100644 index 0000000..01e349f --- /dev/null +++ b/contrib/cvs/contrib/rcslock.pl @@ -0,0 +1,235 @@ +#! xPERL_PATHx +# -*-Perl-*- + +# Author: John Rouillard (rouilj@cs.umb.edu) +# Supported: Yeah right. (Well what do you expect for 2 hours work?) +# Blame-to: rouilj@cs.umb.edu +# Complaints to: Anybody except Brian Berliner, he's blameless for +# this script. +# Acknowlegements: The base code for this script has been acquired +# from the log.pl script. + +# rcslock.pl - A program to prevent commits when a file to be ckecked +# in is locked in the repository. + +# There are times when you need exclusive access to a file. This +# often occurs when binaries are checked into the repository, since +# cvs's (actually rcs's) text based merging mechanism won't work. This +# script allows you to use the rcs lock mechanism (rcs -l) to make +# sure that no changes to a repository are able to be committed if +# those changes would result in a locked file being changed. + +# WARNING: +# This script will work only if locking is set to strict. +# + +# Setup: +# Add the following line to the commitinfo file: + +# ALL /local/location/for/script/lockcheck [options] + +# Where ALL is replaced by any suitable regular expression. +# Options are -v for verbose info, or -d for debugging info. +# The %s will provide the repository directory name and the names of +# all changed files. + +# Use: +# When a developer needs exclusive access to a version of a file, s/he +# should use "rcs -l" in the repository tree to lock the version they +# are working on. CVS will automagically release the lock when the +# commit is performed. + +# Method: +# An "rlog -h" is exec'ed to give info on all about to be +# committed files. This (header) information is parsed to determine +# if any locks are outstanding and what versions of the file are +# locked. This filename, version number info is used to index an +# associative array. All of the files to be committed are checked to +# see if any locks are outstanding. If locks are outstanding, the +# version number of the current file (taken from the CVS/Entries +# subdirectory) is used in the key to determine if that version is +# locked. If the file being checked in is locked by the person doing +# the checkin, the commit is allowed, but if the lock is held on that +# version of a file by another person, the commit is not allowed. + +$ext = ",v"; # The extension on your rcs files. + +$\="\n"; # I hate having to put \n's at the end of my print statements +$,=' '; # Spaces should occur between arguments to print when printed + +# turn off setgid +# +$) = $(; + +# +# parse command line arguments +# +require 'getopts.pl'; + +&Getopts("vd"); # verbose or debugging + +# Verbose is useful when debugging +$opt_v = $opt_d if defined $opt_d; + +# $files[0] is really the name of the subdirectory. +# @files = split(/ /,$ARGV[0]); +@files = @ARGV[0..$#ARGV]; +$cvsroot = $ENV{'CVSROOT'}; + +# +# get login name +# +$login = getlogin || (getpwuid($<))[0] || "nobody"; + +# +# save the current directory since we have to return here to parse the +# CVS/Entries file if a lock is found. +# +$pwd = `/bin/pwd`; +chop $pwd; + +print "Starting directory is $pwd" if defined $opt_d ; + +# +# cd to the repository directory and check on the files. +# +print "Checking directory ", $files[0] if defined $opt_v ; + +if ( $files[0] =~ /^\// ) +{ + print "Directory path is $files[0]" if defined $opt_d ; + chdir $files[0] || die "Can't change to repository directory $files[0]" ; +} +else +{ + print "Directory path is $cvsroot/$files[0]" if defined $opt_d ; + chdir ($cvsroot . "/" . $files[0]) || + die "Can't change to repository directory $files[0] in $cvsroot" ; +} + + +# Open the rlog process and apss all of the file names to that one +# process to cut down on exec overhead. This may backfire if there +# are too many files for the system buffer to handle, but if there are +# that many files, chances are that the cvs repository is not set up +# cleanly. + +print "opening rlog -h @files[1..$#files] |" if defined $opt_d; + +open( RLOG, "rlog -h @files[1..$#files] |") || die "Can't run rlog command" ; + +# Create the locks associative array. The elements in the array are +# of two types: +# +# The name of the RCS file with a value of the total number of locks found +# for that file, +# or +# +# The name of the rcs file concatenated with the version number of the lock. +# The value of this element is the name of the locker. + +# The regular expressions used to split the rcs info may have to be changed. +# The current ones work for rcs 5.6. + +$lock = 0; + +while (<RLOG>) +{ + chop; + next if /^$/; # ditch blank lines + + if ( $_ =~ /^RCS file: (.*)$/ ) + { + $curfile = $1; + next; + } + + if ( $_ =~ /^locks: strict$/ ) + { + $lock = 1 ; + next; + } + + if ( $lock ) + { + # access list: is the line immediately following the list of locks. + if ( /^access list:/ ) + { # we are done getting lock info for this file. + $lock = 0; + } + else + { # We are accumulating lock info. + + # increment the lock count + $locks{$curfile}++; + # save the info on the version that is locked. $2 is the + # version number $1 is the name of the locker. + $locks{"$curfile" . "$2"} = $1 + if /[ ]*([a-zA-Z._]*): ([0-9.]*)$/; + + print "lock by $1 found on $curfile version $2" if defined $opt_d; + + } + } +} + +# Lets go back to the starting directory and see if any locked files +# are ones we are interested in. + +chdir $pwd; + +# fo all of the file names (remember $files[0] is the directory name +foreach $i (@files[1..$#files]) +{ + if ( defined $locks{$i . $ext} ) + { # well the file has at least one lock outstanding + + # find the base version number of our file + &parse_cvs_entry($i,*entry); + + # is our version of this file locked? + if ( defined $locks{$i . $ext . $entry{"version"}} ) + { # if so, it is by us? + if ( $login ne ($by = $locks{$i . $ext . $entry{"version"}}) ) + {# crud somebody else has it locked. + $outstanding_lock++ ; + print "$by has file $i locked for version " , $entry{"version"}; + } + else + { # yeah I have it locked. + print "You have a lock on file $i for version " , $entry{"version"} + if defined $opt_v; + } + } + } +} + +exit $outstanding_lock; + + +### End of main program + +sub parse_cvs_entry +{ # a very simple minded hack at parsing an entries file. +local ( $file, *entry ) = @_; +local ( @pp ); + + +open(ENTRIES, "< CVS/Entries") || die "Can't open entries file"; + +while (<ENTRIES>) + { + if ( $_ =~ /^\/$file\// ) + { + @pp = split('/'); + + $entry{"name"} = $pp[1]; + $entry{"version"} = $pp[2]; + $entry{"dates"} = $pp[3]; + $entry{"name"} = $pp[4]; + $entry{"name"} = $pp[5]; + $entry{"sticky"} = $pp[6]; + return; + } + } +} diff --git a/contrib/cvs/contrib/sccs2rcs.csh b/contrib/cvs/contrib/sccs2rcs.csh new file mode 100644 index 0000000..0f31893 --- /dev/null +++ b/contrib/cvs/contrib/sccs2rcs.csh @@ -0,0 +1,277 @@ +#! xCSH_PATHx -f +# +# Sccs2rcs is a script to convert an existing SCCS +# history into an RCS history without losing any of +# the information contained therein. +# It has been tested under the following OS's: +# SunOS 3.5, 4.0.3, 4.1 +# Ultrix-32 2.0, 3.1 +# +# Things to note: +# + It will NOT delete or alter your ./SCCS history under any circumstances. +# +# + Run in a directory where ./SCCS exists and where you can +# create ./RCS +# +# + /usr/local/bin is put in front of the default path. +# (SCCS under Ultrix is set-uid sccs, bad bad bad, so +# /usr/local/bin/sccs here fixes that) +# +# + Date, time, author, comments, branches, are all preserved. +# +# + If a command fails somewhere in the middle, it bombs with +# a message -- remove what it's done so far and try again. +# "rm -rf RCS; sccs unedit `sccs tell`; sccs clean" +# There is no recovery and exit is far from graceful. +# If a particular module is hanging you up, consider +# doing it separately; move it from the current area so that +# the next run will have a better chance or working. +# Also (for the brave only) you might consider hacking +# the s-file for simpler problems: I've successfully changed +# the date of a delta to be in sync, then run "sccs admin -z" +# on the thing. +# +# + After everything finishes, ./SCCS will be moved to ./old-SCCS. +# +# This file may be copied, processed, hacked, mutilated, and +# even destroyed as long as you don't tell anyone you wrote it. +# +# Ken Cox +# Viewlogic Systems, Inc. +# kenstir@viewlogic.com +# ...!harvard!cg-atla!viewlog!kenstir +# +# Various hacks made by Brian Berliner before inclusion in CVS contrib area. +# +# $Id: sccs2rcs.csh,v 1.1 1995/07/10 02:26:48 kfogel Exp $ + + +#we'll assume the user set up the path correctly +# for the Pmax, /usr/ucb/sccs is suid sccs, what a pain +# /usr/local/bin/sccs should override /usr/ucb/sccs there +set path = (/usr/local/bin $path) + + +############################################################ +# Error checking +# +if (! -w .) then + echo "Error: ./ not writeable by you." + exit 1 +endif +if (! -d SCCS) then + echo "Error: ./SCCS directory not found." + exit 1 +endif +set edits = (`sccs tell`) +if ($#edits) then + echo "Error: $#edits file(s) out for edit...clean up before converting." + exit 1 +endif +if (-d RCS) then + echo "Warning: RCS directory exists" + if (`ls -a RCS | wc -l` > 2) then + echo "Error: RCS directory not empty + exit 1 + endif +else + mkdir RCS +endif + +sccs clean + +set logfile = /tmp/sccs2rcs_$$_log +rm -f $logfile +set tmpfile = /tmp/sccs2rcs_$$_tmp +rm -f $tmpfile +set emptyfile = /tmp/sccs2rcs_$$_empty +echo -n "" > $emptyfile +set initialfile = /tmp/sccs2rcs_$$_init +echo "Initial revision" > $initialfile +set sedfile = /tmp/sccs2rcs_$$_sed +rm -f $sedfile +set revfile = /tmp/sccs2rcs_$$_rev +rm -f $revfile + +# the quotes surround the dollar signs to fool RCS when I check in this script +set sccs_keywords = (\ + '%W%[ ]*%G%'\ + '%W%[ ]*%E%'\ + '%W%'\ + '%Z%%M%[ ]*%I%[ ]*%G%'\ + '%Z%%M%[ ]*%I%[ ]*%E%'\ + '%M%[ ]*%I%[ ]*%G%'\ + '%M%[ ]*%I%[ ]*%E%'\ + '%M%'\ + '%I%'\ + '%G%'\ + '%E%'\ + '%U%') +set rcs_keywords = (\ + '$'Id'$'\ + '$'Id'$'\ + '$'Id'$'\ + '$'SunId'$'\ + '$'SunId'$'\ + '$'Id'$'\ + '$'Id'$'\ + '$'RCSfile'$'\ + '$'Revision'$'\ + '$'Date'$'\ + '$'Date'$'\ + '') + + +############################################################ +# Get some answers from user +# +echo "" +echo "Do you want to be prompted for a description of each" +echo "file as it is checked in to RCS initially?" +echo -n "(y=prompt for description, n=null description) [y] ?" +set ans = $< +if ((_$ans == _) || (_$ans == _y) || (_$ans == _Y)) then + set nodesc = 0 +else + set nodesc = 1 +endif +echo "" +echo "The default keyword substitutions are as follows and are" +echo "applied in the order specified:" +set i = 1 +while ($i <= $#sccs_keywords) +# echo ' '\"$sccs_keywords[$i]\"' ==> '\"$rcs_keywords[$i]\" + echo " $sccs_keywords[$i] ==> $rcs_keywords[$i]" + @ i = $i + 1 +end +echo "" +echo -n "Do you want to change them [n] ?" +set ans = $< +if ((_$ans != _) && (_$ans != _n) && (_$ans != _N)) then + echo "You can't always get what you want." + echo "Edit this script file and change the variables:" + echo ' $sccs_keywords' + echo ' $rcs_keywords' +else + echo "good idea." +endif + +# create the sed script +set i = 1 +while ($i <= $#sccs_keywords) + echo "s,$sccs_keywords[$i],$rcs_keywords[$i],g" >> $sedfile + @ i = $i + 1 +end + +onintr ERROR + +############################################################ +# Loop over every s-file in SCCS dir +# +foreach sfile (SCCS/s.*) + # get rid of the "s." at the beginning of the name + set file = `echo $sfile:t | sed -e "s/^..//"` + + # work on each rev of that file in ascending order + set firsttime = 1 + sccs prs $file | grep "^D " | awk '{print $2}' | sed -e 's/\./ /g' | sort -n -u +0 +1 +2 +3 +4 +5 +6 +7 +8 | sed -e 's/ /./g' > $revfile + foreach rev (`cat $revfile`) + if ($status != 0) goto ERROR + + # get file into current dir and get stats + set date = `sccs prs -r$rev $file | grep "^D " | awk '{printf("19%s %s", $3, $4); exit}'` + set author = `sccs prs -r$rev $file | grep "^D " | awk '{print $5; exit}'` + echo "" + echo "==> file $file, rev=$rev, date=$date, author=$author" + sccs edit -r$rev $file >>& $logfile + if ($status != 0) goto ERROR + echo checked out of SCCS + + # add RCS keywords in place of SCCS keywords + sed -f $sedfile $file > $tmpfile + if ($status != 0) goto ERROR + echo performed keyword substitutions + cp $tmpfile $file + + # check file into RCS + if ($firsttime) then + set firsttime = 0 + if ($nodesc) then + echo about to do ci + echo ci -f -r$rev -d"$date" -w$author -t$emptyfile $file + ci -f -r$rev -d"$date" -w$author -t$emptyfile $file < $initialfile >>& $logfile + if ($status != 0) goto ERROR + echo initial rev checked into RCS without description + else + echo "" + echo Enter a brief description of the file $file \(end w/ Ctrl-D\): + cat > $tmpfile + ci -f -r$rev -d"$date" -w$author -t$tmpfile $file < $initialfile >>& $logfile + if ($status != 0) goto ERROR + echo initial rev checked into RCS + endif + else + # get RCS lock + set lckrev = `echo $rev | sed -e 's/\.[0-9]*$//'` + if ("$lckrev" =~ [0-9]*.*) then + # need to lock the brach -- it is OK if the lock fails + rcs -l$lckrev $file >>& $logfile + else + # need to lock the trunk -- must succeed + rcs -l $file >>& $logfile + if ($status != 0) goto ERROR + endif + echo got lock + sccs prs -r$rev $file | grep "." > $tmpfile + # it's OK if grep fails here and gives status == 1 + # put the delta message in $tmpfile + ed $tmpfile >>& $logfile <<EOF +/COMMENTS +1,.d +w +q +EOF + ci -f -r$rev -d"$date" -w$author $file < $tmpfile >>& $logfile + if ($status != 0) goto ERROR + echo checked into RCS + endif + sccs unedit $file >>& $logfile + if ($status != 0) goto ERROR + end + rm -f $file +end + + +############################################################ +# Clean up +# +echo cleaning up... +mv SCCS old-SCCS +rm -f $tmpfile $emptyfile $initialfile $sedfile +echo =================================================== +echo " Conversion Completed Successfully" +echo "" +echo " SCCS history now in old-SCCS/" +echo =================================================== +set exitval = 0 +goto cleanup + +ERROR: +foreach f (`sccs tell`) + sccs unedit $f +end +echo "" +echo "" +echo Danger\! Danger\! +echo Some command exited with a non-zero exit status. +echo Log file exists in $logfile. +echo "" +echo Incomplete history in ./RCS -- remove it +echo Original unchanged history in ./SCCS +set exitval = 1 + +cleanup: +# leave log file +rm -f $tmpfile $emptyfile $initialfile $sedfile $revfile + +exit $exitval |