rsalz@uunet.uu.net (Rich Salz) (05/04/90)
Submitted-by: Dick Grune <dick@cs.vu.nl> Posting-number: Volume 22, Issue 13 Archive-name: cvs3.0/part01 [ This is the basis for Brian Berliner's CVS presented at the last Usenix, to appear tomorrow. --r$ ] CVS, published last in comp.sources.unix in "Volume 6 (Ends mid-July, 1986)", has evolved a bit, under user demand, hopefully without succumbing to creeping featurism. This is Release 3 (the previous published one was probably Release 1, acc. to present nomenclature). CVS is a front end for RCS, supporting the concurrent and independent use of an RCS directory by several people. See manual page cvs.1. This set of shell scripts assumes the presence of the RCS programs rcs, ci, co, rcsmerge and rlog (by Walter Tichy). Kind regards, Dick Grune Vrije Universiteit de Boelelaan 1081 1081 HV Amsterdam the Netherlands dick@cs.vu.nl ---------------------------------------------------------------- : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting 'READ_ME' sed 's/^X//' > 'READ_ME' << '+ END-OF-FILE ''READ_ME' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: READ_ME,v 3.2 89/09/26 15:33:30 dick Exp $ X XThis is Release 3, 890925. X XCVS is a front end for RCS, supporting the concurrent and independent Xuse of an RCS directory by several people. See manual page cvs.1. X XThis set of shell scripts assumes the presence of the RCS programs Xrcs, ci, co, rcsmerge and rlog (by Walter Tichy). X XTo install, examine the Makefile and give suitable values to: X XCVSBIN the directory for the commands themselves eg. /usr/local/bin XCVSLIB idem for the auxiliaries eg. /usr/lib/local/cvs XCVSMAN idem for the manual page cvs.1 eg. /usr/man/man1 XRCSBIN the directory that holds the RCS programs eg. /usr/bin X XThen call make install X XBe sure you can write/create: X in $(CVSBIN): AE CM CV DF GC HR LS NR RC RM RV UV REP LAR LAU LCK X in $(CVSLIB): anything X in $(CVSMAN): cvs.1 X XHistorian: X Unlike the previous releases this release keeps a configuration history X file. To construct such a file retroactively a 'historian' has been X added. See manual page historian.1. Install by calling X make install.hist X Be sure you can write/create: X in $(CVSBIN): historian hist1 hist2 coALL X in $(CVSMAN): historian.1 X XChanges from release 880312 (configuration 1.93, should have been Release 2): X features a series of commands to handle sets of repositories X keeps a configuration history file X release numbers can be set for a (set of) repositories X XChanges from release 860518 (configuration 1.61, should have been Release 1): X preserves inodes when updating and committing X DF has a better idea of what has changed X maintains CVS.adm/Files containing all file names X environment variables $RCSBIN and $CVSPATH, to access binaries X Changed the name of the attic directory from .old to Attic. X X X Dick Grune X Vrije Universiteit X de Boelelaan 1081 X 1081 HV Amsterdam X the Netherlands X dick@cs.vu.nl + END-OF-FILE READ_ME chmod 'u=rw,g=r,o=r' 'READ_ME' set `wc -c 'READ_ME'` count=$1 case $count in 1973) :;; *) echo 'Bad character count in ''READ_ME' >&2 echo 'Count should be 1973' >&2 esac echo Extracting 'Makefile' sed 's/^X//' > 'Makefile' << '+ END-OF-FILE ''Makefile' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: Makefile,v 3.2 89/09/28 17:42:41 dick Exp $ X XCVSBIN = /home/top/dick/bin# # where to install the CVS programs XCVSLIB = /home/top/dick/lib/cvs# # where to install the CVS auxiliaries XCVSMAN = /home/top/dick/man# # where to install the CVS manual XRCSBIN = /usr/local/bin# # where the RCS binaries reside X XINF = READ_ME Makefile Install cvs.1 historian.1 XPRG = AE CM CV DF GC HR LS NR RC RM RV UV REP LAR LAU LCK XAUX = BE.aux CA.aux CC.aux CI.aux CS.aux EF.aux FN.aux HN.aux LR.aux MF.aux \ X ND.aux NR.aux OP.aux RG.aux SC.aux SL.aux VN.aux VT.aux WL.aux XHIST = historian hist1 hist2 coALL X Xwhat: X @echo "Call is: make [ install | install.hist | .distr | shar | clean ]" X Xinstall: install.files $(CVSMAN)/cvs.1 X Xinstall.files: X for F in $(PRG); do ./Install $$F $(CVSBIN) $(CVSLIB) $(RCSBIN); done X for F in $(AUX); do ./Install $$F $(CVSLIB) $(CVSLIB) $(RCSBIN); done X Xinstall.hist: X for F in $(HIST); do ./Install $$F $(CVSBIN) $(CVSLIB) $(RCSBIN); done X cp historian.1 $(CVSMAN)/historian.1 X X$(CVSMAN)/cvs.1: cvs.1 X cp cvs.1 $(CVSMAN)/cvs.1 X X# create a (composite) shar file shar[12] Xshar: shar1 shar2 XSHAR1 = $(INF) $(AUX) $(HIST) XSHAR2 = $(PRG) X Xshar1: $(SHAR1) Makefile X shar $(SHAR1) >shar1 X Xshar2: $(SHAR2) Makefile X shar $(SHAR2) >shar2 X X.distr: Makefile X echo $(SHAR1) $(SHAR2) | tr ' ' '\012' >.distr X Xclean: X rm -f shar[12] .distr X + END-OF-FILE Makefile chmod 'u=rw,g=r,o=r' 'Makefile' set `wc -c 'Makefile'` count=$1 case $count in 1469) :;; *) echo 'Bad character count in ''Makefile' >&2 echo 'Count should be 1469' >&2 esac echo Extracting 'cvs.1' sed 's/^X//' > 'cvs.1' << '+ END-OF-FILE ''cvs.1' X.\" This file is part of the Concurrent Versions System CVS. X.\" Written by Dick Grune, Vrije Universiteit, Amsterdam. X.\" $Header: cvs.1,v 3.3 89/10/06 12:58:22 dick Exp $ X.TH CVS 1 89/09/25 "Vrije Universiteit" X.SH NAME Xcvs \- concurrent-versions system X.SH SYNOPSIS X.B CV Xrepository-name X.br X.B UV X[ X.B \-n X] [ filename ... ] X.br X.B CM X[ X.B \-n X] 'log-message' [ filename ... ] X.br X.B AE X[ \-... ] filename ... X.br X.B RM Xfilename ... X.br X.B LS X[ filename ... ] X.br X.B DF X[ \-... ] [ filename ... ] X.br X.B GC X.br X.B HR X[ repository-name ] X.br X.B NR Xrelease-number repository-name X.br X.B RC X[ X.B \-i X] [ repository-name ] X.br X.B RV Xrepository-name configuration-identifier X.sp X.B REP X[ X.B \-n X] CVS-command ... X.br X.B LAR Xdirectory X.br X.B LAU X.sp X.B LCK X[ X.B on X| X.B off X] X.SH DESCRIPTION X.I CVS Xsupports the concurrent use of independent versions of an RCS directory or a Xset of RCS directories, and as such acts as a front end for RCS. The user is Xnot required to know RCS commands or ever give them. The original files of a Xproject reside in one or more RCS directories, called X.IR repositories , Xand are handled by the above commands only. The casual user uses X.I UV Xand X.I CM Xand may use X.IR CV , X.IR DF Xand X.IR LS ; Xthe other commands are for maintenance only. X.PP XEach participant in the project has his own private copy of the Xfiles; such a copy is called a X.IR configuration . XEach participant can work on his copy at his convenience since it Xis totally his; the command X.I UV X(Update Version) Xwill merge updates to the repository into his files without Xdisturbing his own modifications; he can merge his own modifications back Xinto the repository with the command X.I CM X(commit). Concurrency conflicts, which turn out to be rare anyway, are Xalmost always detected. The repository is protected by multi-reader Xsingle-writer locks. There is a simple facility for sets of user Xdirectories and repositories; see below. X.PP X.B "Commands" X.br X.B CV X(Create Version) creates a version of the configuration described by a Xrepository. This configuration is owned totally by the user and is actually Xan independent copy, to be dealt with as seen fit. Once X.I CV Xhas been called Xin a given directory, it never needs to be called again. The Xuser can keep up-to-date by calling X.I UV Xwhen he feels like it; Xthis will supply him with a merge of his own modifications Xand the changes made by others in the repository. See X.I UV Xfor details. X.PP XWhen the user is satisfied with his own modifications, the Xpresent configuration can be committed by X.I CM X(ComMit); this keeps the present configuration in tact. X.PP XThe call is X.br X CV X.I repository-name X.br Xwith preferably the full path name of the repository. X.I CV Xwill then make the initial copy (at RCS speed). Files in the Xworking directory with names that also occur in the repository are Xsupposed to derive already from the RCS files. X.PP X.I CV Xcreates a directory X.IR ./CVS.adm , Xin which X.I CVS Xkeeps its Xadministration, in a number of files. Only the file X.I ./CVS.adm/Repository Xis of importance to the user, since it contains Xthe name of the repository. This file is a normal file and can be Xedited by the user, if necessary (when the repository is moved, e.g.). X.PP X.B UV X(Update Version) updates the configuration in the present directory with Xrespect to the repository. The present configuration must have been created Xby X.I CV. XThe call is X.br X UV X.br Xfor a general update, or X.br X UV X.I file ... X.br Xfor a partial update. X.PP XModified or new RCS files are checked out. XModified user files are reported on standard output Xas X.I "M\ user_file." XIf both the XRCS file and the user file have been modified, the user file Xis replaced by the result of X.I rcsmerge. XIf this throws up irreconcilable differences, the file is reported as X.I "C\ user_file," Xand as X.I "M\ user_file" Xotherwise. XFiles added but not yet committed are reported as X.I "A\ user_file." XFiles removed but not yet decommitted are reported as X.I "R\ user_file." X.PP X.I UV Xallows a X.B \-n Xoption, which restricts the actions to reporting only. X.PP X.B CM X(ComMit) commits the present configuration to the repository, X.I after Xhaving done a test on conflicts. The call is X.br X CM X.I log-message X.br Xfor a general commit, and X.br X CM X.I "log-message file ..." X.br Xfor a (dangerous!) partial commit. The X.I log-message Xis obligatory, and will be passed to RCS to be stored in the affected Xrepository files. X.PP X.I CM Xallows a X.B \-n Xoption, which restricts the actions to reporting only. X.PP X.B AE X(Add Entries) adds new entries to the present configuration; for each file it Xasks for a description, in RCS fashion. XThe entries will be added to the repository upon the next call of X.I CM. XThe user files must already exist. X.I AE Xon a file removed with X.I RM Xwill resurrect the file, unless its removal has already been committed. XAny options to X.I AE Xwill be passed on to X.I rcs \-i X(see RCS manual). X.PP X.B RM X(ReMove) marks the entries as removed on purpose from the present Xconfiguration. The RCS files will be actually removed from the repository Xupon the next call of X.I CM; Xthey will be moved to a directory X.I Attic Xin the repository. X.PP X.B LS Xprints three lines of information for each of its arguments, Xone for the user file (line 1), one for the newest RCS file X(line 3) and one for the RCS file both derive from (line 2). XLike the Unix X.I ls, Xit will treat all files if no arguments are given. X.PP X.B DF Xdoes a nice form of diff(1) on each of its arguments and the XRCS file that argument derives from. XIf there are options, these are passed to diff(1) and the diff Xformat is adhered to; otherwise a more readable format is produced. XStandard diff(1) format can also be forced by a single \-. XIf there are no file names, X.I DF Xtreats the files that have been modified since the last call to X.I CM. XIf the option is X.B \-n, Xdiff(1) will not be called, but the list of modified files will be displayed Xinstead. X.PP X.B GC X(Garbage Collection) collects garbage, dust & dead wood. Should be called Xafter crashes while a X.IR CVS -program Xwas running, and other mishaps. XIt is up to the user to remove (or not!) the files X.I GC Xcomplains about. X.PP X.B HR X(Highest Release number) writes the highest release number of any RCS file in Xthe repository to standard output. If no argument is given, the command Xapplies to the repository of which the working directory derives. The "release Xnumber" is the first part of the RCS revision number. X.PP X.B NR X(New Release number) sets the (highest) release number of a repository to the Xnumber which is its first argument. The repository should have been locked by X.I "LCK on" Xalready. The number must be higher than the present release number. X.PP X.B "Examining and restoring previous versions" X.br X.I CVS Xkeeps a history of the versions of the configurations that have been Xcommitted to the repository. X.PP X.B RC X(Retrieve Configuration history) displays the configuration identifier, Xdate and log message of each version. A configuration is represented by a X.IR "configuration identifier" , Xwhich is basically the version number of a record describing the contents of Xthe configuration. This configuration identifier can be presented to X.I RV, Xwhich will restore the identified configuration; this process Xrequires the repository again (or still) to be present, though not Xnecessarily with the same path name. X.br X RC \-i X.br Xwill print the configuration identifier of the present configuration. X.I RC Xcan be given the name of a repository as a parameter, and will then work on Xthat repository. X.PP XOlder versions of CVS (before Release 3) did not keep this configuration Xhistory; it can be reconstructed for old repositories by using the program X.I historian ; Xsee historian(1). X.PP X.B RV X(Restore Version) restores a version of the configuration, given the Xrepository name and a configuration identifier. The call is X.br X RV X.I "repository-name configuration-identifier" X.br XThe repository has to exist; the files will be reconstructed with the correct Xrevision number, even if they were removed by X.I RM Xand X.I CM Xin the meantime. X.PP XFor backward compatibility, X.I RV Xwill still be able to work from SV-records, as created by the late program XSV. The SV-record will be read from standard input by the call X.B RV X.I "repository-name" X.B \- X.PP XIf the configuration identifier is kept of the distribution sent to a client, Xthe following scenario is useful when the client sends in some Xcorrections. In an empty directory, call X.I "RV conf-idf" Xto reconstruct the client's files. Apply his corrections. Call X.I UV Xto integrate them with your own innovations. Call X.I DF Xand test, to see if they still make sense. If satisfied, call X.I CM Xand remove the directory. X.PP X.B "Sets of directories" X.br XProjects are often not confined to a single repository, nor to a single user Xdirectory, and having CVS commands that work on sets of both would be useful. XThere is, however, no generally accepted tree structure for RCS directories Xwith subdirectories, so the user is required to specify their structure and the Xrelated user directory structure. This information, which includes a list of Xdirectories or repositories, is fed (on standard input) Xto X.B REP X(for Repeat) which is given the CVS command to be repeated as its first Xargument. A second reason for this factorized approach is that CVS commands on Xsets of repositories can take hours, may come to an abnormal end, and may have Xto be restarted somewhere in the middle. The latter can be achieved by Xsupplying the remainder of the input list to a second call of X.I REP. X.PP X.I REP Xis not naive about the command under its control and knows that different Xcommands require different arguments; depending on its command X.I REP Xitself will require different input and further arguments. Several types of Xcalls can be distinguished. X.LP X <UserDir-list REP UV X.br X <UserDir-list REP CM 'message' X.br X <UserDir-list REP LS X.br X <UserDir-list REP DF X.br X <UserDir-list REP GC X.br XThe commands require a list of user directory names as input, and will Xperform the named command in all these directories. X.LP X <Repository-list REP RC [ \-i ] X.br X <Repository-list REP HR X.br X <Repository-list REP NR release-number X.br XThe commands require a list of repository names as input. X.I "REP RC" Xgives a formatted report of the configuration histories and X.I "REP RC \-i" Xproduces output of the form X.br X <repository-name> <configuration-identifier> X.br Xwhich can serve as a basis for input to a later call of X.IR "REP RV" . X.I "REP HR" Xgives the over-all highest release number in the repository tree. X.I "REP NR release-number" Xsets the over-all highest release number in the repository tree to X.I release-number. X.LP X <Repository-UserDir-list REP CV X.br XThe command requires a list of repository-name/user-directory-name pairs X(separated by a space) as input, and will create the described versions, Xcreating user directories if necessary. X.LP X <Repository-UserDir-ConfIdf-list REP RV X.br XThe command requires a list of Xrepository-name/user-directory-name/configuration-identifier triplets X(separated by spaces) as input, and will restore the described versions, Xcreating user directories if necessary. X.PP XThe CVS commands X.I AE Xand X.I RM Xcannot be repeated. X.I REP Xitself can have a X.B \-n Xoption, which causes it to print its commands rather than execute them. X.PP XThe input to X.I REP Xcan be obtained in various ways. The user (project manager) can keep files that Xembody the proper interrelationships; if the relations are irregular, that may Xbe the only way. UserDir lists can be generated by X.B LAU X(List All User directories), which lists all user directories under CVS that Xare subdirectories of the working directory, according to the criterion that Xa user directory under CVS contains a directory X.IR CVS.adm . XConsequently, X.br X LAU | REP UV X.br Xwill do an update on the working directory and all its CVS subdirectories. XRepository-lists can be generated by a call of X.B LAR X(List All Repositories). X.I "LAR directory" Xlists all repositories that are subdirectories of X.IR directory , Xaccording to the criterion that a repository contains RCS files and that it Xis not named X.I Attic Xor X.IR Admin . XConsequently, X.br X LAR <top-repository> | REP HR X.br Xwill display the over-all highest release number in the whole repository tree. XMore complex input lists (for X.I CV Xand X.IR RV ) Xwill have to be constructed by additional means. If the user tree is to have Xthe same form as the repository tree, the following X.IR sed (I) Xcommand may be useful: X.DS X.cw Xsed ' X s/.*/&|&/ X s|'"$RCSPREFIX"'|'"$USERPREFIX"'| X s/\e(.*\e)|\e(.*\e)/\e2\ \e1/ X\&' X.ft 0 X.DE Xwhich converts, e.g. X.br X /home/x8/RCS/part3/module5 X.br Xinto X.br X /home/x8/RCS/part3/module5 /usr/x8/part3/module5 X.br Xwith the setting RCSPREFIX=/home/x8/RCS and USERPREFIX=/usr/x8, thus creating Xinput to X.IR "REP CV" . X.PP X.B LCK Xcan be used to manually lock (first argument X.BR on ) Xand unlock (first argument X.BR off ) Xa repository. Although this command can be used on separate repositories, it Xis normally used on a set (tree) of them, which is why it is treated here. It Xshould X.I not Xbe used by the normal user; X.I CM Xand X.I UV Xhandle all normal cases. The command is required before doing X.IR NR , Xand is useful to ensure that no activity takes place in a repository. X.PP X.B "Setting up" X.br XTo set up a repository X.I repos, Xmake an empty directory of that name, call X.I "CV repos," Xdo X.I AE Xfor each file to go into the repository and finally call X.I CM Xto commit the initial version. X.PP XTo participate in an existing repository X.I repos, Xi.e., to create your own private configuration of a repository, just call X.I "CV repos". X.PP XTo turn an existing RCS directory into a repository, you can likewise call X.I "CV repos", Xsince no administration is kept in the RCS directory. XThis works even if both the user files and Xthe RCS directory already exist (this is useful if you want to start using X.I CVS Xfor an existing project). X.PP X.B "Remarks" X.br XIt is generally not wise to interrupt a CVS command: many of them perform a Xlarge number of actions that are only meaningful if done in their entirety or Xnot at all, and UNIX is not good at pretending it's all one indivisible Xaction. If a CVS command has succumbed to a system crash, act as follows. XCall X.I GC Xrepeatedly and act on its messages until it shuts up. You can Xunlock an RCS file that may have been left locked by calling X.I "rcs -u", Xand unlock a repository by calling X.I "LCK off repos". XThen call X.I UV Xand act on its messages until it shuts up. And then call X.I UV Xagain (this is necessary to get the time stamps right in some cases). X.PP XIf the user configuration is quiescent (i.e., X.I "DF \-n" Xgives no output), the user can remove his files with impunity; a Xsubsequent call of X.I UV Xwill restore the full configuration. X.SH "ENVIRONMENT VARIABLES" X.IP RCSBIN 8 XIf defined: the name of the directory where the RCS programs reside. XDefault: as determined in the X.I Makefile. X.IP CVSPATH 8 XIf defined: the search path for non-RCS programs. Default: X.I /bin:/usr/bin. X.SH FILES X.ta 8n 36n XIn the present directory: X.br X *,[pt] options and text from X.I AE X.br XIn the directory ./CVS.adm: X.br X Repository holds name of repository X.br X Files list of file names in the configuration X.br X Entries version number and time stamp for each file X.br X Entries.Backup X.br X Mod names of files modified since last X.I CM X(or since X.IR CV ) X.br X LastUpdate time stamp of latest full update X.br XIn the repository: X.br X Attic/ attic for removed files X.br X #cvs.* multi-reader single-writer locks X.br X Admin/ holds X.I CVS.confrec,v Xfor the configuration history X.br X and X.I HighestRelease Xfor the highest release number X.br XElsewhere: X.br X rcs, ci, co, rcsmerge, rlog RCS programs X.SH SEE ALSO Xhistorian(1); RCS documentation, rcsintro(1) X.SH AUTHOR XDick Grune, Vrije Universiteit, Amsterdam X.SH DIAGNOSTICS XBoth X.I UV Xand X.I CM Xattempt first to make sure that all required actions are possible before Xdoing any of them. X.SH DISADVANTAGES XIf X.I N Xusers participate, there will be X.I N Xcopies on disk. X.br XIt's all shell files and slow. X.br X.SH BUGS XThere is not (yet) a way to work with branches. X.br XFunny file names (e.g. containing spaces or *) will give trouble. X.br XWeird things happen if the RCS programs cannot be found. X.br XDo not run two of the X.I CVS Xprograms simultaneously in the same user Xdirectory; there is no lock-out on the user directory, for Xefficiency reasons (though there is on the repository). + END-OF-FILE cvs.1 chmod 'u=rw,g=r,o=r' 'cvs.1' set `wc -c 'cvs.1'` count=$1 case $count in 16569) :;; *) echo 'Bad character count in ''cvs.1' >&2 echo 'Count should be 16569' >&2 esac echo Extracting 'historian.1' sed 's/^X//' > 'historian.1' << '+ END-OF-FILE ''historian.1' X.\" This file is part of the Concurrent Versions System CVS. X.\" Written by Dick Grune, Vrije Universiteit, Amsterdam. X.\" $Header: historian.1,v 3.2 89/10/02 15:15:21 dick Exp $ X.TH HISTORIAN 1 89/09/25 X.SH NAME Xhistorian \- reconstruct configuration history for CVS X.SH SYNOPSIS X.B historian X[ repository ] X.br X.B hist1 X[ repository ] X>ph1 X.br X.B hist2 X[ repository ] X<ph1 >ph2 X.br X.B coALL Xfilename X.SH DESCRIPTION XRelease 3 of CVS keeps the history of the project in an RCS file X.IR $Repository/Admin/CVS.confrec,v , Xwhich holds the revisions of the X.I "configuration record," Xwhich in its turn is a file with the names of the files that make up the Xconfiguration, with their version numbers. If you start using CVS on a new Xrepository, CVS will create such a configuration history file for you Xand maintain it. If, however, you use the new CVS on an old Xrepository, then CVS, not knowing any better, will also create this Xconfiguration history file, and subsequent calls to RC will suggest that the Xrepository originated at the time you started using the new CVS: your previous Xconfiguration history is lost. This may or may not bother you. If it does Xnot, there is no problem; everything will work normally, except that older Xconfigurations cannot be retrieved by configuration identifier using X.I RV X(they can still be retrieved manually or by using old output of SV). X.PP X.I "Reconstruction, ignoring removed files" X.PP XThe program X.I historian Xcan help you to recreate (or more precisely: to create) the configuration Xhistory of the entire repository from the moment it was first brought Xunder RCS (not: CVS!). It can be called with or without a parameter; it will Xthen reconstruct the configuration history file for the repository belonging Xto the working directory, or for the repository given as a parameter. This Xwill take a couple of minutes and the result can be enjoyed by calling X.I "RC." X.PP XThe resulting configuration history file will be correct if no files have Xever been removed from the indicated configuration. XIf files have been removed from the configuration (using X.IR RM ), Xthen there is a minor but serious problem: the historian cannot find out Xexactly when a file was removed from the configuration; it will tell you so Xbut it will nevertheless construct a configuration history file. Files which Xare removed are moved to X.IR $Repository/Attic , Xbut their arrival there was not recorded anywhere and their last modification Xtime is not a good indication either. So, to get this right, the historian Xneeds help from a human. X.PP XThere are two things you can do about this. One is to do nothing; the result is Xthat some old configurations, as retrieved by X.I RV, Xwill contain files Xthat should not have been there. However, the history of all configurations Xcreated after the first CM from CVS Release 3 will be correct and will not Xshow any obsolete files any more. If this is acceptable, doing Xnothing about the removed files is by far the easiest option. X.PP X.I "Reconstruction, considering removed files" X.PP XIt is possible to tell the historian exactly when a file was removed. To Xunderstand the method, we have to take a closer look at what the historian Xdoes. It consists of three phases, executed by X.I hist1, X.I hist2 Xand X.I sh, Xrespectively. X.PP X.I Hist1 Xdoes a call of the RCS program X.I rlog Xon all the files in the repository and the Attic, and combines the output into Xa list of changes at each commit. For each commit that the historian is able Xto discern, it writes a group of lines, each line identifying time, file Xname, RCS version number, author and message of a single file. This group Xdescribes the forward X.I delta Xeffected by the identified commit and is terminated by a blank line, which is Xessential to the functioning of X.I hist2. X.PP X.I Hist2 Xreads this list from standard input and constructs from it a shell script that Xwill construct the configuration history file in a sequence of calls to the RCS Xprogram X.I ci Xand to the UNIX editor X.I ed. XThe contents of this script can only be described as "gross". X.PP XThis script is then fed to the UNIX shell X.I sh. XSo, the following pipe line will construct the configuration history file: X.br X.B " hist1 | hist2 | sh" X.br X.PP XThis is indeed the main contents of the program X.I historian. X.PP XThe input to X.I hist2 Xnormally consists of the list of commit deltas, where each line in a commit Xdelta consists of many fields. If a line in a commit delta contains one field Xonly, it is taken by X.I hist2 Xto be the name of a file which was removed during the commit of that Xdelta. So, by editing the output of X.I hist1 Xand adding file names in the proper places, the user can tell X.I hist2 Xwhen files were removed; be sure not to add or remove blank lines Xduring this edit operation, especially not the one at the end of the file. XThe need to manually edit the information stream at some point is the main Xreason why the historian's process was divided into two parts. X.PP XThe problem is that it is very difficult for the user to find out during which Xcommit the file was removed. The following approach may be useful. X.PP XWhen a file is used in a configuration, it is likely to be mentioned in the XMakefile. The historian's aid X.I coALL Xcan be used to retrieve all versions of, e.g., the Makefile. A call X.br X.B " coALL Makefile" X.br Xcreates a directory X.I Makefile.ALL Xand stores in it all versions of the Makefile, each identified by its RCS Xversion number. By using the UNIX command X.I grep Xon these files, it is often easy to determine in which versions of the XMakefile a given file was used. This gives the highest version number in Xwhich it was used, and consequently, the version number of the first Makefile Xthat no longer uses it. The commit delta in the input of X.I hist2 Xthat enters this version of the Makefile should contain the remove message for Xthe file being examined. X(coALL will also work on other file names). X.PP XThe process of identifying a file in a configuration by inspecting e.g., a XMakefile is so problem-dependent that I think it is not worth while to Xautomate it. A file X.I read.c Xmay for instance occur as X.I read.o Xin the Makefile. X.PP XThe commands X.I hist1 Xand X.I hist2 Xdo not affect any files and can be run as often as desired, irrespective of the Xpresence of a configuration history file. The resulting shell script will only Xrun if there is no configuration history file already; it will only affect X.IR $Repository/Admin/CVS.confrec,v . XIf this file is removed, the script can be run as often as desired (i.e. Xuntil it does what you want). X.SH FILES Xhist1 X.br Xhist2 X.br XcoALL X.SH SEE ALSO Xcvs.1 X.SH AUTHOR Xdick@cs.vu.nl (Dick Grune @ Vrije Universiteit, Amsterdam) X.SH DIAGNOSTICS XThe scripts take some liberty with the RCS commands, which sometimes give Xwarnings or error messages; these can be mostly ignored. Error messages from Xthe historian's commands are always identified as such. X.SH CAVEATS XThis is not production-quality software; be sure to check its effects. X.br XThe resulting shell script thinks it knows the internal structure of RCS Xfiles and modifies them under evasion of the normal interface. X.SH BUGS XThe first part of the historian relies on two consecutive commits never Xhaving the same message; if they have, they will coalesce. + END-OF-FILE historian.1 chmod 'u=rw,g=r,o=r' 'historian.1' set `wc -c 'historian.1'` count=$1 case $count in 7288) :;; *) echo 'Bad character count in ''historian.1' >&2 echo 'Count should be 7288' >&2 esac echo Extracting 'BE.aux' sed 's/^X//' > 'BE.aux' << '+ END-OF-FILE ''BE.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: BE.aux,v 3.1 89/09/25 16:29:18 dick Exp $ X X# X# B u i l d E n t r y X# Script, to be included. X# X# Assumes set: X# $CVSLIB X# $Name X# $Options X# $Rcs X# $Repository X# $User X# X# Builds an entry for a new file and sets up $User,[pt] by X# interrogating the user. X# X# Sets OK to no and calls continue, if necessary. X# X X# there may be an old file with the same name in the attic! X# this is an awkward place to test, but other places are equally awkward Xif # it is in the attic already X [ -r $Repository/Attic/$User,v ] Xthen X echo $Name: there is an old file $User already \ X in $Repository/Attic >&2 X OK=no X continue Xfi X X# isn't the name too long? Xif # both $User and $User,x can be linked made by linking X ln $User $User, >/dev/null 2>/dev/null \ X&& X ln $User $User,x >/dev/null 2>/dev/null Xthen X rm $User, $User,x Xelse X rm -f $User, X echo $Name: filename $User is too long >&2 X OK=no X continue Xfi X X# store the options Xecho "$Options" >$User,p X X# get a description file by imitating a call of rcs -i Xecho "RCS file: $Rcs" Xecho "enter description, terminated with ^D or '.':" Xecho "NOTE: This is NOT the log message!" Xcp /dev/null $User,t Xwhile # the user still provides text X read TXT Xdo # add it to $User,t, except if it is a single dot X if # it is the terminating dot X [ "$TXT" = "." ] X then X break X fi X echo "$TXT" >>$User,t Xdone Xecho done X X# create the entry (at the end, since the user may have interrupted) X$CVSLIB/RG.aux $User 0 "Initial $User" + END-OF-FILE BE.aux chmod 'u=rwx,g=rx,o=rx' 'BE.aux' set `wc -c 'BE.aux'` count=$1 case $count in 1585) :;; *) echo 'Bad character count in ''BE.aux' >&2 echo 'Count should be 1585' >&2 esac echo Extracting 'CA.aux' sed 's/^X//' > 'CA.aux' << '+ END-OF-FILE ''CA.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: CA.aux,v 3.1 89/09/25 16:29:27 dick Exp $ X X# X# C r e a t e A d m i n i s t r a t i o n X# Script, to be included. X# X# Assumes set: X# $Name X# $Repository X# X# Creates a user CVS administration directory based on repository X# $Repository. X# X X# install CVS.adm directory Xif # there is already a directory CVS.adm X [ -d CVS.adm ] Xthen X echo $Name: this directory is already managed by CVS >&2 X exit 1 Xfi X Xif # we can create the administration directory X mkdir CVS.adm Xthen : Xelse X echo $Name: cannot make administration directory ./CVS.adm >&2 X exit 1 Xfi X X# set up the administration Xecho $Repository >CVS.adm/Repository Xcat /dev/null >CVS.adm/Entries + END-OF-FILE CA.aux chmod 'u=rw,g=r,o=r' 'CA.aux' set `wc -c 'CA.aux'` count=$1 case $count in 777) :;; *) echo 'Bad character count in ''CA.aux' >&2 echo 'Count should be 777' >&2 esac echo Extracting 'CC.aux' sed 's/^X//' > 'CC.aux' << '+ END-OF-FILE ''CC.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: CC.aux,v 3.2 89/10/13 12:04:18 dick Exp $ X X# X# C o m m i t C o n f i g u r a t i o n f i l e X# Script, to be included. X# X# Assumes set: X# $Name X# $ACT X# $Repository X# $Message X# $RCSBIN X# $RcsCfr X# $UsrCfr X# $Revision # -r<number> or empty X# X# Commits the new version of the configuration history file, $UsrCfr X# X X# we need the configuration history file Xif # there is a configuration history file X [ -r $RcsCfr ] Xthen : Xelse # try to create it X if echo "Configuration history file handled automatically by CVS" | X $ACT $RCSBIN/rcs -i $RcsCfr X then : X else echo $Name on $Repository: could not create \ X automatic configuration history file >&2 X exit 1 X fi Xfi X X# check it in Xif # lock the RCS file X $ACT $RCSBIN/rcs -q -l $RcsCfr 2>&1 Xthen : Xelse # something went wrong X echo $Name on $Repository: could not lock \ X configuration history file >&2 X rm $UsrCfr X exit 1 Xfi X Xif # check in the configuration record X $ACT $RCSBIN/ci $Revision -m"$Message" -f $RcsCfr $UsrCfr 2>&1 Xthen # the file $UsrCfr will now be gone X : Xelse # something is wrong; unlock the locked file & remove the added file X echo $Name on $Repository: automatic configuration history file \ X not updated >&2 X if # unlock $RcsCfr X $ACT $RCSBIN/rcs -q -u $RcsCfr X then : X else # something very wrong X echo $Name: HELP: could not UNlock $RcsCfr >&2 X fi X X rm -f $UsrCfr X X # and give up X exit 1 Xfi X + END-OF-FILE CC.aux chmod 'u=rw,g=r,o=r' 'CC.aux' set `wc -c 'CC.aux'` count=$1 case $count in 1510) :;; *) echo 'Bad character count in ''CC.aux' >&2 echo 'Count should be 1510' >&2 esac echo Extracting 'CI.aux' sed 's/^X//' > 'CI.aux' << '+ END-OF-FILE ''CI.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: CI.aux,v 3.1 89/09/25 16:29:46 dick Exp $ X X# X# C h e c k I n X# Script, to be included X# X# Assumes set: X# $ACT X# $CVSLIB X# $Message X# $Name X# $RCSBIN X# $Repository X# $User X# X# Does a very careful check-in of the file $User, and tries not X# to spoil its modification time (to avoid useless recompilations) X# X# Sets OK to no, if necessary. X# X Xecho Checking in $User\; log: "$Message" XRcs=$Repository/$User,v X X# offer a copy of $User to RCS/ci, to preserve the inode XOrig=,,$User X$ACT mv $User $Orig X$ACT cp $Orig $User X Xif # check in $Rcs X $ACT $RCSBIN/ci -m"$Message" $Rcs 2>&1 Xthen # the file $User will now be gone; X # get a new $User, with a possibly updated $Header X if # check out $Rcs into $User, creating a new inode X $ACT $RCSBIN/co -q $Rcs X then # restore $Orig from it with as few modifications as possible X if # there were no modifications made by $RCSBIN/co X $ACT cmp -s $User $Orig X then : X else # we must copy these modifications to $Orig X $ACT cp $User $Orig X fi X # undo the whole renaming X $ACT rm -f $User X $ACT mv $Orig $User X else # something is wrong but we have still got $Orig X $ACT mv $Orig $User X echo $Name: could not check out $User again >&2 X OK=no X fi X X # get new version number and time stamp X . $CVSLIB/VT.aux # sets $VN_User, $VN_Rcs, $TS_User, $TS_Rcs X # and register $User X $ACT $CVSLIB/RG.aux $User $VN_Rcs "$TS_User" Xelse # something is very wrong X # restore the old $User X $ACT mv $Orig $User X echo $Name: could not check in $User >&2 X OK=no X if # unlock $Rcs X $ACT $RCSBIN/rcs -u $Rcs X then : X else X echo $Name: could not UNlock $Rcs >&2 X fi Xfi + END-OF-FILE CI.aux chmod 'u=rw,g=r,o=r' 'CI.aux' set `wc -c 'CI.aux'` count=$1 case $count in 1734) :;; *) echo 'Bad character count in ''CI.aux' >&2 echo 'Count should be 1734' >&2 esac echo Extracting 'CS.aux' sed 's/^X//' > 'CS.aux' << '+ END-OF-FILE ''CS.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: CS.aux,v 3.1 89/09/25 16:30:17 dick Exp $ X X# X# C o l l e c t S e t s X# Script, to be included. X# X# Assumes set: X# $@ X# $CVSLIB X# $Name X# $User X# $VN_Rcs X# $VN_User X# $TS_Rcs X# $TS_User X# X# Collects the interesting file names from the administration and X# the repository in a number of shell variables: X# solved by: X# CLIST conflict-ridden (user) X# GLIST modified, needs merging (--/UV) X# MLIST modified, needs checking in (CM/--) X# OLIST needs checking out (--/UV) X# ALIST to be added (CM/--) X# RLIST to be removed (CM/--) X# WLIST remove entry (--/UV) X# X# It sets OK to no if something is wrong. X# X Xfor User in $@ Xdo X Rcs=$Repository/$User,v X . $CVSLIB/VT.aux # sets $VN_User, $VN_Rcs, $TS_User, $TS_Rcs X X # what entry is this? X case $VN_User in X "") X # no entry available, $TS_Rcs is invalid X X # how is the RCS file? X case $VN_Rcs in X "") X # there is no RCS file either X X # how is the user file? X case "$TS_User" in X "") X # there is no user file X echo $Name: nothing known about $User >&2 X OK=no X ;; X *) X # there is a user file X echo $Name: use AE to create entry \ X for $User >&2 X OK=no X ;; X esac X ;; X *) X # there is an RCS file X X # how is the user file? X case "$TS_User" in X "") X # there is no user file X OLIST="$OLIST $User" X ;; X *) X # there is a user file X echo $Name: move away $User\; \ X it is in the way >&2 X CLIST="$CLIST $User" X OK=no X ;; X esac X ;; X esac X ;; X X 0) X # an entry for a new-born file, $TS_Rcs is dummy X X # how is the user file? X case "$TS_User" in X "") X # there is no user file, but there should be one X X echo $Name: warning: \ X new-born $User has disappeared >&2 X WLIST="$WLIST $User" X ;; X *) X # there is a user file X X # how is the RCS file? X case $VN_Rcs in X "") X # there is no RCS file X X ALIST="$ALIST $User" X ;; X *) X # there is an RCS file X X echo $Name: conflict: $User created \ X independently by second party >&2 X CLIST="$CLIST $User" X OK=no X ;; X esac X ;; X esac X ;; X X -*) X # an entry for a removed file, $TS_Rcs is valid X X # how is the user file? X case "$TS_User" in X "") X # there is no user file (as it should be) X X # how is the RCS file? X case -$VN_Rcs in X -) X # there is no RCS file X X # this is all-right, however; it has been X # removed independently by second party X WLIST="$WLIST $User" X ;; X $VN_User) X # the RCS file is the same version as X # the user file X X # and that's OK X RLIST="$RLIST $User" X ;; X *) X # the RCS file is a newer version than X # the user file X X # and this is definitely not OK X echo $Name: conflict: removed $User was \ X modified by second party >&2 X CLIST="$CLIST $User" X OK=no X ;; X esac X ;; X *) X # user file shouldn't be there X echo $Name: $User should be removed \ X and is still there >&2 X OK=no X ;; X esac X ;; X X *) X # a normal entry, $TS_Rcs is valid X X # how is the RCS file? X case $VN_Rcs in X "") X # there is no RCS file X X # how is the user file? X case "$TS_User" in X "") X # there is no user file X echo $Name: warning: $User is not \ X \(no longer\) pertinent >&2 X WLIST="$WLIST $User" X ;; X "$TS_Rcs") X # the user file is still unmodified X echo $Name: $User is no longer \ X in the repository >&2 X WLIST="$WLIST $User" X ;; X *) X # the user file has been modified X echo $Name: conflict: $User is modified but \ X no longer in the repository >&2 X CLIST="$CLIST $User" X OK=no X ;; X esac X ;; X $VN_User) X # the RCS file is the same version as the user file X X # how is the user file? X case "$TS_User" in X "") X # there is no user file X echo $Name: warning: $User was lost >&2 X OLIST="$OLIST $User" X ;; X "$TS_Rcs") X # the user file is still unmodified X # nothing special at all! X ;; X *) X # the user file has been modified X # but do we believe it? This is complicated: X . $CVSLIB/ND.aux # sets MLIST, if necessary X ;; X esac X ;; X *) X # the RCS file is a newer version than the user file X X # how is the user file? X case "$TS_User" in X "") X # there is no user file X echo $Name: warning: $User was lost >&2 X OLIST="$OLIST $User" X ;; X "$TS_Rcs") X # the user file is still unmodified X OLIST="$OLIST $User" X ;; X *) X # the user file has been modified X GLIST="$GLIST $User" X ;; X esac X ;; X esac X ;; X esac Xdone + END-OF-FILE CS.aux chmod 'u=rwx,g=rx,o=rx' 'CS.aux' set `wc -c 'CS.aux'` count=$1 case $count in 4680) :;; *) echo 'Bad character count in ''CS.aux' >&2 echo 'Count should be 4680' >&2 esac echo Extracting 'EF.aux' sed 's/^X//' > 'EF.aux' << '+ END-OF-FILE ''EF.aux' X#!/bin/sh X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: EF.aux,v 3.1 89/09/25 16:31:12 dick Exp $ X X# X# E n t r i e s f i l e t o F i l e s f i l e X# Creates a file CVS.adm/Files containing the names that comprise X# the project, from CVS.adm/Entries. X# X X<CVS.adm/Entries sed ' X /^-/d X s/.* \(.*\)|/\1/ X' | Xsort >CVS.adm/Files + END-OF-FILE EF.aux chmod 'u=rwx,g=rx,o=rx' 'EF.aux' set `wc -c 'EF.aux'` count=$1 case $count in 414) :;; *) echo 'Bad character count in ''EF.aux' >&2 echo 'Count should be 414' >&2 esac echo Extracting 'FN.aux' sed 's/^X//' > 'FN.aux' << '+ END-OF-FILE ''FN.aux' X#!/bin/sh X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: FN.aux,v 3.1 89/09/25 16:31:20 dick Exp $ X X# X# F i n d N a m e s X# Writes to standard output all the pertinent file names, both from the X# administration (included those that were RMed) and from the X# repository $1, sorted. X# X X( X (cd $1; ls -a) | grep ',v$' | sed 's/,v$//' X (<CVS.adm/Entries sed 's/.* \(.*\)|/\1/') X) | Xsort -u + END-OF-FILE FN.aux chmod 'u=rwx,g=rx,o=rx' 'FN.aux' set `wc -c 'FN.aux'` count=$1 case $count in 468) :;; *) echo 'Bad character count in ''FN.aux' >&2 echo 'Count should be 468' >&2 esac echo Extracting 'HN.aux' sed 's/^X//' > 'HN.aux' << '+ END-OF-FILE ''HN.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: HN.aux,v 3.1 89/09/25 16:31:41 dick Exp $ X X# X# H e a d e r N u m b e r X# Script, to be included. X# X# Assumes set: X# $RCSBIN X# $User X# X# Sets the following shell variable: X# HN_user version number in the RCS Header in the file $User X# as found by $RCSBIN/ident; may also be empty, if X# there is no RCS Header. X# X XHN_User=` X ($RCSBIN/ident $User 2>&1) | X grep 'Header: .*,v' | X sed ' X s/.*,v // X s/ .*// X ' X` X + END-OF-FILE HN.aux chmod 'u=rw,g=r,o=r' 'HN.aux' set `wc -c 'HN.aux'` count=$1 case $count in 547) :;; *) echo 'Bad character count in ''HN.aux' >&2 echo 'Count should be 547' >&2 esac echo Extracting 'LR.aux' sed 's/^X//' > 'LR.aux' << '+ END-OF-FILE ''LR.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: LR.aux,v 3.1 89/09/25 16:32:33 dick Exp $ X X# X# L o c a t e R C S F i l e X# Script, to be included. X# X# Assumes set: X# $Repository X# $User X# X# Called when the RCS file sought may be in the attic $Repository/Attic. X# Sets $Rcs to $Repository/Attic/$User,v if appropriate and to X# $Repository/$User,v otherwise. X# X XRcs=$Repository/$User,v XOld=$Repository/Attic/$User,v Xif # it is in the repository X [ -r $Rcs ] Xthen : Xelif # it is in the attic X [ -r $Old ] Xthen X Rcs=$Old Xelse # it is treated as if it were in the repository X : Xfi + END-OF-FILE LR.aux chmod 'u=rw,g=r,o=r' 'LR.aux' set `wc -c 'LR.aux'` count=$1 case $count in 661) :;; *) echo 'Bad character count in ''LR.aux' >&2 echo 'Count should be 661' >&2 esac echo Extracting 'MF.aux' sed 's/^X//' > 'MF.aux' << '+ END-OF-FILE ''MF.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: MF.aux,v 3.1 89/09/25 16:32:49 dick Exp $ X X# X# M o d i f i e d F i l e s X# Prints the names of the files that have been modified since the last X# CM. The list is constructed by combining the contents of CVS.adm/Mod X# (verified to be really different) with time stamp information from X# CVS.adm/LastUpdate. X# X X( # list all files modified between last CM and last UV X cat CVS.adm/Mod X X # list all files modified after last UV X # get the list of all files in the configuration and of X # CVS.adm/LastUpdate, sorted on time X ls -lt `cat CVS.adm/Files` CVS.adm/LastUpdate 2>/dev/null | X # remove the entry CVS.adm/LastUpdate and anything older X sed '/CVS.adm\/LastUpdate/,$d' | X # retrieve files name only X sed 's/.* //' X) | Xsort -u + END-OF-FILE MF.aux chmod 'u=rwx,g=rx,o=rx' 'MF.aux' set `wc -c 'MF.aux'` count=$1 case $count in 857) :;; *) echo 'Bad character count in ''MF.aux' >&2 echo 'Count should be 857' >&2 esac echo Extracting 'ND.aux' sed 's/^X//' > 'ND.aux' << '+ END-OF-FILE ''ND.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: ND.aux,v 3.1 89/09/25 16:33:07 dick Exp $ X X# X# N o D i f f e r e n c e X# Script, to be included. X# X# Assumes set: X# $ACT X# $CVSLIB X# $Name X# $RCSBIN X# $Rcs X# $TS_User X# $User X# $VN_Rcs X# $VN_User X# X# The user file looks modified judging from its time stamp; however X# it needn't be. ND.aux finds out whether it is or not. X# If it is, it adds its name to the $MLIST. X# If it is not, it updates the administration. X# It may set OK to 'no'. X# X XTmp=,,$User Xif # we can retrieve a provisional copy of $Rcs X $RCSBIN/co -p -q -r$VN_User $Rcs >$Tmp Xthen # test for differences X if # they are equal X cmp -s $User $Tmp X then # there were no real user differences: X # update reference time stamp X TS_Rcs="$TS_User" X $ACT $CVSLIB/RG.aux $User $VN_Rcs "$TS_User" X else # its name belongs in the MLIST X MLIST="$MLIST $User" X fi X X rm -f $Tmp X Xelse # something very wrong X echo $Name: could not check out revision $VN_User of $User >&2 X rm $Tmp X OK=no Xfi X + END-OF-FILE ND.aux chmod 'u=rwx,g=rx,o=rx' 'ND.aux' set `wc -c 'ND.aux'` count=$1 case $count in 1086) :;; *) echo 'Bad character count in ''ND.aux' >&2 echo 'Count should be 1086' >&2 esac echo Extracting 'NR.aux' sed 's/^X//' > 'NR.aux' << '+ END-OF-FILE ''NR.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: NR.aux,v 3.1 89/09/25 16:33:29 dick Exp $ X X# X# N a m e o f R e p o s i t o r y X# Script, to be included. X# X# Assumes set: X# $Name X# $Repository (optionally) X# Sets: X# $Repository X# X# Determines the name of the RCS repository and sets $Repository X# accordingly. If $Repository is already set, then that is the name, X# otherwise the name is retrieved from CVS.adm/Repository. X# Checks the presence of the repository. X# X Xif [ "$Repository" = "" ] Xthen # retrieve CVS.adm/Repository X if # there is no administration directory X [ ! -d CVS.adm ] X then X echo $Name: there is no configuration under CVS here\; \ X do CV first >&2 X exit 1 X fi X X if # the necessary files are there X [ -r CVS.adm/Repository -a -r CVS.adm/Entries ] X then # read the name of the RCS repository from the file X Repository=`cat CVS.adm/Repository` X else # no good X echo $Name: \*PANIC\* administration files missing >&2 X exit 1 X fi Xfi X Xif # the promised repository isn't there X [ ! -d $Repository ] Xthen X echo $Name: there is no repository $Repository >&2 X exit 1 Xfi X Xexport Repository + END-OF-FILE NR.aux chmod 'u=rwx,g=rx,o=rx' 'NR.aux' set `wc -c 'NR.aux'` count=$1 case $count in 1195) :;; *) echo 'Bad character count in ''NR.aux' >&2 echo 'Count should be 1195' >&2 esac echo Extracting 'OP.aux' sed 's/^X//' > 'OP.aux' << '+ END-OF-FILE ''OP.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: OP.aux,v 3.1 89/09/25 16:33:40 dick Exp $ X X# X# O p t i o n s X# Script, to be included. X# X# Collects options from $@ and puts them in $Options. X# Each option, including the first, will be preceded by a space. X# X XGO_ON=true Xwhile # there may still be an option X $GO_ON Xdo X case $1 in X -*) X Options="$Options $1" X shift X ;; X *) X GO_ON=false X ;; X esac Xdone + END-OF-FILE OP.aux chmod 'u=rw,g=r,o=r' 'OP.aux' set `wc -c 'OP.aux'` count=$1 case $count in 485) :;; *) echo 'Bad character count in ''OP.aux' >&2 echo 'Count should be 485' >&2 esac echo Extracting 'RG.aux' sed 's/^X//' > 'RG.aux' << '+ END-OF-FILE ''RG.aux' X#!/bin/sh X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: RG.aux,v 3.1 89/09/25 16:34:19 dick Exp $ X X# X# R e g i s t e r X# Enters file $1 into the administration with version number $2 X# and time stamp $3. Removes the old entry first, if necessary. X# X# Assumes set: X# $CVSLIB X# X X$CVSLIB/SC.aux $1 # scratch the entry Xecho "$2|$3|" >>CVS.adm/Entries # and append a new one + END-OF-FILE RG.aux chmod 'u=rwx,g=rx,o=rx' 'RG.aux' set `wc -c 'RG.aux'` count=$1 case $count in 456) :;; *) echo 'Bad character count in ''RG.aux' >&2 echo 'Count should be 456' >&2 esac echo Extracting 'SC.aux' sed 's/^X//' > 'SC.aux' << '+ END-OF-FILE ''SC.aux' X#!/bin/sh X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: SC.aux,v 3.1 89/09/25 16:34:48 dick Exp $ X X# X# S c r a t c h X# Scratches file $1 from the administration X# X Xmv CVS.adm/Entries CVS.adm/Entries.Backup Xfgrep -v " $1|" CVS.adm/Entries.Backup >CVS.adm/Entries + END-OF-FILE SC.aux chmod 'u=rwx,g=rx,o=rx' 'SC.aux' set `wc -c 'SC.aux'` count=$1 case $count in 343) :;; *) echo 'Bad character count in ''SC.aux' >&2 echo 'Count should be 343' >&2 esac echo Extracting 'SL.aux' sed 's/^X//' > 'SL.aux' << '+ END-OF-FILE ''SL.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: SL.aux,v 3.1 89/09/25 16:34:58 dick Exp $ X X# X# S e t L o c k X# Script, to be included. X# X# Assumes set: X# $Name X# $Repository X# $LCK name of lock X# X# Persistently tries to make the directory $LCK, which serves as X# a lock. X# X Xuntil # we can enter the critical section X trap '' 1 2 3 15 # play deaf X mkdir $LCK >/dev/null 2>/dev/null Xdo X # we missed it this cycle X echo $Name: `date`: waiting for access to $Repository X X # sleep with both ears open X trap 'exit 1' 1 2 3 15 X sleep 60 Xdone + END-OF-FILE SL.aux chmod 'u=rw,g=r,o=r' 'SL.aux' set `wc -c 'SL.aux'` count=$1 case $count in 622) :;; *) echo 'Bad character count in ''SL.aux' >&2 echo 'Count should be 622' >&2 esac echo Extracting 'VN.aux' sed 's/^X//' > 'VN.aux' << '+ END-OF-FILE ''VN.aux' X#!/bin/sh X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: VN.aux,v 3.1 89/09/25 16:35:19 dick Exp $ X X# X# V e r s i o n N u m b e r X# Writes the version number of the most recent revision of $1 X# to standard output. X# This is sloppy, but the only way to do it, short of analyzing X# the *,v file itself. X# X# Assumes set: X# $RCSBIN X# X X( # The following stupid construction is necessary, since the X # shell sometimes generates a NL when a pipe breaks, as it X # does here, where sed stops after a few lines. Letting X # sed process all the rest is also a shame. X # X$RCSBIN/rlog $1 | Xsed -n ' X /^head:/{ X s/.* //p X q X } X' X) 2>/dev/null + END-OF-FILE VN.aux chmod 'u=rwx,g=rx,o=rx' 'VN.aux' set `wc -c 'VN.aux'` count=$1 case $count in 714) :;; *) echo 'Bad character count in ''VN.aux' >&2 echo 'Count should be 714' >&2 esac echo Extracting 'VT.aux' sed 's/^X//' > 'VT.aux' << '+ END-OF-FILE ''VT.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: VT.aux,v 3.1 89/09/25 16:35:27 dick Exp $ X X# X# V e r s i o n & T i m e S t a m p X# Script, to be included. X# X# Assumes set: X# $CVSLIB X# $Rcs X# $User X# X# Sets the following shell variables: X# VN_User version # of the RCS file the user file derives from X# may also be: X# empty: no entry for user file X# 0: user file is new X# -$VN_User: user file is to be removed X# VN_Rcs version # of active RCS file X# is empty for absent RCS file X# TS_User present time stamp of the user file X# is empty for absent user file X# TS_Rcs time stamp of the lastest check-out of the RCS file. X# X# The syntax of an entry is X# <version-number>|<time-stamp>| X# and since the time stamp is obtained through ls, it includes X# the file name. X# X XVN_Rcs=`$CVSLIB/VN.aux $Rcs` X Xif # the user file exists X [ -r $User ] Xthen #get its time stamp X TS_User=`ls -ld $User` Xelse # yield null X TS_User= Xfi X XENTRY=`fgrep " $User|" CVS.adm/Entries` Xif # the entry is non-empty X [ "$ENTRY" != "" ] Xthen # dissect it X VN_User=`expr "$ENTRY" : '\(.*\)|.' ` X TS_Rcs=`expr "$ENTRY" : '.*|\(.*\)|' ` Xelse # yield nulls X VN_User= X TS_Rcs= Xfi + END-OF-FILE VT.aux chmod 'u=rwx,g=rx,o=rx' 'VT.aux' set `wc -c 'VT.aux'` count=$1 case $count in 1253) :;; *) echo 'Bad character count in ''VT.aux' >&2 echo 'Count should be 1253' >&2 esac echo Extracting 'WL.aux' sed 's/^X//' > 'WL.aux' << '+ END-OF-FILE ''WL.aux' X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: WL.aux,v 3.2 89/10/13 12:04:40 dick Exp $ X X# X# W r i t e L o c k X# Script, to be included. X# X# Assumes set: X# $Repository X# $Name X# $CVSLIB X# $AutoRemove set to yes if lock is to be removed X# automatically upon script exit X# X# Sets a write lock in $Repository for exclusive write access X# X XLCK=$Repository/\#cvs.lock # the lock XTFL=$Repository/\#cvs.tfl.$$ # a temporary test file XRFL=$Repository/\#cvs.rfl # pattern of the read flags XWFL=$Repository/\#cvs.wfl # the general write flag X X# do we have write access at all? Xif # we can write at all X cp /dev/null $TFL >/dev/null 2>/dev/null Xthen # OK so far X rm $TFL Xelse # not so OK X echo $Name: you have no write permission in $Repository >&2 X exit 1 Xfi X X# set the lock itself X. $CVSLIB/SL.aux # persistently tries to mkdir $LCK X X# set trap to remove flag and lock on interrupt Xtrap 'rm -f $WFL; rmdir $LCK; exit 1' 1 2 3 15 X X# conditionally set trap to remove flag and lock on exit Xcase "$AutoRemove" in Xyes) # lock to be removed automatically upon exit X trap 'rm -f $WFL; rmdir $LCK; exit 0' 0 X ;; Xesac X X# start of critical section X X# notify others of intention Xcp /dev/null $WFL # plant write flag X X# wait for the readers to disappear Xwhile # there are still read flags X [ "`echo $RFL.* | grep -v '\*'`" != "" ] Xdo X echo $Name: `date`: waiting for readers to disappear from $Repository X sleep 60 Xdone X X# the caller of WL.aux can now write in safety X + END-OF-FILE WL.aux chmod 'u=rw,g=r,o=r' 'WL.aux' set `wc -c 'WL.aux'` count=$1 case $count in 1548) :;; *) echo 'Bad character count in ''WL.aux' >&2 echo 'Count should be 1548' >&2 esac echo Extracting 'historian' sed 's/^X//' > 'historian' << '+ END-OF-FILE ''historian' X#!/bin/sh X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: historian,v 3.1 89/09/25 16:36:25 dick Exp $ X X# X# Historian: ad-hoc configuration history reconstruction program X# X# historian [ repository ] X# attempts to reconstruct the configuration history file of the X# repository, using reasonable(?) heuristics. If no repository is given, X# the repository of the present directory is used. X# X# This simple script assumes that there are no "removed files", i.e., X# that the Attic is non-existent or empty. X# XName=historian; export Name X X# CVSBIN, CVSLIB and RCSBIN directories XCVSBIN=/home/top/dick/cvs XCVSLIB=/home/top/dick/cvs XRCSBIN=${RCSBIN-/usr/local/bin} Xexport CVSBIN CVSLIB RCSBIN X X# avoid spurious identifications XPATH=${CVSPATH-/bin:/usr/bin}; export PATH X X# determine the name of the repository XRepository=$1 X. $CVSLIB/NR.aux X X# worry about the Attic Xif # there is an Attic X [ -d $Repository/Attic ] Xthen # it may still be empty X REMOVED=`ls $Repository/Attic` Xfi X Xif # some files have been removed X [ -n "$REMOVED" ] Xthen # tell the truth X echo "The configuration history file reconstructed for $Repository" X echo "will not be completely correct, although it is still a good" X echo "approximation. Obtaining a correct configuration history file" X echo "requires manual assistance concerning the removal dates of" X echo "$REMOVED" | X sed 's/,v//' X echo "See the manual page of 'historian' for further information." X echo "" Xfi X X$CVSBIN/hist1 $Repository | X$CVSBIN/hist2 $Repository | Xsh X + END-OF-FILE historian chmod 'u=rwx,g=rx,o=rx' 'historian' set `wc -c 'historian'` count=$1 case $count in 1576) :;; *) echo 'Bad character count in ''historian' >&2 echo 'Count should be 1576' >&2 esac echo Extracting 'hist1' sed 's/^X//' > 'hist1' << '+ END-OF-FILE ''hist1' X#!/bin/sh X# This file is part of the Concurrent Versions System CVS. X# Written by Dick Grune, Vrije Universiteit, Amsterdam. X# $Header: hist1,v 3.2 89/10/13 11:54:39 dick Exp $ X X# X# Historian: ad-hoc configuration history reconstruction program, part 1 X# X# hist1 [ repository ] X# writes on standard output phase 1 of the reconstruction of the X# configuration history file of the repository, using reasonable(?) X# heuristics. If no repository is given, the repository of the present X# directory is used. X# XName=hist1; export Name X X# CVSBIN, CVSLIB and RCSBIN directories XCVSBIN=/home/top/dick/cvs XCVSLIB=/home/top/dick/cvs XRCSBIN=${RCSBIN-/usr/local/bin} Xexport CVSBIN CVSLIB RCSBIN X X# avoid spurious identifications XPATH=${CVSPATH-/bin:/usr/bin}; export PATH X X# determine the name of the repository XRepository=$1 X. $CVSLIB/NR.aux X X# get the whole rlog of all files XRCSFILES=` X ls $Repository/*,v $Repository/.*,v \ X $Repository/Attic/*,v $Repository/Attic/.*,v 2>/dev/null | X grep -v "\*" X` Xfor Rcs in $RCSFILES Xdo X $RCSBIN/rlog $Rcs Xdone | X X# remove all kinds of garbage Xtr '\200-\377' '' | X X# identify and combine revision and date lines Xsed ' X /^--*$/{ X N X s/\nrevision /\ X<REV> / X N X s/\ndate: / / X s/; *author:/ / X s/;.*// X } X /^==*$/s/.*/----------------------------/ X' | X X# construct one line for each file modification Xawk ' X $1 == "RCS" && running == 0 { X # establish file name X fname = $6; X } X $1 == "<REV>" { X # print date time fname rev author X printf("%s %s %s %s %s ; ", $3, $4, fname, $2, $5); X running = 1; X } X $1 ~ /^--*$/ && running != 0 { X # revision description terminator X printf("\n"); X } X $1 != "<REV>" && $1 !~ /^--*$/ && running != 0 { X # one line of revision description X if (running > 1) { X # multi-line revision message X printf("\\n"); X } X printf("%s", $0); X running++; X } X' | X X# sort on date and time Xsort -n | X X# put a separator after each group of identical messages Xawk -F\; ' X { if (msg != "" && $2 != msg) {print ""; } X msg = $2; X print; X } X END { X if (msg != "") {print ""; } X } X' X Xexit 0 X + END-OF-FILE hist1 chmod 'u=rwx,g=rx,o=rx' 'hist1' set `wc -c 'hist1'` count=$1 case $count in 2055) :;; *) echo 'Bad character count in ''hist1' >&2 echo 'Count should be 2055' >&2 esac exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.