[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: The hated $Log$ keyword
Greg A. Woods
Re: The hated $Log$ keyword
Mon, 9 Jul 2001 04:12:30 -0400 (EDT)
[ On Monday, July 9, 2001 at 00:01:01 (-0400), Eric Siegerman wrote: ]
> Subject: Re: The hated $Log$ keyword
> > and that they contain their markers
> > when they appear in a "frozen" file.
> Why is this a problem? I very much prefer it. Suppose, using
> SCCS or raw RCS, I accidentally edit a file I haven't locked.
> With RCS, once I've seen the "permission denied" message, I can:
> :!co -l foo
> The SCCS equivalent would inappropriately freeze all my keywords.
> OK, that's a really dumb thing to do when collaborating with
> others. But then, I've rarely collaborated using raw RCS, and
> never with SCCS; by the time I had coworkers who were willing to
> consider version control at all, I'd discovered CVS :-)
Well, with CVS the meaning of "frozen" file is quite a bit different.
In the most basic sense what I'm saying is that "-kv" should be the
default for "cvs export".
In a pure RCS environment the issue with keyword markers in unlocked
files is somewhat more complex. If I'm not mis-remembering the history
of this feature part of the original intent was to allow for exactly the
scenario you describe above. Another "feature" of this ability was to
allow a new RCS ,v file to be created with initial defaults for various
values, such as the revision number (i.e. with "ci -k"):
This option is useful for
software distribution. A revision that is sent to
several sites should be checked in with the -k
option at these sites to preserve the original num-
ber, date, author, and state.
In practice I don't think this scheme has ever worked very well unless
all sites in question had an agreed upon branching plan since you still
have to either reserve branch numbers for each site (or invent some tool
to do branch renumbering, which is I think what BitKeeper does).
Of course in both CVS and RCS the ultimate problem with having the
keyword markers in the frozen files is that subsequent checkins/imports
to a new repository (without '-k') will clobber the old value. This is
why '-kv' should be the default for "cvs export", and why large projects
using RCS (or those using CVS who haven't learned to use "cvs export")
have always invented their own project-specific keyword (eg. $NetBSD,
$Xconsortium, $XFree86, etc.)
(Which reminds me -- someone with commit access really should commit the
patches from OpenBSD that implement "tag=OpenBSD" in CVSROOT/config!)
BTW, with plain SCCS the "workaround" for saving changes to unlocked
files is to save only the diff and apply it again to the locked file:
sccs diff foo.c > foo.diff
sccs edit foo.c
patch foo.c < foo.diff # no patch? use 'diff -e' and 'ed'
sccs delget foo.c
> I don't see how one could even do CVS-style unreserved checkouts
> layered on top of something which handled its keywords the way
> SCCS does. Should a checkout give you the values (in which case,
> the magic-keyword-ness is lost on commit), or the keywords (in
> which case, why bother with keywords in the first place since
> they never get substituted)?
In order to follow the SCCS style of keyword handling CVS would have to
always provide only the un-expanded keywords in working directories
(i.e. use "co -kk" in the case of RCS, or always create the working
directory with "get -k" in the case of SCCS). At least this was the
conclusion I came to when I was trying to figure out how to make CVS
work as an SCCS front-end.
Yes this would significantly reduce the utility of keywords, at least
for the way many people use them today.
However in many environments such a scheme would be more or less
invisble (eg. in emacs with the VC hooks enabled the checked out
revision is given in the mode line).
One advantage of such a scheme would be that people who wanted to use
keywords to tag all their published files would soon learn when and how
to use "cvs export" and they'd be much less likely to accidentally
publish something from within a working directory! ;-)
> I'm trying to think of how one could get this to work. You'd
> have to do some kludge like:
> - check out with values only into the user's sandbox (actually,
> SCCS itself gives you no choice, if I recall, since the only
> way to get keywords only is "get -e", which also acquires a
No need to do the lock with SCCS, just use "get -k"....
> - at commit time, do a merge between:
> 1. a fresh checkout with values only
> 2. another fresh checkout with keywords only
> 3. the sandbox file
> i.e. diff (1) and (2) and apply the results to (3) as a patch
I'm not sure where you're going there.....
Normally in a working directory you'd only ever see the unexpanded
keywords (since a concurrent editing system can't predict which file(s)
might be edited).
At commit time a CVS-like front-end to SCCS would just do something
delta file.c # delta normally removes the g-file
get -k file.c
You'd only ever see the expanded keywords with "cvs export" (and of
course '-kv' wouldn't be necessary since that's the only way SCCS
Somewhere I have notes on other issues in making CVS work as a front-end
to SCCS, but I don't know where they are now. The most difficult issues
are not with how to do concurrency and keywords, but rather with how to
do lazy branching and tagging.
One approach to the tagging problem was successfully implemented by
tccs, but I don't know if anyone's done a lazy branching scheme for
plain SCCS (BitKeeper does its lines of development stuff with
branching, and I think it has some form of symbolic naming too, but I
think it makes use of some semi-proprietary extensions to the SCCS
Originally I leaned strongly towards avoiding the lazy branching issue
and simply following strict SCCS-style branching schemes. It would make
branch creation a much more intensive and highly visible process though
as a branch with a null delta would have to actually be created in every
file. However if there's a way to sneak tag names into the SCCS file
format it would probably still make more sense to simply reserve
branches by adding a symbolic name with a magic branch number (you need
the "magic" part to distinguish a branch tag from a release tag), just
as CVS does with RCS files now. That way only files changed on the
branch would have a "B.S" part to their SIDs.
You still end up having to follow SCCS branching rules though, and you
still only have R.L.B.S format SIDs with one level of branching.....
Back when I used only SCCS I used a manual lazy branching technique to
track changes I made to third party code. Unfortunately without a
CVS-like front end it was "hard" to find all the branched files and to
create a complete patch file for all the local changes. The normal SCCS
tools I had access to then really wanted the branch to actually be
present in all files. (Actually I was really lazy and only ever even
entered files into SCCS that I was actually going to modify! ;-)
Which of course is another issue with designing a CVS-like front-end for
SCCS. If you want to handle
I never wrote an "import" script though to add a new vendor release to
the trunk (I just re-created my repo with every new release). If I had
I could also have written a merge script to pull my branch changes up to
merge with the new vendor release. That concept raised another issue
though -- with the current RCS-based "cvs import" we have new revisions
on the vendor branch only when there's a delta to a given file. With
SCCS, especially without tags, you really do have to add null deltas to
all files lest you mix up your branches when you go to edit a file
previously un-touched locally. I.e. if you've edited some file you'll
have 1.1 as the original vendor version and 1.1.1.X as your local
revision. If you don't create 1.2 when importing on an un-modified
vendor file then you'll end up with 1.1.1.Y as the revision for a patch
to the second vendor release but you won't be able to tell which vendor
release it's for (or more importantly you'll no longer be able to
recreate the patch to the first vendor release as now this newly
modified file will appear to be a patch for the first release). If you
do create an empty 1.2 though then you'll have 1.2.1.X as the revision
for the patch to the second vendor release.
So, I guess for at least the handling of third-party code a CVS-like
front-end to SCCS could even do without tags, and could use lazy
branching, just so long as imports of new vendor releases always create
new revisions on the "trunk", even if they're null deltas.
Multiple un-related patches to third-party code are also far easier to
handle with a scheme like this that imports to the trunk too since you
need only create new branch numbers for each. Eg. 1.2.1.X would be one
patch branch, 1.2.2.X another, and so on. You can even easily merge all
these separate branches onto an integration branch, making it easy to
create and manage separate change sets for submission back to the
vendor. Meanwhile managing separate normal branches in a
vendor-branched CVS module is very much a nightmare and doesn't work
well at all.
This vendor-import-to-the trunk scheme could be implemented with CVS.
You'd need some indicator, such as a special state (and subsequently a
special new "dead" state), to indicate that the file is in a module
that's managing third-party code. This indicator would take the place
of the current trick of using the default branch and would tell CVS to
create the local delta revision on a branch. Optional tagging of
additional branches would facilitate the management of multiple
independent local patches, with perhaps the '.1' branch reserved as the
master default local branch (which could be used for making automation
of integration of many such branches much easier). Integration support
like this would scream out for automation of leap-frog tags for partial
merge mangement too.
Blue-sky dreaming for CVS, I think, but maybe for an SCCS front end....
> Now that you mention it, I seem to recall wishing for the same
> thing (not quite a decade ago), but never got around to griping
> about it. Maybe I should have :-)
I still really really really want a $Module keyword, but not enough to
implement it, at least at the moment! ;-)
Greg A. Woods
+1 416 218-0098 VE3TCP <address@hidden> <address@hidden>
Planix, Inc. <address@hidden>; Secrets of the Weird <address@hidden>