home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

  Previous section   Next section

7.1 Creating a Project

A project is any group of files and directories that exist beneath one project root directory. Every project must include at least one directory, because CVS needs to be able to create a subdirectory to store metadata about the project.

Most often, a project represents one program, one set of related configuration files, or one web site. Sometimes, a project is a collection of related items. For instance, I store all my articles for http://www.oreillynet.com/ in one project, with each topic grouped under a subdirectory. Sometimes a project is a subsection of something larger.

If you want to create a project right now with default settings and minimal reading, read Section 2.3 in Chapter 2. That section walks you through the process of importing a project.

7.1.1 Preparing a Project

To create a project in CVS, you need to have a copy of the files and directories you want to import, or an idea of which files and directories you want to make. You may modify this copy of the project, so make a copy in a temporary directory to use for importing.

If you have an existing set of files and directories, check whether you have files that can be generated from other files, such as compiled code. Files that can be generated easily do not usually need to be stored in CVS and can be removed from the copy of the project. It is good practice to store the commands that generate these files in CVS as part of the project, usually as a build script or as part of the installation document.

If you have a set of files stored in another version control system and want to save their revision history, see Section 7.1.5 in this chapter. If you don't need to retain their revision history, export the files from the other system using a command that gives you a clean copy of the project with no administrative files, and use that copy to import from.

If you don't have any existing files, you can import a single directory with the project name. If you are more comfortable with a structure to work from, create an initial directory structure for your project and import that.

If you cannot easily fit the task you are trying to accomplish into a single project, you can use the modules feature of CVS to give each development team a smaller section to work from, or you can create several projects and use a module to combine projects into a larger unit when needed. Modules are explained in Section 7.3.3 and Section 7.6.3.

Once you have at least one directory ready to add to the repository, you need to decide how you will add it. There are two methods, which are explained in Section 7.1.2 and Section 7.1.4.

7.1.2 Importing a Project

The cvs import command is used for both creating a new project and updating the vendor branch. Vendor branches are explained in Section 7.1.3 of this chapter.

To create a new project, make your initial directory structure and place in it the initial files for your project, or set out your existing code that is ready for importing, as described in Section 7.1.1. Run the cvs import command from within the root directory of that structure. CVS takes the files and directories from the initial directory structure and copies them into the repository. The syntax for cvs import is:

cvs [cvs-options] import [command-options] project_name vendor_tag release_tag

cvs import requires a log message and calls an editor if it is not invoked with the -m option. You'll then be able to type a message into the editor to record the purpose of the import. See Chapter 2 for more information about the log message.

Check out a sandbox to test whether the import command has worked. If the files are in the sandbox correctly, you can remove or store the original files or directories as you see fit; CVS no longer needs them. cvs import doesn't change the files it imported from, and doesn't convert them into a sandbox.

Example 7-1 shows how to import a project and create an initial project sandbox. The ellipsis indicates where CVS calls the editor so you can enter a log message. Note that I change directories before checking out the test sandbox.

Example 7-1. Importing with cvs import
bash-2.05a$ cvs -d cvs:/var/lib/cvs import wizzard wizzard ver_1-0
"/tmp/cvsfaQoRz" 5L, 287C written
N wizzard/Makefile
N wizzard/README
N wizzard/TODO
No conflicts created by this import
bash-2.05a$ cd ~/cvs
bash-2.05a$ cvs -d cvs:/var/lib/cvs checkout wizzard     
cvs server: Updating wizzard

cvs import saves the data from the files to both the project trunk and to the special branch known as the vendor branch. Unless specified otherwise with -b, the vendor branch is given the ID 1.1.1. The vendor tag parameter is used for the branch tag, and the release tag tags the branch at the current (just-imported) revision. These tags can consist of only alphanumeric characters, hyphens, and underscores.

If you need to import binary files or other files that are not plain text, see the information on binary files in Chapter 3 before adding them to the repository.

The cvs import command honors cvsignore and cvswrappers files and recognizes the standard -k, -I, and -W options (also used by cvs checkout and cvs update) explained in Chapter 3 and Chapter 10. The -d option causes CVS to record the time of import based on a file's last modification time, rather than the current time.

