[cvsnt] Best practices for shadow repository
John J. Xenakis
mhare at jxenakis.com
Mon Dec 26 19:30:05 GMT 2005
I'm setting up CVSNT for a client, and I want it to behave
functionally as much like MS Visual SourceSafe as possible.
I think I've gotten everything working on a prototype basis, including
the shadow repository, but I'd like to share what I've done and ask if
I've followed "best practices."
I suspect that you have a lot of CVSNT users in the same boat as me,
and many of them may find this narrative interesting.
After much head-scratching I got past the restrictions on a
share-based repository, and I'm now fully on board with the wonders
>>> User Interface
There will be about 10-20 users working collaboratively on about 200
Microsoft Word DOC files. The users are all very familiar and
comfortable with the Windows user interface, but few are comfortable
with a command line interface. So I've been using command line CVS
commands to do everything, so that I can understand what's going on,
but the users will almost exclusively use a GUI.
I've tested both TortoiseCVS and WinCvs, and find that they both work
very nicely, individually and together. My plan is to instruct users
to install both of these and try both of them, and then tell them to
stick with whichever user interface each one prefers on a daily
>>> Exclusive edit locks
I want the restriction that only one person at a time can edit any
given file to be strictly enforced (even for text files). All the
documentation I've read is very disparaging of this model, often even
contemptuous, but it's still what's needed for this group on this
project. I hope I have this right (since it needs further testing),
but I've settled on the following to accomplish this for a given new
cvs co Project
cvs watch on
TortoiseCVS then seems to handle the locking and unlocking properly,
so I'm hoping this is the right way / best way / correct way to do
>>> Using POSTCOMMAND triggers
I guess the easiest way to maintain a shadow repository is the
following, which I've tried and found to work:
(*) Add a trigger to the postcommand file to call a Perl program
(*) Have the Perl program see if the shadow repository already
exists, and do either "cvs co" or "cvs update" in the respective
cases (does not exist versus exists).
I guess this is OK, but I'm concerned about performance problems
when the project gets larger. Doing an update of the entire project
whenever anyone does a "commit" seems likely to be very time
consuming, and will be noticeable if someone uses TortoiseCVS to
commit a series of files, one at a time.
So I wanted to do something more sophisticated that would get around
the potential performance issues, but I was thwarted at every turn.
I wanted to modify the Perl program so that it would only update the
shadow repository files that had been actually committed, rather than
the entire project. (There might be some additional logic that would
update the entire shadow repository once an hour, "just in case.")
I wanted to have as much information as possible available to the
Perl program, so I added this line to the POSTCOMMAND file:
ALL perl cvsup.pl cm=%c tm=%d ho=%h~%H us=%u rp=%r~%R fl=%s dr=%p
However, I discovered that I get an error message on "%s" in the
POSTCOMMAND file, so that had to be removed.
That still left one hope: Using "%p", update just that one
sub-directory in the shadow repository. But it turns out that the
supplied directory may or may not be related to the files being
Next, I tried POSTCOMMIT triggers, hoping that I would get one
postcommit trigger for each file committed. The official CVSNT
documentation (cvs.pdf) says that there's a POSTCOMMIT trigger, but
there was no such file in CVSROOT. I added the file to CVSROOT, but
it turns out that it works the same as POSTCOMMAND. So that was a
dead end too.
So, unless I'm missing something, there's basically only one way to
update a shadow repository: Implement a trigger and issue "cvs
update" for the entire project.
Is this in fact correct? Am I overly concerned about performance
issues as the number of files and directories increases?
>>> Using COMMITINFO triggers
There's one more idea I'm thinking of trying. I've found out that
"%s" is OK with commitinfo triggers, so the algorithm would be this:
(*) When COMMITINFO is triggered by the user, save all the directory
and file information for the files being committed in a file.
(*) When POSTCOMMIT is triggered by the same user, the saved
information is retrieved, and selective commits are performed in
the shadow directory.
Will this work? Will it solve the performance issues? Is it OK?
>>> Shadow repository on a share
I'm fairly certain that at some point the client is going to ask me
to move the shadow repository to a shared disk. I understand that
this idea is treated with disdain and contempt by the CVSNT community,
but I believe that the client is going to request this.
I understand that I'll have to program "net use" to do this, and that
there'll have to be a password in plain text.
Can anyone suggest a "best practices" way of doing this? I'm
thinking of a separate userid and password just for the shadow
repository, so that if it's discovered, the exposure will be limited
to just the shadow repository.
>>> A suggestion ...
I suspect that the problem of dealing with shared disks is going to
become a much greater issue with many more of CVSNT's users.
The reason is that you can now walk into an office supplies store and
purchase a 200 GB disk drive that plugs into your network as a shared
disk. My client is already using these for other purposes, but I can
well imagine that there'll be an increasingly widespread desire to
put CVS repositories on shared disks.
I'm mentioning this only to suggest that it might be worthwhile to
figure out a way to make it easier to use shares with CVSNT.
John J. Xenakis
Xenakis Consulting Services Inc.
44 Dinsmore Ave #304
Framingham, MA 01702
E-mail: john at jxenakis.com
More information about the cvsnt