Updating SNOMAN under CVS Control

SNOMAN at Oxford is being placed under CVS control on PPLX3. This document gives a very brief primer sufficient to allow people to update code. Note, CVS access outside Oxford is not available

Contents


Tell me later: I don't have time right now!

If you need to make an update but don't have time to play about with CVS, this should work:-
  1. Send out a mail saying that sudbury and the Repository are closed.
  2. Login as sudbury on PPLX3.
  3. cd $SNO_ROOT/snoman/dev
  4. cvs update
    (this just ensures that the code is up to date with the Repository although it normally will as a cron job runs each night to do this).
  5. Make your changes.
  6. cvs commit -m"<brief comment>"
    e.g. cvs commit -m"Bug fix to FTT"
  7. Logout and send out a mail saying that sudbury and the Repository are open.

What is CVS?

CVS stands for Concurrent Versioning System. Its a tool that allows multiple people work on the code simultaneously without treading on each other's modifications. At any time you can get a copy of any or all of the code. This process is called checkout. You can modify it in any way you like. If you want to store them then this is done with the commit process. If nobody has changed the official code since you took a copy then this should work. however if someone else has changed anything CVS will tell you that you have to update your version first. Updating brings your code up to date with the official version. However CVS is smart enough to recognise changes you have made locally and attempts to merge in changes that others have made. If they have changed the same bit of code that you have, CVS considers this a conflict and records the conflict in your file in such a way that it won't compile so you have to fix it. Even if CVS is happy that there isn't a conflict it is still a good idea to check that their modifications don't logically conflict with yours. Once all conflicts have been resolved you can attempt to commit again and this time it should go through, unless further changes have taken place!

Some useful URLs:-

  1. CVS home page:-
    http://www.cvshome.org/
  2. A Tutorial on CVS:-
    http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/cvs/
  3. CVS Manual (Postscript):-
    http://wwwinfo.cern.ch/asd/cvs/cvs.ps

What is the Repository?

The Repository is the name for the set of directories that hold the source code. For every file the latest version is held in full but CVS also holds, as a series of compact editing instructions, the way to step back version by version, to the files's original form. CVS also records user comments submitted with each change so, at any time, you can see a complete history of changes and can extract any previous version of the file. You can also ask CVS to compare any two versions or to compare any version to the file you currently have.


Defining the Repository location (CVSROOT)

The simplest way to tell CVS the location of the Repository is to define the environmental variable CVSROOT in .cshrc or equivalent. For SNOMAN at Oxford:-

  setenv CVSROOT /snodisk1/sudbury/snoman/Repository
If you use other Repositories, then your probably don't need to be told that, on any CVS command, you can supply the Repository location using the -d option e.g.
  cvs -d /snodisk1/sudbury/snoman/Repository update
but in the sections that follow it will be assumed that CVSROOT is set appropriately.

A Simple Development Cycle

This first example shows how to get a copy of the code into a working directory, make changes, commit them and then erase the working directory.

