Maintaining and Synchronizing Local CVS Repository

by Reid Spencer

This information may have been posted previously, but its new to me so I thought I might put it out there in case it is useful to anyone else intending to add to or modify ACE/TAO/JACE.

CAVEAT1: this isn't for the weak of heart. If you aren't doing serious development on ACE (as opposed to just using ACE), you can probably skip this ... onward.

CAVEAT2: this is NOT for ACE developers at WUSTL. If you do any of this, you run this risk of botching up the master repository. If you're going to try this, make SURE your $CVSROOT does NOT point at the master repository on tango!

Okay, you've been warned ..

I have figured out how to (reasonably reliably!) synchronize my own CVS Repository with the repository at Washington University. This permits me the flexibility of doing "local" commits on a branch that will not be reflected in the WUSTL repository. This is far more effective than simply mirroring the master repository because cvsup can keep my branch changes will at the same time bringing in changes from the master repository. It is also much more effective than simply downloading a new checked out workspace with cvsup since I have the full power of CVS at my hands. I can work independently on modifications to ACE and only submit them as a batch when I'm sure they compile and work. This really helps to parallelize the work!

To make it all happen, there are three essential steps:

  1. Utilize an ace-supfile with cvsup that copies the RCS files in the CVS repository (rather than the checked out versions of those files).

  2. Utilize a "hacked" version of CVS that supports CVS_LOCAL_BRANCH_NUM environment variable.
    Note: this hack is small, and it has been working at for some time now.

  3. Understand what the hell you're doing with all this.

Here are the details:
  1. Utilize ace-supfile

    CVSup has two (subtle!) features that support updating a repository rather than a work space. First, by leaving out the "tag=." specification you tell cvsup to obtain the RCS files (those funny ones with the ,v in them) in the repository rather than a checked-out copy of the tag ".".

    Note: because you're taking a copy of the RCS files, you are essentially copying EVERYTHING that EVER happened to ACE (all versions, and all deadwood (Attic files)). The result is (currently) about 320MB of disk space that you must provide for your local ACE repository. Fortunately, I just bought a new 13GB drive. Note that a workspace from the head of just the source code is only about 75MB. You should probably allow at least 500MB of space for future additions (you ARE doing this to make changes to ACE, right?).

    The second feature is to not delete any files or any revisions in RCS files. You should read the caveat about this in the CVSup FAQ (that's step one below). Basically, you are instructing cvsup not to delete anything in the target repository. That means that deleted files will remain where they are, even if they were deleted from the ACE master repository. This can have some consequences but the impact is generally limited because,

    It appears point c) applies to the CVS master repository.

    The benefit of not having any deletions done is that the revisions you check into your local repository will REMAIN! If you include the "delete" option in your ace-supfile then anything you committed to your local repository would be removed the next time you ran cvsup. That is obviously counter-productive.

  2. Utilize "hacked" CVS

    For exactly the same reason as used here, has modified their version of CVS to support the environment variable CVS_LOCAL_BRANCH_NUM. This essentially defeats CVS's branch number selection algorithm and always uses the integer value provided in CVS_LOCAL_BRANCH_NUM. The "hack" affects exactly one function, about 10 lines of code. Its works for FreeBSD and it works for me. Perhaps one day someone will actually put it into CVS.

    Why would we want to do this, you ask? Well, we have to avoid using branch numbers that might conflict with those in the master CVS repository. The whole goal here is to allow our local CVS repository to be updated once in a while from the master while you work on a branch. If the branch numbers conflicted, then CVSup might delete or overwrite the versions checked in on your branch! That, obviously, isn't good. So, by forcing CVS to use a specific (and rather large) value for the branch number, you can be pretty much guaranteed that you won't get a branch number conflict.

  3. Understand what's going on

    1. we're using CVSup to COPY the RCS files from the ACE master CVS repository (at WUSTL) to our local CVS repository.

    2. CVSup will MERGE changes into the RCS file, rather than just overwrite them (yes, its that smart).

    3. we will work on a branch in our local repository that doesn't conflict with branch numbers in the CVS repository.

    4. the above allows us to check in revisions that don't conflict with other development changes.

    5. when we're ready to send the changes back to WUSTL, we can use CVS to merge all the changes made since the branch was taken back into our work area. Hopefully there won't be too many conflicts.

    6. we're using some "on the fringe" features of cvsup (no delete option) and CVS (CVS_LOCAL_BRANCH_NUM hack).

So, if after all the foregoing, you are still interested, here's how ..


