Node:Traditional, Next:, Previous:WSAD, Up:Top



Using CVS with a traditional CVS client

I give instructions on how to accomplish these tasks using the command-line interface to CVS. If you use some graphical CVS tool, it is up to you to figure out if and how to accomplish the same CVS operations using your tool.

SSH

Make sure to export the env variable CVS_RSH and set it to the value ssh. This tells CVS to use ssh instead of rsh to communicate with the CVS server host. Besides encryption (which I don't think we need), ssh allows us to authenticate in a secure manner without having to type in a password each time (this is not possible in a secure manner with rsh).

If you don't enjoy entering your password time after time after time, then set up your ssh keys so that you can ssh into your CVS reposiroty host without supplying a password. If that works, the commands in this section and the My CVS Scripts section should not prompt you for a password.

If you get error messages about ssh and libraries, check if you have a crazy setting for LD_LIBRARY_PATH. In most cases, the only thing you should have in your LD_LIBRARY_PATH is $ORACLE_HOME/lib. (The Iplanet build environment files are known to do nasty things to the LD_LIBRARY_PATH).

The Bare Basics

If you are going to be using CVS at the command-line, memorize these idioms:

cvs -H command
Gives a syntax message for use of the command cvs... command....
cvs -help-commands
Lists all of the available cvs commands (i.e., cvs... X...).
cvs -help-commands
Lists all global options (i.e., options that you put after cvs but before the command).

If you are familiar with RCS, be aware that, unlike RCS, CVS switches that take arguments usually require whitespace (i.e., an additional argument) after the switch itself (see the use of the -m switch a few lines down). Exceptions to this rule are the -k and -r switches, which usually work better for CVS without whitespace.

Commands that every developer must know.

cvs -n -q update
lists all changes made both up in the repository and in your local files, since your local files were last synchronized. I give -q with almost all CVS commands because the default behavior of nearly all CVS commands is too verbose for my taste. If you have derived files in your local area, there are several methods to filter them out. This is best explained at http://www.linuxselfhelp.com/gnu/cvs/html_chapter/cvs_21.html#SEC148.
cvs -q update
means download changes FROM repository. Note that this is exactly the same as the previous command without the global -n switch (which means to Not modify any files).
cvs -q commit -m 'my comment' resource...
means upload changes TO repository. You should always run an update command (see immediately above) before committing changes. I always use the -m switch to supply a comment when committing because otherwise I would be confronted with an editor session just to type in a 1 or 2 line comment. You use the -r switch to specify a tag, but you should generally not use cvs... commit -r with a static tag, but only with branch tags (as explained latter in this section). If you use no -r switch, the commit defaults to the HEAD branch (unless you checked out or previously updated with another tag... but that's also covered latter in this section).

Repository Root

Be aware that the CVS commands need to know where the repository root is. This is accomplished in a few different ways. Most cvs commands use a file in the CVS subdirectory of the current directory to find the location. The checkout and Remote commands (like rtag and rlog) will use the same method as above if you have a CVS subdirectory, otherwise you must use the -d switch or the CVSROOT env variable. (Beware that the precedences explained in the CVS documentation are not what I observe in practice). (My CVS scripts (explained in a section below) which do remote CVS commands use the env variable SCRIPT_CVSROOT.)

Tags

Tags are completely analogous to PVCS labels.

Do not use

     cvs... commit... -r TAGNAME...
     
to check in file(s) and apply a static (non-floating) tag TAGNAME to the checked-in version. That works ok for floating tags (branches), but otherwise, TAGNAME must be an existing tag, and the data you check in will assume that revision- i.e. it will not move the tag to a different version. (Note that HEAD is a floating tag, and the default behavior, if you give no -r switch, is to make a new revision and apply HEAD to that revision). If you want to check in something to head and apply a label to it, then just do that. Check it in to head (with no -r switch), then use "cvs tag" or "cvs rtag" to apply the desired tag to it. (Of course, if you want to tag a file in some other branch, then use the -r switch to commit to that branch, then run a tag command on that branch).

Example checking in a file and a directory branch, and tagging these resources.

         cvs commit -m 'fixed a bug' file.txt subdir
         cvs tag TAGNAME file.txt subdir
     

Module Alias Conventions

Many of the remote CVS commands take CVS module name(s) as argument(s). Often, we want to apply some command to all of the modules for a specific development project. Most critically, when working with tags, we need a way to specify the target resources more reliably (and easier) than typing in long lists of CVS modules and depended-upon jar files. We use module aliases to achieve this goal. In this section, I use the phrase traditional module to mean the normal CVS modules which have a physical directory branch rooted in the CVS repository directory, as opposed to a module alias.

Note that module aliases are named so because after a module alias is defined, it is used in remote CVS commands exactly as if it were a traditional module, but the contents of a module alias are not necessarily a module or modules. Module aliases often are a short-hand for just one (or more) artifact file(s) (artifact files = normal files under CVS control).

At any time, you can see the list of all the usable module aliases by catting the file CVSROOT/modules under the CVS repository on the repository host.

Since it is extremely important for users to understand exactly which resources are encompassed by a given module alias, we use the following naming convention to differentiate between the different types of aliases that we use.

Justification (skip this paragraph unless you want to know how we decided on these conventions). The normal convention for CVS is to use all-caps for tag names. Since we do not want to be confusing tag names with module aliases, we use lower-case for module aliases. We use the hypen and dot characters, with specific suffixes, to indicate the type of module alias. We do not use slashes because we don't want our aliases to look like paths (you can often append a path to a module specification, so that would get really ugly). Since we do not use dots in traditional module names, we decided to use the dot-specifier to differentiate an alias for a specific file. That is intuitive since if you ran a diror ls and saw a node with a dot, you would assume that it is a file. Since our traditional modules all contain the hyphen character, we use the hyphen character for aliases which contain modules. To differentiate module aliases from traditional module names, we use the specific suffixes -ali and -all, which can never collide with our base CVS modules (which are all named x-ear, x-ejb, x-web, x-java and x-jop).

all-all
This is one module alias with the constant name given. It is equivalent to every traditional module in the repository. You could use this, for example, if you needed to check out all resources with tag TAGX, but didn't know for sure all of the modules which have TAGX. The checkout will be inefficient because every file in every traditional module will be checked for the tag, but you will be sure to achieve your goal.


*-ali
This is equivalent to a set of traditional modules. There should be an alias of this form for every application, and for each group of non-application traditional modules. For example, there should be an emt-ali and a storeshared-ali. emt-ali contains the modules emt-ear, emt-ejb, emt-web, emt-jop.


*-all
This is equivalent to all of the resources needed to build a particular application. An -all alias typically is defined to contain the main application -ali alias, plus other depended-upon -ali's, plus any external file resources neede to build the app. emt-ali contains emt-ali and storeshared-ali and coreEJB.jar


*.*
These are just aliases to an indidual file in a module. These are defined to make it easier to specify (and remember) depended-upon binary jar files that live in projects that we don't develop in. For example, coreEJB.jar is an alias for core-ejb/bin/coreEJB.jar.

See the Server-side CVS Administration section for instructions on how to add module aliases.

Use of Module Aliases

You could definitely do everything using only traditional module names, and skip module aliases altogether. I'll give an example to show why you probably do want to use module aliases.

A common task is to update a tag to the HEAD. Our example is to update the tag 'ATAG' for the EMT application. You need to make sure that every single artifact needed by your appliation build gets updated. If you depend upon coreEJB.jar, for example-- even though coreEJB.jar is not in any of your development modules, you still need to tag it so that the build procedure knows which version to check out when you do your UNIX build (which is why we say that it is depended upon).

Using traditional module names, the update command looks like this

         cvs -d /cvs/cvsrepos -q rtag -F -a ATAG aisleCore-ejb catalog-ejb  \
          core-ejb/bin/coreEJB.jar coreFrameWork-jar corePresentation-jar  \
          emt-ear emt-ejb emt-jar emt-web ratePlan-ejb storeAccount-ejb emt-jop
     
Using module aliases, the update command looks like this
         cvs -d /cvs/cvsrepos -q rtag -F -a ATAG emt-all
     

Creating and Updating Tags

You create a new tag like this.

       cvs -d /cvs/cvsrepos -q rtag NEWTAG emt-all
     
You update a tag like this.
         cvs -d /cvs/cvsrepos -q rtag -F -a EXISTINGTAG emt-all
     
You have to use the -F and -a switches to update tags. See the man page if you want to know why.

Binary files

When committing adds of binary files, you must flag them as binary so that the files don't get corrupted when transferring them between different OSes. The -kb option to commit (or to cvs admin) flags a file as binary. Example.

         cvs commit -kb -m 'A new jar file' file.jar
     
You don't have to worry about this from Eclipse or WSAD, since the plugin sets the flag based on the filename extension.

Sticky tags

Many CVS commands that use the -r switch are sticky. I.e., once you use that command, future CVS commands in that directory (or upon that file, etc.) will use that tag specification by default. For example, if you run cvs co -r TAGX modulename, then any future "updates" done within the checkedout "modulename" branch will apply to tag TAGX.

You need to understand this because when cvs.tag* property(s) are set in env.properties (the UNIX build environment file), the "co" target will checkout with the specified tags, and will therefore set sticky tags.

You can always view the sticky tags for a resource by using the "cvs... status" command. As explained elsewhere in this document, you should not attempt to commit changes using a static (non-floating) tag. Therefore, if you use the build script to check out your modules and later wish to commit changes you make to that source, you will need to clear the stick tag with cvs -q update -A (if you wish to apply a non-HEAD branch, you'll also have to specify the branch tag).