These patches add support for tracking file death to rcs-5.6.6. These patches are a prerequisite for the remove/add patches to cvs. These patches add the following features to rcs. rcs can now record the fact that a file has "died". This is done with: co -l file ; ci -K file A dead revision is identical to it's immediate predecessor, except that the dead revision is flagged as dead. Checking out a dead revision results in a warning message, but no file. To recover the contents of a dead revision, use "co -l file", "co -f file", or "co -p file". You would do this if, for instance, you were considering resurrecting that file. "rcs -Krev file" will mark any arbitrary revision as dead. "rcs -Rrev file" will remove the death flag. Use these sparingly. They are intended as surgical tools for correcting scrambled rcs files. Merging a dead revision into a live revision results in a collision. Merging a live revision into a dead revision results in a live revision. Rationale: The current CVS support for adding and removing files is incomplete. There is a general feeling that what is needed in CVS is some way to record changes *about* a file, directory, module, and/or tree as distinct from changes to the contents of a file, directory, module, and/or tree. The general solution is currently being referred to as the "rename database". I needed to support some very specific features. Namely, adding files that had previously been removed and adding and removing files in branches AND merging those changes into the trunk. In order to add these features, I needed to record this information about a file. Again, this is information *about* a file as distinct from information about the *contents* of a file. Put another way, I needed a way to record information that was "out of band" with respect to the contents of a file. CVS had no place to record this information. RCS offered the potential for future expansion through the use of "newphrases" (cf. rcsfile(5)). These patches add a newphrase to the revision part of an rcs file. That new phrase is "dead". Since this is information *about* a file rather than information about a file's *contents*, this information is communicated to rcs via command line options rather than, say, being embedded in the contents of the file. This is not a *necessary* extension to RCS, simply a convenient one from the point of view of CVS. From a strictly RCS perspective, this extension is perhaps only somewhat useful. 12/02/92 K. Richard Pixley diff -r -p -u rcs-5.6.6/man/ci.1 rcs/man/ci.1 --- rcs-5.6.6/man/ci.1 Tue Nov 9 09:40:15 1993 +++ rcs/man/ci.1 Thu Nov 11 13:28:43 1993 @@ -476,6 +476,11 @@ is installation-dependent; normally it i for hosts like Unix that permit commas in filenames, and is empty (i.e. just the empty suffix) for other hosts. .TP +.BI \-K +commits a new, dead revision. In this case the working file must be +identical to the specified revision. See +.BR rcsintro (1) +for details. .BI \-z zone specifies the date output format in keyword substitution, and specifies the default time zone for diff -r -p -u rcs-5.6.6/man/co.1 rcs/man/co.1 --- rcs-5.6.6/man/co.1 Tue Nov 9 09:40:15 1993 +++ rcs/man/co.1 Thu Nov 11 13:30:01 1993 @@ -85,6 +85,14 @@ command applied to an \*r file with no revisions creates a zero-length working file. .B co always performs keyword substitution (see below). +.PP +If the specified revision is dead, (see also +.BR rcsintro (1) +), then by default, no working file is created. Specifying +.BR \-f, \-p, +or +.BR \-l +will retrieve the contents of the file at the time it died. .SH OPTIONS .TP .BR \-r [\f2rev\fP] diff -r -p -u rcs-5.6.6/man/rcs.1 rcs/man/rcs.1 --- rcs-5.6.6/man/rcs.1 Wed Nov 3 09:42:27 1993 +++ rcs/man/rcs.1 Thu Nov 11 13:32:22 1993 @@ -165,6 +165,28 @@ be used for files that are shared. Whether default locking is strict is determined by your system administrator, but it is normally strict. .TP +.BR \-K [\f2rev\fP] +Kill, that is, add the dead flag to, the revision with number +.IR rev . +If a branch is given, mark the latest revision on that branch. If +.I rev +is omitted, kill the latest revision on the default branch. Use this +option sparingly. It is intended as a tool for surgically correcting +scrambled \*r files. See also +.BR rcsintro (1) . +.TP +.BR \-R [\f2rev\fP] +Resurrect, that is, remove the dead flag from the revision with +number +.IR rev . +If a branch is given, resurrect the latest revision on that branch. +If +.I rev +is omitted, resurrect the latest revision on the default branch. Use this +option sparingly. It is intended as a tool for surgically correcting +scrambled \*r files. See also +.BR rcsintro (1) . +.TP \f3\-m\fP\f2rev\fP\f3:\fP\f2msg\fP Replace revision .IR rev 's diff -r -p -u rcs-5.6.6/man/rcsfile.5 rcs/man/rcsfile.5 --- rcs-5.6.6/man/rcsfile.5 Wed Nov 3 09:42:27 1993 +++ rcs/man/rcsfile.5 Thu Nov 11 13:32:23 1993 @@ -63,6 +63,7 @@ nonterminal symbols are in \f3state\fP {\f2id\fP}\f3;\fP \f3branches\fP {\f2num\fP}*\f3;\fP \f3next\fP {\f2num\fP}\f3;\fP + { \f3dead ; \fP} { \f2newphrase\fP }* .LP \f2desc\fP ::= \f3desc\fP \f2string\fP diff -r -p -u rcs-5.6.6/man/rcsintro.1 rcs/man/rcsintro.1 --- rcs-5.6.6/man/rcsintro.1 Wed Nov 3 09:42:27 1993 +++ rcs/man/rcsintro.1 Thu Nov 11 13:32:24 1993 @@ -56,6 +56,11 @@ The logging makes it easy to find out what happened to a module, without having to compare source listings or having to track down colleagues. .IP \(bu +Maintain a history of file existence. This history is used to +determine whether a file exists at any given point in time. Using +this information \*r can record additions, removals, and subsequent +additions of files to a particular set of files. +.IP \(bu Resolve access conflicts. When two or more programmers wish to modify the same revision, \*r alerts the programmers and prevents one modification from corrupting the other. @@ -283,6 +288,42 @@ There are several additional identificat .BR co (1) for details. +.SS "File Death" +\*r can record death information for a file. All files and revisions +are assumed to be +.BI alive +unless otherwise marked. Live files are treated as described. +.IP +A particular revision of a file may also be +.BI dead. +Death is simply a way of recording information +.BI about +a file as distinct from the +.BI contents +of the file. The particular piece of information that death +represents, is file existence. That is, a dead file is a file that +does not exist at this point in time. +.IP +For example, at some point in time I create a file, strcat.c and put +it under \*r control. My project evolves over time as does my file +and these changes are recorded by \*r. At a later point in time, I +find that I no longer need this file, so I check in a dead revision. +See +.BR ci (1) +for details. +.IP +Subsequent attempts to retrieve the latest revision of this file will +result in a warning message and no working file will be created. +Attempts to retrieve previous revisions, or attempts to recover the +state of the file as of a particular date will produce a working +file as expected. +.IP +At some even later point in time, I may find that I need that file +again. At this point I can check out the file and lock it as I would +any other file. This will produce a working file whose contents are +identical to the contents of the file before it died. I can then +examine and modify this file as I would any other file. A subsequent +check in will again produce a normal, live revision. .SH IDENTIFICATION Author: Walter F. Tichy. .br diff -r -p -u rcs-5.6.6/man/rcsmerge.1 rcs/man/rcsmerge.1 --- rcs-5.6.6/man/rcsmerge.1 Wed Nov 3 09:42:27 1993 +++ rcs/man/rcsmerge.1 Thu Nov 11 13:32:25 1993 @@ -36,6 +36,17 @@ prints a warning if there are overlaps, the overlapping regions as explained in .BR merge (1). The command is useful for incorporating changes into a checked-out revision. +.PP +Merging a live revision into a dead revision results in the live +revision. Merging a dead revision into a live revision results in a +collision which is marked in the resulting file with an initial line +of the form: +.LP +.RS +.nf +.BI <<<<<<< revision is dead >>>>>>> +.RE +.fi .SH OPTIONS .TP .B \-A diff -r -p -u rcs-5.6.6/man/rlog.1 rcs/man/rlog.1 --- rcs-5.6.6/man/rlog.1 Tue Nov 9 09:40:15 1993 +++ rcs/man/rlog.1 Thu Nov 11 13:32:37 1993 @@ -32,9 +32,9 @@ number of revisions selected for printin descriptive text. This is followed by entries for the selected revisions in reverse chronological order for each branch. For each revision, .B rlog -prints revision number, author, date/time, state, number of -lines added/deleted (with respect to the previous revision), -locker of the revision (if any), and log message. +prints revision number, the death flag if it exists, author, +date/time, state, number of lines added/deleted (with respect to the +previous revision), locker of the revision (if any), and log message. All times are displayed in Coordinated Universal Time (\*u) by default; this can be overridden with .BR \-z . diff -r -p -u rcs-5.6.6/src/ci.c rcs/src/ci.c --- rcs-5.6.6/src/ci.c Tue Nov 9 09:40:15 1993 +++ rcs/src/ci.c Thu Nov 11 13:43:18 1993 @@ -269,6 +269,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.27 1 int initflag, mustread; int lockflag, lockthis, mtimeflag, removedlock, Ttimeflag; int r; + int killing; int changedRCS, changework, dolog, newhead; int usestatdate; /* Use mod time of file for -d. */ mode_t newworkmode; /* mode for working file */ @@ -284,6 +285,7 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.27 1 altdate[0]= '\0'; /* empty alternate date for -d */ usestatdate=false; suffixes = X_DEFAULT; + killing = 0; nextassoc = &assoclst; argc = getRCSINIT(argc, argv, &newargv); @@ -404,6 +406,10 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.27 1 setRCSversion(*argv); break; + case 'K': + killing = 1; + break; + case 'z': zone_set(a); break; @@ -543,6 +549,9 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.27 1 } + if (killing) + newdelta.dead = 1; + if (lockflag && addlock(&newdelta, true) < 0) continue; if (keepflag && *prevname.string) @@ -590,13 +599,15 @@ mainProg(ciId, "ci", "$Id: ci.c,v 5.27 1 expname = buildrevision( gendeltas, targetdelta, (FILE*)0, false ); - if ( - !forceciflag && - strcmp(newdelta.state, targetdelta->state) == 0 && - (changework = rcsfcmp( - workptr, &workstat, expname, targetdelta - )) <= 0 - ) { + + changework = rcsfcmp(workptr, &workstat, expname, targetdelta); + if (killing && changework == 1) { + error("file has changed. will not kill."); + continue; + } else if (!forceciflag + && !killing + && strcmp(newdelta.state, targetdelta->state) == 0 + && changework <= 0) { diagnose("file is unchanged; reverting to previous revision %s\n", targetdelta->num ); diff -r -p -u rcs-5.6.6/src/co.c rcs/src/co.c --- rcs-5.6.6/src/co.c Tue Nov 9 09:40:15 1993 +++ rcs/src/co.c Thu Nov 11 13:44:44 1993 @@ -391,6 +391,25 @@ mainProg(coId, "co", "$Id: co.c,v 5.15 1 /* get numbers of deltas to be generated */ if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas))) continue; + + /* if the target delta is dead, we are not locking it, + and we are not sending it to stdout, then say so and go on. */ + if (targetdelta->dead + && lockflag != 1 + && !tostdout + && !join + && !forceflag) { + diagnose("revision %s is dead. (not checked out)\n", targetdelta->num); + + /* Prepare and remove old working file if necessary. */ + if (workstatstat == 0 + && rmworkfile()) { + un_link(workname); + } + + continue; + } + /* check reservations */ changelock = lockflag < 0 ? @@ -731,7 +750,13 @@ buildjoin(initialfile) int i; char const *cov[11], *mergev[12]; char const **p; + struct hshentry *delta; + if ((delta = genrevs(joinlist[lastjoin], 0, 0, 0, &gendeltas)) + == 0) { + error("no such revision: %s\n", joinlist[lastjoin]); + } + bufautobegin(&commarg); bufautobegin(&subs); rev2 = maketemp(0); @@ -786,7 +811,12 @@ buildjoin(initialfile) mergev[6] = joinlist[i+1]; p = &mergev[7]; if (quietflag) *p++ = quietarg; - if (lastjoin<=i+2 && workstdout) *p++ = "-p"; + if (lastjoin<=i+2 && workstdout) { + *p++ = "-p"; + if (delta->dead) { + aprintf(stdout, "<<<<<<< %s is dead >>>>>>>\n", joinlist[lastjoin]); + } + } *p++ = initialfile; *p++ = rev2; *p++ = rev3; @@ -797,7 +827,43 @@ buildjoin(initialfile) default: goto badmerge; } - i=i+2; + + if (lastjoin <= i + 2 && !workstdout && delta->dead) { + /* if final revision was dead, then prepend marker + saying so. */ + char const *tmpname; + RILE *in; + FILE *out; + struct stat status; + + tmpname = maketemp(4); + + if ((in = Iopen(initialfile, FOPEN_R_WORK, &status)) == 0) { + eerror(initialfile); + } + + if ((out = fopen(tmpname, FOPEN_W_WORK)) == 0) { + eerror(tmpname); + } + + fastcopy(in, out); + Izclose(&in); + Ozclose(&out); + + if ((in = Iopen(tmpname, FOPEN_R_WORK, &status)) == 0) { + eerror(initialfile); + } + + if ((out = fopen(initialfile, FOPEN_W_WORK)) == 0) { + eerror(tmpname); + } + + aprintf(out, "<<<<<<< %s is dead >>>>>>>\n", joinlist[lastjoin]); + fastcopy(in, out); + Izclose(&in); + Ozclose(&out); + } + i=i+2; } bufautoend(&commarg); bufautoend(&subs); Only in rcs/src: configure.in diff -r -p -u rcs-5.6.6/src/merger.c rcs/src/merger.c --- rcs-5.6.6/src/merger.c Wed Nov 3 09:42:27 1993 +++ rcs/src/merger.c Thu Nov 11 13:52:22 1993 @@ -70,10 +70,18 @@ merge(tostdout, edarg, label, argv) char const *a[3], *t; char *b[3]; int s; + struct hshentries *gendeltas; + struct hshentry *delta; + #if !DIFF3_BIN char const *d[2]; #endif + if ((delta = genrevs(label[1], 0, 0, 0, &gendeltas)) + == 0) { + error("no such revision: %s\n", label[1]); + } + for (i=3; 0<=--i; ) a[i] = normalize_arg(argv[i], &b[i]); @@ -88,6 +96,11 @@ merge(tostdout, edarg, label, argv) t = 0; if (!tostdout) t = maketemp(0); + else { + warn("overlaps during merge"); + aprintf(stdout, "<<<<<<< %s is dead >>>>>>>\n", label[1]); + } + s = run( (char*)0, t, DIFF3, edarg, "-am", "-L", label[0], @@ -111,6 +124,10 @@ merge(tostdout, edarg, label, argv) efaterror(argv[0]); if (!(rt = Iopen(t, FOPEN_R, (struct stat*)0))) efaterror(t); + if (delta->dead) { + warn("overlaps during merge"); + aprintf(f, "<<<<<<< %s is dead >>>>>>>\n", label[1]); + } fastcopy(rt, f); Ifclose(rt); Ofclose(f); diff -r -p -u rcs-5.6.6/src/rcs.c rcs/src/rcs.c --- rcs-5.6.6/src/rcs.c Tue Nov 9 09:40:15 1993 +++ rcs/src/rcs.c Thu Nov 11 13:52:24 1993 @@ -197,6 +197,12 @@ struct Symrev { struct Symrev * nextsym; }; +struct Deathrev { + char const *revno; + int kill; + struct Deathrev *nextrev; +}; + struct Message { char const *revno; struct cbuf message; @@ -227,12 +233,15 @@ static int buildeltatext P((struct hshen static int doaccess P((void)); static int doassoc P((void)); static int dolocks P((void)); +static int dodeaths P((void)); static int domessages P((void)); static int rcs_setstate P((char const*,char const*)); static int removerevs P((void)); static int sendmail P((char const*,char const*)); static int setlock P((char const*)); +static int setdeath P((char const *rev, int transition)); static struct Lockrev **rmnewlocklst P((char const*)); +static void rmdeathlst P((struct Deathrev const*)); static void buildtree P((void)); static void cleanup P((void)); static void getaccessor P((char*,enum changeaccess)); @@ -245,9 +254,10 @@ static void scanlogtext P((struct hshent static struct buf numrev; static char const *headstate; -static int chgheadstate, exitstatus, lockhead, unlockcaller; +static int chgheadstate, exitstatus, lockhead, unlockcaller, killhead; static int suppress_mail; static struct Lockrev *newlocklst, *rmvlocklst; +static struct Deathrev *deathlst; static struct Message *messagelst, **nextmessage; static struct Status *statelst, **nextstate; static struct Symrev *assoclst, **nextassoc; @@ -266,11 +276,13 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 5.1 int branchflag, changed, expmode, initflag; int strictlock, strict_selected, textflag; int keepRCStime, Ttimeflag; + int kill, resurrect; size_t commsymlen; struct buf branchnum; struct Lockrev *lockpt; struct Lockrev **curlock, **rmvlock; struct Status * curstate; + struct Deathrev *deaths = 0, *deathpt; nosetid(); @@ -284,11 +296,13 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 5.1 commsymlen = 0; curlock = &newlocklst; rmvlock = &rmvlocklst; + deathpt = 0; expmode = -1; suffixes = X_DEFAULT; initflag= textflag = false; strict_selected = 0; Ttimeflag = false; + kill = resurrect = 0; /* preprocessing command options */ argc = getRCSINIT(argc, argv, &newargv); @@ -451,6 +465,26 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 5.1 zone_set(a); break; + case 'K': + case 'R': + if (!*a) { + /* death transition for head or default branch. */ + killhead = a[-1]; + break; + } + deathpt = talloc(struct Deathrev); + deathpt->revno = a; + deathpt->kill = (a[-1] == 'K'); + deathpt->nextrev = 0; + if (deaths) + deaths->nextrev = deathpt; + else + deathlst = deathpt; + deaths = deathpt; + + rmdeathlst(deathpt); + break; + case 'k': /* set keyword expand mode */ if (0 <= expmode) redefined('k'); if (0 <= (expmode = str2expmode(a))) @@ -543,6 +577,8 @@ mainProg(rcsId, "rcs", "$Id: rcs.c,v 5.1 changed |= dolocks(); /* Update locks. */ + changed |= dodeaths(); + changed |= domessages(); /* Update log messages. */ /* update state attribution */ @@ -941,6 +977,39 @@ rmnewlocklst(which) return pre; } + static void +rmdeathlst(which) + struct Deathrev const *which; +/* Function: remove death transition to revision which->revno from deathlst if + which->kill doesn't match */ + +{ + struct Deathrev *pt, *pre; + + while (deathlst + && (!strcmp(deathlst->revno, which->revno)) + && (deathlst->kill != which->kill)) { + struct Deathrev *pn = deathlst->nextrev; + tfree(deathlst); + deathlst = pn; + } + + pt = pre = deathlst; + while(pt) { + if (!strcmp(pt->revno, which->revno) + && pt->kill != which->kill) { + pre->nextrev = pt->nextrev; + tfree(pt); + pt = pre->nextrev; + } + else { + pre = pt; + pt = pt->nextrev; + } + } + return; +} + static int @@ -1389,6 +1458,33 @@ dolocks() static int +dodeaths() +/* Function: make death transitions as listed in deathlst. + */ +{ + struct Deathrev const *deathpt; + int changed = false; + + for (deathpt = deathlst; deathpt; deathpt = deathpt->nextrev) + changed |= setdeath(deathpt->revno, deathpt->kill); + + if (killhead) { /* default branch or head */ + if (Dbranch) { + changed |= setdeath(Dbranch, killhead == 'K'); + } else if (Head) { + changed |= (Head->dead != (killhead == 'K')); + diagnose("%s %s\n", Head->num, + (killhead == 'K' ? "killed" : "resurrected")); + } else { + warn("can't lock an empty tree"); + } + } + return(changed); +} + + + + static int setlock(rev) char const *rev; /* Function: Given a revision or branch number, finds the corresponding @@ -1418,6 +1514,40 @@ setlock(rev) } return 0; } + + + static int +setdeath(rev, transition) + char const *rev; + int transition; +/* Function: Given a revision or branch number, finds the corresponding + * delta and sets the death state to transition. + */ +{ + struct hshentry *target; + int changed; + + if (expandsym(rev, &numrev)) { + target = genrevs(numrev.string, (char*)0, (char*)0, + (char*)0, &gendeltas); + if (target) { + if (!(countnumflds(numrev.string) & 1) + && cmpnum(target->num,numrev.string)) { + error("can't %s nonexisting revision %s", + transition ? "kill" : "resurrect", + numrev.string); + } else { + changed = (target->dead != transition); + target->dead = transition; + if (changed) + diagnose("%s %s\n", target->num, + transition ? "killed" : "resurrected"); + } + } + } + + return(changed); +} static int diff -r -p -u rcs-5.6.6/src/rcsbase.h rcs/src/rcsbase.h --- rcs-5.6.6/src/rcsbase.h Tue Nov 9 09:40:15 1993 +++ rcs/src/rcsbase.h Thu Nov 11 13:54:04 1993 @@ -332,6 +332,7 @@ struct hshentry { long insertlns;/* lines inserted (computed by rlog) */ long deletelns;/* lines deleted (computed by rlog) */ char selector; /* true if selected, false if deleted */ + char dead; /* true if file deleted, otherwise false */ }; /* list of hash entries */ diff -r -p -u rcs-5.6.6/src/rcsgen.c rcs/src/rcsgen.c --- rcs-5.6.6/src/rcsgen.c Wed Nov 3 09:42:27 1993 +++ rcs/src/rcsgen.c Thu Nov 11 13:54:08 1993 @@ -524,6 +524,9 @@ putdelta(node, fout) } aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:""); + if (node->dead) { + aprintf(fout, "dead;\n"); + } awrite(node->ig.string, node->ig.size, fout); } diff -r -p -u rcs-5.6.6/src/rcssyn.c rcs/src/rcssyn.c --- rcs-5.6.6/src/rcssyn.c Wed Nov 3 09:42:27 1993 +++ rcs/src/rcssyn.c Thu Nov 11 13:55:21 1993 @@ -156,6 +156,7 @@ char const Kbranch[] = "branch", Kcomment[] = "comment", Kdate[] = "date", + Kdead[] = "dead", Kdesc[] = "desc", Kexpand[] = "expand", Khead[] = "head", @@ -424,6 +425,14 @@ getdelta() getkey(Knext); Delta->next = num = getdnum(); getsemi(Knext); + + Delta->dead = 0; + if (nexttok == ID && !strcmp(Kdead,NextString)) { + getkey(Kdead); + getsemi(Kdead); + Delta->dead = 1; + } + Delta->lockedby = 0; Delta->log.string = 0; Delta->selector = true; diff -r -p -u rcs-5.6.6/src/rcstest rcs/src/rcstest --- rcs-5.6.6/src/rcstest Wed Nov 3 09:42:27 1993 +++ rcs/src/rcstest Thu Nov 11 13:57:00 1993 @@ -89,6 +89,21 @@ rcs -i -L -ta.11 $q a.c && } rlog a.c >/dev/null || { echo "#rlog failed on empty RCS file"; exit 1; } +echo live >a.c +ci $q -mm a.c || { echo "#ci failed to prep death test"; exit 1; } +co $q -l a.c || { echo "#co failed to prep death test"; exit 1; } +ci $q -K -mdying a.c || { echo "#ci failed to kill file"; exit 1; } +test -f a.c && { echo "#ci killing a file leaves the working file"; exit 1; } +co $q a.c || { echo "#co failed to check out dead file"; exit 1; } +test -f a.c && { echo "#co file exists after checking out dead revision"; exit 1; } +co $q -l a.c || { echo "#co failed to co & lock dead file"; exit 1; } +test -f a.c || { echo "#co working file missing after co+lock dead revision"; exit 1; } +echo zombie > a.c +ci $q -mresurrect a.c || { echo "#ci failed to resurrect dead file"; exit 1; } +co $q a.c || { echo "#co cannot check out resurrected file"; exit 1; } +test -f a.c || { echo "#co working file missing after co of resurrected file"; exit 1; } +rm -f a.c + rm -f $RCSfile || exit 2 cp a.11 a.c && diff -r -p -u rcs-5.6.6/src/rlog.c rcs/src/rlog.c --- rcs-5.6.6/src/rlog.c Tue Nov 9 09:40:15 1993 +++ rcs/src/rlog.c Thu Nov 11 13:57:02 1993 @@ -540,9 +540,10 @@ putadelta(node,editscript,trunk) return; out = stdout; - aprintf(out, - "----------------------------\nrevision %s", node->num - ); + aprintf(out, + "----------------------------\nrevision %s%s", + node->num, node->dead ? " (dead)" : "" + ); if ( node->lockedby ) aprintf(out, "\tlocked by: %s;", node->lockedby);