Here are the steps I took to get all this working. I offer this in the hope it might be useful. It is unapologetically UNIX based. Adapt it accordingly to your own platform.

  1. Read the CVSup FAQ CAREFULLY.

  2. Get CVSup from

  3. Create your local CVS Repository:

    	export CVSROOT=/cvsrep     # Or wherever
    	cvs init
  4. Put the ace-repo-supfile (attached) in your $CVSROOT directory.

  5. Modify the ace-supfile to contain a setting of base=$CVSROOT. That is, change the line that reads *default base=/cvsrep so that /cvsrep is replaced by the full path to your CVS Repository (i.e. the value of $CVSROOT).

  6. Modify the ace-supfile to contain a setting of prefix=$CVSROOT/ACE_wrappers. Same comment for base= applies here too. This is where the CVSup will write the ACE repository to. I recommend you leave it at $CVSROOT/ACE_wrappers (after the appropriate substitution for $CVSROOT) unless you have very special needs.

  7. Now, go get the ACE Repository from WUSTL. Issue the commands:

    	cd $CVSROOT
    	cvsup -g -L 2 ace-repo-supfile
  8. The initial download of the repository will take some time, while we're waiting, we'll get a copy of CVS 1.10 and modify it to support CVS_LOCAL_BRANCH_NUM.

  9. Get the source code for CVS 1.10 from

  10. Decompress the file somewhere and go to the resulting directory with:

    	gzcat cvs-1.10.tar.gz | tar xvf -
    	cd cvs-1.10
  11. In the CVS src directory, modify the rcs.c file to include support for CVS_LOCAL_BRANCH_NUM. This step entails adding and modifying just a few lines in one function. The diff output for the change is in rcs.c.diff.

  12. Read the INSTALL file to find out how to build CVS. Basically, you just run configure and then run make. It was that easy with gcc 2.95.2 and Linux 2.2.

  13. (OPTIONAL) Run make install if you want to try installing it on your system. This will most likely require root access and you might not want to go modifying /usr/bin/cvs anyway.

  14. Okay, the ACE CVS Repository should be finished downloading by now, so lets create a tag for the branch on which our work will be done. First, you need to pick a unique branch number that is unlikely to conflict with a branch number that will occur in the ACE master repository. I suggest using a good high number. This branch number will only be found in your repository, so we don't have to worry about conflicts on branch numbers. These branches will never make it back into the master repository. However, if you pick a branch number that is too low, an update from the master repository might wipe out your branch! I suggest using a good high number. I chose 65536 based on today's e-mail discussion on the maximum value that an unsigned short could hold (really!). I subscribe to Doug's point of view, even if it is off by one. (:o) (actually, the value has to be even so the "correct" value (65535) wouldn't work).

  15. Next, you'll need to pick a branch name. This can be anything but again shouldn't be chosen so as to conflict with any branch's in the ACE CVS repository already (or in the future). I'd include your name. I chose Reid_Branch.

  16. Okay, finally we can create the branch. Use commands like:

    	export CVS_LOCAL_BRANCH_NUM=65534
    	cvs rtag -b My_Branch_Name ACE_wrappers

    Note: if you screw up and issue the cvs rtag command with the WRONG version of cvs (the one that doesn't support CVS_LOCAL_BRANCH_NUM, it is easy enough to fix. Just do this:

    	/path/to/hacked/cvs rtag -F -b My_Branch_Name ACE_wrappers
  17. Now, we're almost done. All we have to do is checkout the branch to our work space with something like:

    	cd /my/build/area
    	cvs checkout -rMy_Branch_Name ACE_wrappers

    Note that this will cause the HEAD revision to be checked out but will set a "sticky" tag that will cause a branch on commit. Do a cvs status some_file and look at the output. You'll see a sticky tag setting with a revision number containing an even number of dots. The last value will contain the value of $CVS_LOCAL_BRANCH_NUM. If it doesn't, you used the wrong version of cvs .. go back to previous step.

  18. HACK AWAY!

  19. Your build area is now set up to commit to the branch you named on the rtag command (My_Branch_Name in the example). You can commit all you want in this work space and your changes will safely go on the branch. You just:

    	cd /my/build/area
    	cvs commit
  20. Now, to merge changes coming from the master repository into your work space, all you have to do is run cvsup again to sync your local repository, and then issue the following cvs command:

    	cvs update -j HEAD

    This will merge all the changes from the head into your branch. This way, if there are any conflicts, you can find out about them before you commit. Make sure you compile and test again!

  21. Now that you've got all the changes merge and compiled and tested, its time to send the changes back to WUSTL. As I haven't done this yet, I'll leave it to the reader as an exercise. However, I imagine it will involve the following command:

    	cvs rdiff -u -r My_Branch_Name ACE_wrappers
  22. Here's the files you'll need:

Home Nanbor Wang, <nanbor at cse wustl edu>
Last modified 16:08:38 CDT Sep 20 2001