Building the Glasgow Functional Programming Tools Suite
Prev |  | Next

# 2. Using the CVS repository

We use CVS (Concurrent Version System) to keep track of our sources for various software projects. CVS lets several people work on the same software at the same time, allowing changes to be checked in incrementally.

This section is a set of guidelines for how to use our CVS repository, and will probably evolve in time. The main thing to remember is that most mistakes can be undone, but if there's anything you're not sure about feel free to bug the local CVS meister (namely Jeff Lewis `<jlewis@galconn.com>`).

## 2.1. Getting access to the CVS Repository

You can access the repository in one of two ways: read-only (Section 2.1.1), or read-write (Section 2.1.2).

### 2.1.1. Remote Read-only CVS Access

Read-only access is available to anyone - there's no need to ask us first. With read-only CVS access you can do anything except commit changes to the repository. You can make changes to your local tree, and still use CVS's merge facility to keep your tree up to date, and you can generate patches using 'cvs diff' in order to send to us for inclusion.

To get read-only access to the repository:

1. Make sure that cvs is installed on your machine.

2. Set your `$CVSROOT` environment variable to `:pserver:anoncvs@glass.cse.ogi.edu:/cvs`

3. Run the command

           $ cvs login

   The password is simply `cvs`. This sets up a file in your home directory called `.cvspass`, which squirrels away the dummy password, so you only need to do this step once.

4. Now go to Section 2.2.

### 2.1.2. Remote Read-Write CVS Access

We generally supply read-write access to folk doing serious development on some part of the source tree, when going through us would be a pain. If you're developing some feature, or think you have the time and inclination to fix bugs in our sources, feel free to ask for read-write access. There is a certain amount of responsibility that goes with commit privileges; we are more likely to grant you access if you've demonstrated your competence by sending us patches via mail in the past.

To get remote read-write CVS access, you need to do the following steps.

1. Make sure that `cvs` and `ssh` are both installed on your machine.

2. Generate a DSA private-key/public-key pair, thus:

            $ ssh-keygen -d

   (`ssh-keygen` comes with `ssh`.) Running `ssh-keygen -d` creates the private and public keys in `$HOME/.ssh/id_dsa` and `$HOME/.ssh/id_dsa.pub` respectively (assuming you accept the standard defaults).

   `ssh-keygen -d` will only work if you have Version 2 `ssh` installed; it will fail harmlessly otherwise. If you only have Version 1 you can instead generate an RSA key pair using plain

           $ ssh-keygen

   Doing so creates the private and public RSA keys in `$HOME/.ssh/identity` and `$HOME/.ssh/identity.pub` respectively.

   [Deprecated.] Incidentally, you can force a Version 2 `ssh` to use the Version 1 protocol by creating `$HOME/config` with the following in it:

          BatchMode Yes

          Host cvs.haskell.org
          Protocol 1

   In both cases, `ssh-keygen` will ask for a passphrase. The passphrase is a password that protects your private key. In response to the 'Enter passphrase' question, you can either:

   - [Recommended.] Enter a passphrase, which you will quote each time you use CVS. `ssh-agent` makes this entirely un-tiresome.

   - [Deprecated.] Just hit return (i.e. use an empty passphrase); then you won't need to quote the passphrase when using CVS. The downside is that anyone who can see into your `.ssh` directory, and thereby get your private key, can mess up the repository. So you must keep the `.ssh` directory with draconian no-access permissions.

   Windows users: see the notes in Section 12.3 about ssh wrinkles!

3. Send a message to to the CVS repository administrator (currently Jeff Lewis `<jeff@galconn.com>`), containing:

   - Your desired user-name.

   - Your `.ssh/id_dsa.pub` (or `.ssh/identity.pub`).

   He will set up your account.