Important! You must only checkout and commit changes from a linux machine. If you use an OSF machine i.e. Al1 or Al17 then the EXTRACT switch settings will be wrong.

  1. Get the code from the Repository (its called version dev) into your $SNO_ROOT/snoman directory.
      cd $SNO_ROOT/snoman
      cvs checkout dev
    
    CVS will respond by checking the dev directory and all subdirectories. It will look something like this:-
    cvs checkout: Updating dev
    cvs checkout: Updating dev/code
    U dev/code/absint.for
    U dev/code/annih.for
    U dev/code/ausgab.for
    ...
    
    It list each file pulls it out from the Repository preceeded by the letter U showing that this is an update i.e code coming from the Repository that doesn't need to be merged with any local changes.

  2. Edit the code as required.

  3. Commit the changes back into the Repository
      cd $SNO_ROOT/snoman/dev
      cvs commit
    
    CVS compares all the code in dev and its subdirectories looking for changes. In the first simple example we will assume that nobody else has made any changes contemporaneously so CVS should accept your changes. It places you in your favourite editor (or vi if you haven't defined the EDITOR environmental variable) ready to enter a summary of the changes. It shows you the files that the summary will cover. For example, if you edit snoman.for and inmain.for, the editor fires up looking like this:-
    
    CVS: ----------------------------------------------------------------------
    CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
    CVS: 
    CVS: Committing in dev/code
    CVS: 
    CVS: Modified Files:
    CVS: 	inmain.for snoman.for 
    CVS: ----------------------------------------------------------------------
    
    Enter a brief summary for the change. The Revision History entries in the individual files will still be used to describe changes at the file level, here the description should just be a broad brush summary for the entire collection of changes.

  4. Now you can erase your working code. This can be done with:-
      cd $SNO_ROOT/snoman
      rm -r dev
    
    but its better to let CVS erase it by:-
      cd $SNO_ROOT/snoman
      cvs remove -d dev
    
    because CVS takes one last look to make sure that you haven't forgotten to commit any code before it releases your working directory. The -d tells it to delete your directories, without this CVS would leave them but would not accept further commit requests.

Parallel Development

The above example is unrealistic in several respects:-

Updating Your Code

Having got a copy of the code you can work with it while the official version in the Repository moves on. When you are ready you can ask CVS to bring your code up to date:-
  cd $SNO_ROOT/snoman/dev
  cvs update -d 
Here the -d tells CVS that if any new directories have been added then they should be checked out into your work directory. CVS will attempt to update all changes and precedes each with a letter indicating what is has done. The most common are:-

Resolving Conflicts

If someone changes a file that you have also changed and they commit first then you must update before you can commit so that their change is incorporated into your version. Of course you might not realise that others are working on the same files you are but CVS does! If you attempt to commit any file that has since changed CVS reports:-
cvs commit: Up-to-date check failed for `file_name'
...
cvs [commit aborted]: correct above errors first!
This forces you to update code as described above and to fix conflicts.

Adding Files

Adding files is a two stage process. First you use the add command to tell CVS that you are changing the composition of the Repository, for example
  cvs add new_file1 new_file2 ...
You can issue as many add commands as you require and add files in any directory that CVS controls. At this stage the Repository hasn't been changed and you can remove any you have added with the add command e.g.:-
  cvs remove -f new_file2 ...
The -f tells CVS to delete the file from your local directory as well. When ready to update the repository you just use commit in the usual way:-
  cd $SNO_ROOT/snoman/dev
  cvs commit

Removing Files

Like adding files, removing is also a two stage process. First the remove command is invoked e.g.:-
  cvs remove old old_file1 old_file2 ...
The -f tells CVS to delete the file from your local directory as well. When ready to update the repository you just use commit in the usual way:-
  cd $SNO_ROOT/snoman/dev
  cvs commit

Getting a File's History

Whenever your current directory is one that is under CVS control you can use the log command to get a complete history of the changes (in CVS these are called revisions) that have been made to a specified file. For example:-
  cd $SNO_ROOT/snoman/dev/code
  cvs log snoman.for
produces output like this:-
RCS file: /snodisk1/sudbury/snoman/Repository/dev/code/snoman.for,v
Working file: snoman.for
head: 1.26
branch:
locks: strict
access list:
symbolic names:
        rel_4_0190: 1.25
...
        rel-1-03: 1.1
        rel_1_03: 1.1
comment leader: "c "
keyword substitution: kv
total revisions: 26;    selected revisions: 26
description:
----------------------------
revision 1.26
date: 2001/09/12 11:47:03;  author: west;  state: Exp;  lines: +9 -9
Updates 4.-190 -> 12 Sep 2001
----------------------------
...
----------------------------
revision 1.1
date: 2001/08/16 13:50:16;  author: sudbury;  state: Exp;
initial commit of 1_03
=============================================================================
This particular file can trace its ancestry back to release 1.03! Each change is given its own revision number starting at 1.1. In the case of this file, the latest revision number is 1.26.

There are also symbolic names which are like aliases for some revisions. For example rel_4_0190 is an alias for 1.25. Each time a release of SNOMAN is made a new symbolic name will be given to the current revision each file so that is possible to specify a revision by the release it was part of. There is no fixed relationship between symbolic names and revisions; code that is not changing could have the same revision for a whole range of symbolic names. On the other hand, code that is changing fast may be modified several times between releases in which case the intervening revisions will have no equivalent symbolic name.


Comparing File Revisions

Whenever your current directory is one that is under CVS control you can use the diff command to compare a specified file to the latest revision of its counterpart in the Repository. For example:-
  cd $SNO_ROOT/snoman/dev/code
  cvs diff snoman.for
You can use the -r<tag> option to compare the your file to a specific revision or symbolic name e.g.:-
  cvs diff -r1.22 snoman.for
or even:-
  cvs diff -rrel_4_0186 -rrel_4_00 snoman.for
to compare two revisions in the Repository.