User Tools

Site Tools


articles:cvs

CVS Notes

Server Repository Setup

A sensible access policy is to make users members of a group (Debian uses src), and make the CVS repository directory owner root.src, with the GUID bit set, so that CVS modules residing in that directory inherit the owner and permissions.

Also, it is easiest to set things up so that access is always by SSH, even when using the host machine. This provides good security by default.

User Environment Variables

For SSH access, the following environment variables avoid needing to specify the repository and access method each time:

CVSROOT=:ext:user@cvsserver.domain.com:/var/lib/cvs
CVS_RSH=ssh

/var/lib/cvs is the default repository directory for Debian.

Setting up a Separate CVS Lock Directory

It's preferable to set up a separate lock directory, to allow some users read-only access to modules.

cd /var/lock
mkdir cvs
chown root.src cvs
chmod 3775 cvs

Now edit CVSROOT/config:

cvs co CVSROOT
cd CVSROOT

Add/modify these lines:

# Put CVS lock files in this directory rather than directly in the repository.
LockDir=/var/lock/cvs

Then

cvs ci

Read Only Access to Certain Modules

Simply using standard permissions will allow this. So to allow user bill to commit changes to files in the QMS module, but all members of src to checkout the QMS for reading:

drwxr-sr-x  3 bill  src  4096 2008-10-13 16:28 QMS

Creating a New Module

cvs import can be used to bring an existing project under CVS control. If starting with an empty module, here are three ways to create the module:

mkdir empty-dir
cd empty-dir
cvs import new-module-name A B

or

cvs co -d top -l .
cd top
mkdir new_module_name
cvs add new-module-name

or directly, use the following script:

  #! /bin/bash
  # Make new module in CVS with correct permissions and attributes

  BASE="/var/lib/cvs"

  if [ -e "${BASE}/$1" ] ; then
  {
      echo "${BASE}/$1 already exists"
  }
  else
  {
      mkdir "${BASE}/$1"
      chown .src "${BASE}/$1"
      chmod 2775 "${BASE}/$1"
  }
  fi

Adding Directories

cvs add dirname
cvs add dirname/files

Adding Binary Files

cvs add -kb files

Creating a Branch

There are many ways of using (and naming) branches. Here's one way:

First tag the trunk at the branch point:

cvs tag Root-of-Validation_Tests

(Format uses hyphens for Root-of-, underscores for description).

Create branch with tag:

cvs tag -b Validation_Tests-branch

To work on the branch:

cvs up -r Validation_Tests-branch

Make changes then

cvs ci -m "Change description"

To work on the trunk:

cvs up -A

We can equally well check out our branch to a different directory:

mkdir branchdir
cd branchdir
cvs co -rValidation_Tests-branch

If you wish to branch from a non-tip point, initially check out the version from which to branch, e.g.

cvs up -rV01_01_02

Although there's a tag there, it's still a good idea to tag the root of the branch using the standard nomenclature.

Reverting and Merging from a Branch

By revert, we mean bring an earlier version of the codebase into the working directory (it requires a subsequent checkin to actually get the reverted files back into the repository at the current tip).

If working from the trunk, you can revert to a previous version with:

cvs up -jHEAD -jEarlier_Version_Tag

This reads as “Apply the differences between HEAD and Earlier_Version_Tag”.

If it's necessary to remove/abandon any unchecked-in local changes first, use the -C switch:

cvs up -C -jHEAD -jEarlier_Version_Tag

Due to inconsistencies in the definition of HEAD within CVS (see below), if working on a branch, revert with:

cvs up -C -jBranchname-branch -jEarlier_Version_Tag

To pull in changes from a branch tag, while working on the trunk, use

cvs up -jBranch_Tag

The single -j implies an omitted first -j which is the common ancestor of the trunk and branch development. It is possible to get into a real mess by only specifying a single -j, so it's probably a good idea to always use -j in pairs.

To merge changes from the trunk into a branch, use the same method:

cvs up -jTrunk_Tag

Again, it's safer to be specific, so:

cvs up -jRoot-of-Validation-Tests -jTrunk_Tag

Merging and Keyword Expansion

Don't use $Log$ keyword, as it makes it impossible to sensibly merge. Use $Id$ instead. Even then, conflicts will occur at that point when merging to or from a branch. Use -kk to disable keyword expansion during merging - e.g.

cvs up -kk -jBranchname-branch -jEarlier_Version_Tag
cvs ci -m"Change desciption"
cvs up -kkv

Note that it's necessary to check in the files before switching keyword expansion back on (-kkv), otherwise the cvs up -kkv is ignored. This appears to be a bug.

What is HEAD?

See http://lists.gnu.org/archive/html/info-cvs/2005-09/msg00170.html

Assuming tags have been used as above, this means that HEAD is the tip of the trunk for everything apart from cvs diff, where it is the tip of the current branch (I think).

CVS Log Reports

To restrict CVS log output to just those files that have been updated between releases, use:

cvs -Q log -SN -rV01_01_00::V01_02_00

To list change descriptions for a given release:

cvs -Q log -SN -rV01_01_00

Using Watches

Watches are useful for editing binary files (.doc etc). Straightforward locking (reserved checkouts) are not supported by CVS (there is a hack using a Perl script rcslock.pl, but the problem with that is that because this doesn't cause files to be checked out read-only, an unsuspecting user doesn't know a file was locked by another until he goes to check in).

Watch Setup

In CVSROOT/notify, ensure the following line is uncommented:

ALL (echo Committed to %r/%p; cat) |mail %s -s "CVS notification"

If any users have external email addresses, these need adding to the CVSROOT/users file. The format of each line in the users file is:

CVS_USERNAME:EMAIL_ADDRESS

However, the CVSROOT/users file does not exist in the stock CVS distribution. Because it's an administrative file, you must not only create, cvs add, and commit it in the usual way, but also add it to CVSROOT/checkoutlist so that a checked-out copy is always maintained in the repository:

# The "checkoutlist" file is used to support additional version controlled
# administrative files in $CVSROOT/CVSROOT, such as template files.
#
# The first entry on a line is a filename which will be checked out from
# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
# The remainder of the line is an error message to use if the file cannot
# be checked out.
#
# File format:
#
#       [<whitespace>]<filename>[<whitespace><error message>]<end-of-line>
#
# comment lines begin with '#'
users   Unable to check out 'users' file in CVSROOT.

Enabling Watches

Force subsequent checkouts to be read-only:

cvs watch on [files]

This step is not mandatory, but is the important one in preventing a user inadvertently wasting time on edits on a file that is already being edited.

Each user can then make themselves a watcher:

cvs watch add [files]

CVS will then send them emails as the status of files change.

Before editing files, a user should issue:

cvs edit [files]

This makes files writable. Note also that an editor becomes a temporary watcher.

When finished, a normal checkin releases the watch and changes the files back to read-only. Alternatively, if no changes where made, the user can issue:

cvs unedit [files]

To list watchers or editors:

cvs watchers
cvs editors
articles/cvs.txt · Last modified: 2009/02/12 15:38 by timallen