Like cvs update, cvs import reports on the status of files it adds to the repository. These are the output codes for cvs import:

C file

The file already exists in the repository and has been modified locally. A conflict must be resolved.

This code is usually seen when a project is reimported (see Section 7.1.3).

I file

The file has matched a cvsignore pattern and has been ignored.

L file

The file is a symbolic link and has been ignored.

N file

The file is new and has been added to the repository.

U file

The file already exists in the repository and has not been locally modified. A new revision has been created.

This code is usually seen when a project is reimported (see Section 7.1.3).

7.1.3 Vendor Branches

A vendor branch is a special type of branch that CVS creates automatically when you cvs import a project. If your project is based on code external to the project itself, such as in-house patches to a vendor's code base, the vendor branch provides a way to merge updates from the external source with your own code.

If you intend to use vendor branches, use cvs import to create your project in CVS, using the vendor's code as the initial directory for the project. Make your changes on the main trunk and run the project normally; the vendor branch is used only when the vendor releases a new set of code.

When the vendor provides a new release, use the cvs import command to add the new code to the same CVS project with the same vendor tag and a new release tag. In effect, this is a special cvs commit to the vendor branch.

Example 7-2 shows a vendor-branch import to the wizzard project. Note the new release tag. The project name and vendor tag remain the same as in Example 7-1.

Example 7-2. Importing a vendor branch
bash-2.05a$ cvs -d cvs:/var/lib/cvs import wizzard wizzard ver_2-0
C wizzard/TODOf" 5L, 270C written
C wizzard/README
C wizzard/Makefile
C wizzard/INSTALL
C wizzard/doc/design/Specification.rtf
C wizzard/doc/design/Requirements.doc
C wizzard/doc/design/Design.rtf
C wizzard/doc/design/Analysis.rtf
C wizzard/doc/design/AcceptanceTest.doc
17 conflicts created by this import.
Use the following command to help the merge:
     cvs -d cvs:/var/lib/cvs checkout -j<prev_rel_tag> -jver_2-0 wizzard

If a file is changed on the vendor branch and the local file has not changed, CVS sets the trunk revision of the file to the new vendor-branch revision.

If both the vendor-branch copy and the local copy of a file have changes, CVS reports this as a conflict with the message N conflicts created by this import, where N is the number of conflicts. CVS also provides a suggested variant of cvs checkout to help you resolve all the conflicts, using two -j command options to merge the vendor branch with the trunk.

CVS 1.11.5 tries to provide the exact cvs checkout command you can use to find the differences between the previous release and the current release of the vendor branch and merge those differences to the trunk. If your version doesn't do this, try the following command:

cvs checkout -j previous_release_tag -j current_release_tag projectname

You may also need to include the -d repository_path CVS option if you run this command from outside the sandbox, where CVS can't find the repository path in the sandbox administrative files.

Section 4.3.6 of Chapter 4 explains how the -j option works and how to resolve any conflicts that arise from this type of merge. Tag the vendor branch once these conflicts have been resolved, and use that tag as the previous_release_tag when you next merge changes from a vendor branch.

If the vendor branch contains binary files or files with keywords, use the keyword (-k) and wrappers (-W) command options to cvs import. Keywords and wrappers are discussed in Chapter 3.

If you have more than one external source for a project, you can use the -b command option to run cvs import on an arbitrary branch number. This creates an additional vendor branch with the specified branch number. Create a separate vendor branch for each separate code source for your project, to help you keep track of which changes came from which vendor.

When selecting a branch to use as a new vendor branch for a new code source, determine that there is no preexisting branch with the number you choose. When updating an existing vendor branch (other than the default branch), use the -b option with the numeric ID of the branch, to specify the target branch for the current import.

Be careful when using -b, as CVS doesn't check whether the branch number corresponds to the vendor tag given in the import command. You can accidentally overwrite one vendor branch with another branch's files.

7.1.4 Alternatives to Importing

If your project does not contain files provided outside the project, it is unlikely you will need to use vendor branches. If this is the case, you can bypass cvs import. To do so, create a new project by adding a new subdirectory to the repository root directory, either by editing the repository directly or by checking out the repository root directory and then using cvs add in that sandbox.