4. Set the following environment variables:

   - `$HOME`: points to your home directory. This is where CVS will look for its `.cvsrc` file.

   - `$CVS_RSH` to `ssh`

     [Windows users.] Setting your `CVS_RSH` to `ssh` assumes that your CVS client understands how to execute shell script ("#!"s,really), which is what `ssh` is. This may not be the case on Win32 platforms, so in that case set `CVS_RSH` to `ssh1`.

   - `$CVSROOT` to `:ext:``your-username` `@cvs.haskell.org:/home/cvs/root` where `your-username` is your user name on `cvs.haskell.org`.

     The `CVSROOT` environment variable will be recorded in the checked-out tree, so you don't need to set this every time.

   - `$CVSEDITOR`: `bin/gnuclient.exe` if you want to use an Emacs buffer for typing in those long commit messages.

   - `$SHELL`: To use bash as the shell in Emacs, you need to set this to point to `bash.exe`.

5. Put the following in `$HOME/.cvsrc`:

       	  checkout -P
       	  release -d
       	  update -P
       	  diff -u

   These are the default options for the specified CVS commands, and represent better defaults than the usual ones. (Feel free to change them.)

   [Windows users.] Filenames starting with `.` were illegal in the 8.3 DOS filesystem, but that restriction should have been lifted by now (i.e., you're using VFAT or later filesystems.) If you're still having problems creating it, don't worry; `.cvsrc` is entirely optional.

[Experts.] Once your account is set up, you can get access from other machines without bothering Jeff, thus:

1. Generate a public/private key pair on the new machine.

2. Use ssh to log in to `cvs.haskell.org`, from your old machine.

3. Add the public key for the new machine to the file `$HOME/ssh/authorized_keys` on `cvs.haskell.org`. (`authorized_keys2`, I think, for Version 2 protocol.)

4. Make sure that the new version of `authorized_keys` still has 600 file permissions.

## 2.2. Checking Out a Source Tree

- Make sure you set your `CVSROOT` environment variable according to either of the remote methods above. The Approved Way to check out a source tree is as follows:

          $ cvs checkout fpconfig

  At this point you have a new directory called `fptools` which contains the basic stuff for the fptools suite, including the configuration files and some other junk.

  [Windows users.] The following messages appear to be harmless:

      setsockopt IPTOS_LOWDELAY: Invalid argument
      setsockopt IPTOS_THROUGHPUT: Invalid argument

  You can call the fptools directory whatever you like, CVS won't mind:

          $ mv fptools directory

  NB: after you've read the CVS manual you might be tempted to try

          $ cvs checkout -d directory fpconfig

  instead of checking out `fpconfig` and then renaming it. But this doesn't work, and will result in checking out the entire repository instead of just the `fpconfig` bit.

          $ cd directory
          $ cvs checkout ghc hslibs libraries

  The second command here checks out the relevant modules you want to work on. For a GHC build, for instance, you need at least the `ghc`, `hslibs` and `libraries` modules (for a full list of the projects available, see Section 3).

  Remember that if you do not have `happy` and/or `Alex` installed, you need to check them out as well.

## 2.3. Committing Changes

This is only if you have read-write access to the repository. For anoncvs users, CVS will issue a "read-only repository" error if you try to commit changes.

- Build the software, if necessary. Unless you're just working on documentation, you'll probably want to build the software in order to test any changes you make.

- Make changes. Preferably small ones first.

- Test them. You can see exactly what changes you've made by using the `cvs diff` command:

      $ cvs diff

  lists all the changes (using the `diff` command) in and below the current directory. In emacs, `C-c C-v =` runs `cvs diff` on the current buffer and shows you the results.

- If you changed something in the `fptools/libraries` subdirectories, also run `make html` to check if the documentation can be generated successfully, too.

- Before checking in a change, you need to update your source tree:

      $ cd fptools
      $ cvs update

  This pulls in any changes that other people have made, and merges them with yours. If there are any conflicts, CVS will tell you, and you'll have to resolve them before you can check your changes in. The documentation describes what to do in the event of a conflict.

  It's not always necessary to do a full cvs update before checking in a change, since CVS will always tell you if you try to check in a file that someone else has changed. However, you should still update at regular intervals to avoid making changes that don't work in conjuction with changes that someone else made. Keeping an eye on what goes by on the mailing list can help here.

- When you're happy that your change isn't going to break anything, check it in. For a one-file change:

      $ cvs commit filename

  CVS will then pop up an editor for you to enter a "commit message", this is just a short description of what your change does, and will be kept in the history of the file.

  If you're using emacs, simply load up the file into a buffer and type `C-x C-q`, and emacs will prompt for a commit message and then check in the file for you.

  For a multiple-file change, things are a bit trickier. There are several ways to do this, but this is the way I find easiest. First type the commit message into a temporary file. Then either

      $ cvs commit -F commit-message file_1 .... file_n

  or, if nothing else has changed in this part of the source tree,

      $ cvs commit -F commit-message directory

  where `directory` is a common parent directory for all your changes, and `commit-message` is the name of the file containing the commit message.

  Shortly afterwards, you'll get some mail from the relevant mailing list saying which files changed, and giving the commit message. For a multiple-file change, you should still get only one message.

## 2.4. Updating Your Source Tree

It can be tempting to cvs update just part of a source tree to bring in some changes that someone else has made, or before committing your own changes. This is NOT RECOMMENDED! Quite often changes in one part of the tree are dependent on changes in another part of the tree (the `mk/*.mk` files are a good example where problems crop up quite often). Having an inconsistent tree is a major cause of headaches.

So, to avoid a lot of hassle, follow this recipe for updating your tree:

    $ cd fptools
    $ cvs update -P 2>&1 | tee log

Look at the log file, and fix any conflicts (denoted by a "C" in the first column). New directories may have appeared in the repository; CVS doesn't check these out by default, so to get new directories you have to explicitly do

    $ cvs update -d

in each project subdirectory. Don't do this at the top level, because then all the projects will be checked out.

If you're using multiple build trees, then for every build tree you have pointing at this source tree, you need to update the links in case any new files have appeared:

    $ cd build-tree
    $ lndir source-tree

Some files might have been removed, so you need to remove the links pointing to these non-existent files:

    $ find . -xtype l -exec rm '{}' \;

To be really safe, you should do

    $ gmake all

from the top-level, to update the dependencies and build any changed files.

## 2.5. GHC Tag Policy

If you want to check out a particular version of GHC, you'll need to know how we tag versions in the repository. The policy (as of 4.04) is:

- The tree is branched before every major release. The branch tag is `ghc-x-xx-branch`, where `x-xx` is the version number of the release with the `'.'` replaced by a `'-'`. For example, the 4.04 release lives on `ghc-4-04-branch`.

- The release itself is tagged with `ghc-x-xx` (on the branch). eg. 4.06 is called `ghc-4-06`.

- We didn't always follow these guidelines, so to see what tags there are for previous versions, do `cvs log` on a file that's been around for a while (like `fptools/ghc/README`).

So, to check out a fresh GHC 4.06 tree you would do:

         $ cvs co -r ghc-4-06 fpconfig
         $ cd fptools
         $ cvs co -r ghc-4-06 ghc hslibs

## 2.6. General Hints

- As a general rule: commit changes in small units, preferably addressing one issue or implementing a single feature. Provide a descriptive log message so that the repository records exactly which changes were required to implement a given feature/fix a bug. I've found this very useful in the past for finding out when a particular bug was introduced: you can just wind back the CVS tree until the bug disappears.

- Keep the sources at least *buildable* at any given time. No doubt bugs will creep in, but it's quite easy to ensure that any change made at least leaves the tree in a buildable state. We do nightly builds of GHC to keep an eye on what things work/don't work each day and how we're doing in relation to previous verions. This idea is truely wrecked if the compiler won't build in the first place!

- To check out extra bits into an already-checked-out tree, use the following procedure. Suppose you have a checked-out fptools tree containing just ghc, and you want to add nofib to it:

      $ cd fptools
      $ cvs checkout nofib

  or:

      $ cd fptools
      $ cvs update -d nofib

  (the -d flag tells update to create a new directory). If you just want part of the nofib suite, you can do

      $ cd fptools
      $ cvs checkout nofib/spectral

  This works because `nofib` is a module in its own right, and spectral is a subdirectory of the nofib module. The path argument to checkout must always start with a module name. There's no equivalent form of this command using `update`.

Prev | Home | Next
Building the Glasgow Functional Programming Tools Suite |  | What projects are there?