If you do not need the vendor-branch capability of cvs import, the choice between cvs import and the combination of cvs checkout and cvs add is a matter of personal taste. However, I recommend that you use either of those methods using CVS commands to create a new project rather than editing the repository directly. Creating a project with cvs add

To create a project with CVS commands other than cvs import, you need to check out a sandbox that contains only the repository root directory, create the new project root directory, and add that directory with cvs add.

To check out the repository root directory, use a period (.) as the project name. Use the -d name command option to give the sandbox a directory name. To avoid including subdirectories, use the -l command option to cvs checkout.

Example 7-3 shows how to create a project and an initial project sandbox by checking out the repository root directory and using cvs add.

Example 7-3. Importing without cvs import
bash-2.05a$ cvs -d cvs:/var/lib/cvs checkout -l -d cvsroot .
cvs server: Updating cvsroot
bash-2.05a$ cd cvsroot
bash-2.05a$ mkdir wizzard
bash-2.05a$ cvs add wizzard
Directory /var/lib/cvs/wizzard added to the repository
bash-2.05a$ cd ~/cvs
bash-2.05a$ cvs -d cvs:/var/lib/cvs checkout wizzard     
cvs server: Updating wizzard

These are the steps for this method:

  1. Check out the entire top level-directory of the repository, renaming the sandbox root directory with a name such as cvsroot, as shown in Example 7-3.

  2. Change directory into cvsroot and create the new project root directory. In Example 7-3, the project directory is wizzard.

  3. If you have existing files or directories to import, copy them into your newly created directory.

  4. Use cvs add to add the new files and directories to the repository. If you add files as well as directories, you also need to use cvs commit. Example 7-3 shows directory addition only.

    As explained in Chapter 3, the cvs add command adds directories immediately, but files are added to the repository only after the next cvs commit.

  5. Change directories to a working directory and check out the new project to test whether the import worked successfully, as shown in Example 7-3.

  6. Use cvs release to remove the repository root sandbox you checked out in step 1. Remove any temporary files you created when preparing to import the project. Creating a project by editing the repository

The second way to create a new project and bypass cvs import is to edit the repository directly. Editing the repository always involves the risk of making a minor typing error and affecting other projects (or your own), so I suggest you back up the repository before editing it.

To create a new project by editing the repository:

  1. Log in to the repository computer with any user that has write access to the repository root directory.

  2. Change directory into the repository root directory.

  3. Use mkdir project_root_name to create the project root directory.

The rest of this process is optional, and is needed only if you have existing files to add to the project:

  1. Log in to a workstation computer.

  2. Use cvs -d repository_path checkout project_root_name to check out a sandbox.

  3. Copy any existing project files and directories into the new sandbox.

  4. Use cvs add to add the new files and directories to the repository. If you add files as well as directories, you also need to use cvs commit.

7.1.5 Importing from Other Version Control Systems

You might want to import a project, including the project's history, from a different version control system into CVS.

If the other version control system can export files into RCS format, use the following steps to install the RCS files into CVS:

  1. Ensure that the latest revision in each RCS file isn't locked, the access list is empty, and the file-locking type is set to strict, using the tools available in your version control system if possible.

    If your version control system doesn't have tools to do these things and you have RCS installed, you can use rcs -elL filename to set locking and access appropriately.

    If RCS isn't available, you can proceed to steps 2 and 3; then, once the files are in the repository, use cvs admin commands to set locking and access.

  2. Create the project's directory structure in CVS using cvs import or one of the alternative methods described earlier.

  3. Copy the RCS files directly into the appropriate directories in the repository.

If the other version control system can't make RCS files, write a script to check out each revision of each file from the other system and commit it into CVS, or create an RCS file with the RCS ci command and use ci to add each revision of the original file to the RCS file. If you create RCS files, you can install them to CVS as described earlier.

The contrib directory in the CVS source contains scripts that convert SCCS and PVCS files to files CVS can use. These scripts can be used as templates for scripts to convert files from other version control systems. Appendix B contains more information about the sccs2rcs and pvcs2rcs scripts.

  Previous section   Next section