15.5. CVS Administrator Reference
This section provides details on
creating and configuring repositories and performing other CVS
administrative tasks. A single computer can run multiple copies of
the CVS server, and each server can serve multiple repositories.
15.5.3. Repository Structure
The
CVS repository is implemented as a normal directory with special
contents. This section describes the contents of the repository
directory.
15.5.3.1. The CVSROOT directory
The CVSROOT
directory contains the administrative files for the repository; other
directories in the repository contain the modules. The administrative
files permit (and ignore) blank lines and comment lines in addition
to the lines containing real configuration information. Comment lines
start with a hash mark (#).
Some of the administrative files contain filename patterns to match
file and directory names. These patterns are regular expressions like
those used in GNU Emacs. Table 15-2 contains the
special constructions used most often.
Table 15-2. Filename pattern special constructions
Construction
|
Description
|
^
|
Match the beginning of the string.
|
$
|
Match the end of the string.
|
.
|
Match any single character.
|
*
|
Modify the preceding construct to match zero or more repetitions.
|
CVS will perform a few important expansions in the contents of the
administrative files before interpreting the results. First, the
typical shell syntax for referring to a home directory is ~/, which expands to the home directory of the
user running CVS, and ~user expands to the home
directory of the specified user.
In addition, CVS provides a mechanism similar to the
shell's environment variable expansion capability.
Constructs such as ${variable} will be replaced by the value of the named
variable. Variable names start with letters and consist entirely of
letters, numbers, and underscores. Curly brackets may be omitted if
the character immediately following the variable reference is not a
valid variable name character. While this construct looks like a
shell environment variable reference, the full environment is not
available. Table 15-3 contains the built-in
variables.
Table 15-3. Administrative file variables
Variable
|
Description
|
CVSEDITOREDITORVISUAL
|
The editor CVS uses for log file editing.
|
CVSROOT
|
The repository locator in use.
|
USER
|
The name of the user (on the server, if using a remote repository)
running CVS.
|
=var
|
The value of a user-defined variable named var.
Values for these variables are provided by the global -s option.
|
To edit these files, check out the CVSROOT
module from the repository, edit the files, and commit them back to
the repository. You must commit the changes for them to affect
CVS's behavior.
Table 15-4 describes the administrative files and
their functions.
Table 15-4. CVSROOT files
File
|
Description
|
checkoutlist
|
Extra files to be maintained in CVSROOT.
|
commitinfo
|
Specifications for commit governors.
|
config
|
Settings to affect the behavior of CVS.
|
cvsignore
|
Filename patterns of files to ignore.
|
cvswrappers
|
Specifications for checkout and
commit filters.
|
editinfo
|
Specifications for log editors (obsolete).
|
history
|
Log information for the history
command.
|
loginfo
|
Specify commit notifier program(s).
|
modules
|
Module definitions.
|
notify
|
Notification processing specifications.
|
passwd
|
A list of users and their CVS-specific passwords.
|
rcsinfo
|
Template form for log messages.
|
readers
|
A list of users having read-only access.
|
taginfo
|
Tag processing specifications.
|
users
|
Alternate user email addresses for use with
notify.
|
verifymsg
|
Specify log message evaluator program.
|
writers
|
A list of users having read/write access.
|
Since the editinfo file is obsolete, use the
$EDITOR environment variable (or the
-e option) to specify the editor and
the verifymsg file to specify an evaluator.
Each line of the taginfo file contains a
filename pattern and a command line to execute when files with
matching names are tagged.
15.5.3.3. The commitinfo file
Whenever a commit is being processed, CVS consults this
file to determine whether or not any precommit checking of the file
is required. Each line of the file contains a directory name pattern,
followed by the path of a program to invoke when files are commited
in directories with matching names.
Aside from the usual filename-pattern syntax, there are two special
patterns:
- ALL
-
If this pattern is present in the file, all files are passed to the
specified checking program. CVS then looks for a pattern that matches
the name of each particular file and runs the additional checks
found, if any.
- DEFAULT
-
If this pattern is present in the file, all files for which there was
no pattern match are sent to the specified checking program. The
automatic match of every file to the ALL entry, if any, does not count as a match
when determining whether or not to send the file to the DEFAULT checking program.
CVS constructs the command line for the checking program by appending
the full path to the directory within the repository and the list of
files being committed (this means you can specify the first few
command-line arguments to the program, if necessary). If the checking
program exits with a nonzero status, the commit is aborted.
The programs that run via this mechanism run on the server computer
when a remote repository is used. Here is an example of a
commitinfo file:
ALL $CVSROOT/CVSROOT/commit-ALL.pl
DEFAULT $CVSROOT/CVSROOT/commit-DEFAULT.pl
CVSROOT$ $CVSROOT/CVSROOT/commit-CVSROOT.pl
This example assumes you will create the script files in the
CVSROOT module and add them to the
checkoutlist file.
15.5.3.5. The cvsignore file
The cvsignore administrative file contains a list of
filename patterns to ignore, just like the
.cvsignore files that can appear in sandboxes
and user home directories. Unlike the filename patterns in other
administrative files, these patterns are in sh syntax; they are not GNU Emacs-style
regular expressions. There can be multiple patterns on a line,
separated by whitespace (consequently, the patterns themselves cannot
contain whitespace).
There is a slight difference between filename patterns in sh and CVS. Since the CVS patterns are not
subject to variable interpolation, a pattern such as _$* (which is one of the patterns built into
CVS) will match a file named _$foo but not one
named _. But, if you present the same pattern to
sh, the $* part will be interpolated resulting in an
effective pattern of just _, which will then match
the file _, but not _$foo.
This becomes particularly important if you are writing your own
utilities to work with CVS and you need to implement the same policy
for ignoring files.
Table 15-5 shows the most commonly used sh-style pattern constructs.
Table 15-5. Filename patterns for cvsignore
Construct
|
Description
|
?
|
Any one character.
|
*
|
Any sequence of zero or more characters.
|
Again, diverging from the standards used by the rest of the
administrative files, the cvsignore file does
not support comments.
15.5.3.8. The loginfo file
The loginfo administrative file works much like the
commitinfo file and can use the special patterns
ALL and DEFAULT. This file allows you to do something
with commit log messages and related
information.
The programs called during loginfo processing
receive the log message on standard input. Table 15-6 shows the three codes that can pass additional
information to the called programs via command-line arguments.
Table 15-6. Special loginfo variables
Variable
|
Description
|
s
|
Filename
|
V
|
Pre-commit revision number
|
v
|
Post-commit revision number
|
If a percent sign (%) followed by the desired
variable is placed after the command path, CVS inserts the
corresponding information as a whitespace-separated list with one
entry for each file, preceded by the repository path (as with
commitinfo). There can be only one percent sign
on the command line, so if you want information from more than one
variable, place the variable names inside curly brackets: %{...}. In this case, each file-specific entry
has one field for each variable, separated by commas. For example,
the code %{sVv} expands into a list
like this:
/usr/local/cvsrep/hello Makefile,1.1,1.2 hello.c,1.8,1.9
It can be helpful to send email notifications each time someone
commits a file to the repository. Developers can monitor this stream
of notices to determine when they should pull the latest development
code into their private sandboxes. For example, consider a developer
doing some preparatory work in his sandbox while he awaits
stabilization and addition of another developer's
new library. As soon as the new library is added and committed, email
notification goes out, and the waiting developer sees that the code
is ready to use. So, he runs cvs upd
-d in the appropriate directory to pull in the new library
code and then sets about integrating it with his work.
It is simple to set up this kind of notification. Just add a line
like this to the CVSROOT/loginfo file:
DEFAULT mail -s %s developers@company.com
Often, the email address is a mailing list, which has all the
interested parties (developers or otherwise) on the distribution
list. If you want to send messages to multiple email addresses, you
can write a script to do that and have that script called via this
file. Alternatively, you can use the log.pl
program that comes as part of the CVS source distribution (located at
/usr/local/src/cvs-1.11/contrib/log.pl, assuming
CVS was unpacked into /usr/local/src).
Instructions for its use are provided as comments in the file.
15.5.3.9. The modules file
The
top-level directories in a repository are called
modules. In addition to these physical
modules, CVS provides a mechanism to create logical modules through
the modules administrative file. Here are the
three kinds of logical modules:
- Alias
-
Alias modules are defined by lines of the form:
module_name -a alias_module ...
Using an alias module name in a CVS command is equivalent to using
its component modules (after the -a
option) directly.
- Regular
-
Regular modules are defined by lines of the form:
module_name [options] directory file ...
Checking out module_name results in the
specified files from directory being checked out
into a directory named module_name. The
intervening directories (if any) are not reflected in the sandbox.
- Ampersand
-
Ampersand modules are defined by lines of the form:
module_name [options] &other_module ...
Checking out such a module results in a directory named
module_name, which in turn contains copies of
the other_module modules.
Table 15-7 shows the options that can define
modules.
Table 15-7. Module options
Option
|
Description
|
-d name
|
Override the default working directory name for the module.
|
-e prog
|
Run the program prog when files are exported
from the module; the module name is passed in to
prog as the sole argument.
|
-i prog
|
Run the program prog when files are committed to
the module; the repository directory of the committed files is passed
in to prog as the sole argument.
|
-i prog
|
Run the program prog when files are checked out
from the module; the module name is passed in to
prog as the sole argument.
|
-s status
|
Assign a status descriptor to the module.
|
-t prog
|
Run the program prog when files are tagged in
the module using rtag; the module
name and the symbolic tag are passed in to prog.
|
-u prog
|
Run the program prog when files are updated in
the module's top-level directory; the full path to
the module within the repository is passed in to
prog as the sole argument.
|
Alias modules provide alternative names for other modules or
shortcuts for referring to collections or subdirectories of other
modules. Alias module definitions function like macro definitions in
that they cause commands to run as if the expanded list of modules
and directories were on the command line. Alias modules do not cause
the modules of their definition to be grouped together under the
alias name (use ampersand modules for that). For example, the
definition:
h -a hello
makes the name h a synonym for the
hello module. This definition:
project -a library client server
allows you to check out all three modules of the project as a unit.
If an entry in the definition of an alias module is preceded by an
exclamation point (!), then the
named directory is excluded from the module.
Regular modules allow you to create modules that are subsets of other
modules. For example, the definition:
header library library.h
creates the header module, which
consists of only the library.h file from the
library module.
Ampersand modules are true logical modules. There are no top-level
directories for them in the repository, but you can check them out to
sandboxes, and directories with their names will then appear. The
modules listed in the definition are below that directory. For
example:
project &library &client &server
is almost the same as the alias module example given earlier, except
that the submodules are checked out inside a subdirectory named
project.
In this file, long definitions may be split across multiple lines by
terminating all but the last line with backslashes
(\).
15.5.3.11. The passwd file
If you
access the repository via a pserver
repository locator (see Section 15.6.1), then CVS can have its own
private authentication information, separate from the
system's user database. This information is stored
in the CVSROOT/passwd administrative file.
This feature provides anonymous CVS access over the Internet. By
creating an entry for a public user (usually anoncvs or anonymous), the pserver can be used by many people sharing the
public account. If you don't want to create a system
user with the same name as the public user, or if you have such a
user but it has a different purpose, you can employ a user alias to
map it to something else:
anonymous:TY7QWpLw8bvus:cvsnoname
Then, make sure you create the cvsnoname user on the system. You can use
/bin/false as the login shell, and the
repository's root directory as the home directory
for the user.
If you leave the password field empty for the anonymous user, then
CVS will accept any password (as of Version 1.11). To restrict the
public user to read-only access, list it in the
CVSROOT/readers administrative file.
Additionally, CVS's private user database is useful
even if you don't want to set up anonymous CVS
access. You can restrict access to a subset of the
system's users, provide remote access to users who
don't have general system access, or prevent a
user's normal system password from being transmitted
in the clear over the network (see Section 15.5.2).
There is no cvs passwd command for
setting CVS-specific passwords (located in the repository file
CVSROOT/passwd). CVS-specific user and password
management is a manual task.
15.5.4. Hacking the Repository
Since the repository is a normal
directory, albeit one with special contents, it is possible to
cd into the directory and examine
its contents and/or make changes to the files and directories there.
For each file that has been added there will be a file with the same
name followed by ,v in a corresponding directory
in the repository. These are RCS (the format, not the program) files
that contain multiple versions of the file.
TIP:
Since the activities discussed in this section involve making changes
directly to the repository instead of working through CVS commands,
you should exercise extreme caution and have current backups when
following these instructions.
15.5.4.1. Restructuring a project
Restructuring the project by moving files and directories around (and
possibly renaming them) in the repository will allow the files to
retain their history. The standard way to rename a file when using
CVS is to rename the file in the sandbox and do a cvs remove on the old name and a cvs add on the new name. This results in the
file being disconnected from its history under the new name, so
sometimes it is better to do the renaming directly in the repository.
However, doing this while people have active sandboxes is dangerous,
as the sandboxes will contain information about a file that is no
longer in the repository.
15.5.4.2. Obsolete and temporary files
When importing an entire project, all of the
project's files will be added to the repository;
however, if some of these files shouldn't have been
added, you'll want to remove them. Doing a cvs remove will accomplish this, but copies of
those files will remain in the repository's
.Attic directory forever. To avoid this, you can
delete the files from the repository directly before checking out
sandboxes from it.
15.5.5. Importing
If you have an existing code base,
you'll want to import it into CVS in a way that
preserves the most historical information. This section provides
instructions for importing projects into CVS from code snapshots or
other version control systems. Except for the code snapshot import
procedure, all of these are based upon conversion to RCS files,
followed by placing the RCS files in the proper location in the CVS
repository.
15.5.5.1. Importing code snapshots
If you
have maintained project history archives manually by taking periodic
snapshots of the code, you can import the first snapshot, tag it with
the date or version number, and then successively overlay the updated
files from later archives. Each set can then be committed and tagged
in order to bootstrap a repository that maintains the prior history.
For example, first unpack the distributions (this assumes they unpack
to directories containing the version numbers):
$ tar xvzf foo-1.0.tar.gz
$ tar xvzf foo-1.1.tar.gz
$ tar xvzf foo-2.0.tar.gz
Next, make a copy of the first version, import it into the CVS
repository, check it out to make a sandbox (since importing
doesn't convert the source directory into a
sandbox), and use cvs tag to give it
a symbolic name reflecting the project version:
$ mkdir foo
$ cp -R -p foo-1.0/* foo
$ cd foo
$ cvs import -m 'Imported version 1.0' foo vendor start
$ cd ..
$ mv foo foo.bak
$ cvs checkout foo
$ cd foo
$ cvs tag foo-1_0
$ cd ..
Now, apply the differences between Version 1.0 and 1.1 to the
sandbox, commit the changes, and create a tag:
$ diff -Naur foo-1.0 foo-1.1 | (cd foo; patch -Np1)
$ cd foo
$ cvs commit -m 'Imported version 1.1'
$ cvs tag foo-1_1
$ cd ..
Apply the differences between Version 1.1 and 2.0 to the sandbox,
commit the changes, and create a tag:
$ diff -Naur foo-1.1 foo-2.0 | (cd foo; patch -Np1)
$ cd foo
$ cvs commit -m 'Imported version 2.0'
$ cvs tag foo-2_0
You can now use the log command to
view the history of the files, browse past versions of the files, and
continue development under version control.
15.5.5.2. Importing from RCS
If you are migrating from RCS to CVS,
following these instructions will result in a usable CVS repository.
This procedure involves direct modification of the CVS repository, so
it should be undertaken with caution.
Before beginning, make sure none of the files to be imported into CVS
is locked by RCS. Then, create a new CVS repository and module (or a
new module within an existing repository). Next, create directories
in the CVS repository to mirror the project's
directory structure. Finally, copy all the version files
(,v) from the project (which may be in
RCS subdirectories) into the appropriate
directories in the repository (without RCS
subdirectories).
For example, first move aside the directory under RCS control, create
an empty directory to build the new CVS structure, import the
directory, and then check it out to make a sandbox:
$ mv foo foo-rcs
$ mkdir foo
$ cd foo
$ cvs import -m 'New empty project' foo vendor start
$ cd ..
$ mv foo foo.bak
$ cvs checkout foo
Next, make directories and add them to the repository to match the
structure in the RCS project:
$ cd foo
$ mkdir dir
$ cvs add dir
$ cd ..
Now, copy the ,v files from the RCS project into
the repository for the CVS project:
$ cp -p foo-rcs/*,v $CVSROOT/foo
$ cp -p foo-rcs/dir/*,v $CVSROOT/foo/dir
Finally, issue the cvs update
command in the sandbox directory to bring in the latest versions of
all the files:
$ cd foo
$ cvs upd
15.5.6. Using an Interim Shared Sandbox
Projects
will sometimes develop unintended environmental dependencies over
time, especially when there is no pressure for the code to be
relocatable. A project developed outside version control may even be
initially developed in place (at its intended installation location).
While these practices are not recommended, they do occur in
real-world situations. CVS can help to improve the situation by
encouraging relocatability from the beginning of a project.
The default mode of operation for CVS is multiple independent
sandboxes, all coordinated with a central shared repository. Code
that runs in this environment is necessarily (at least partially)
relocatable. So, using CVS from the beginning of a project helps
ensure flexibility.
However, if a project is already well underway, an interim approach
can be used. For example, you could convert the development area to a
single shared sandbox by importing the code into CVS and checking it
back out again:
$ cd /usr/local/bar
$ cvs import bar vendor start
$ cd ..
$ mv bar bar.bak
$ cvs checkout bar
Chances are good that this approach is too aggressive and will check
in more files than absolutely necessary. You can either go back and
hack the repository to remove the files that
shouldn't be there, or just issue the cvs remove command to delete them as you
discover them.
In addition, there will probably be some binary files in the sandbox
that were imported as text files. Wherever you see a binary file that
needs to remain in the repository, you should issue the command
cvs admin -kb
file, then make a fresh copy from the project
backup. Finally, issue the command cvs
commit file to commit the fixed file
back to the repository.
Having version control in place before making flexibility
enhancements is a good idea, as it makes it easier to find (and
possibly reverse) changes that cause trouble.
The repository locator (see Section 15.6.1) is specified via the
-d option or the $CVSROOT environment variable. It is stored in
the various CVS/root sandbox files. If you are
using the password server (pserver),
the user ID of the person checking out the sandbox will be
remembered. If more than one person is working with a particular
sandbox, they will have to share an account for CVS access.
One way to do this is to have a neutral user account with a password
known by everyone with CVS access. One person then issues the
cvs login command with that user ID
and password. Once you are no longer using a shared sandbox, this
workaround won't be necessary. However, during the
time you are using a shared sandbox, it is important that the
developers type their real user IDs into their log messages, since
all the changes will appear to have been made by the common user.
15.5.8. Administrator Commands
Table 15-8
lists the commands that CVS administrators can use to manage their
repositories.
Table 15-8. Administrator commands
Command
|
Description
|
adminadmrcs
|
Perform administrative functions.
|
init
|
Create a new repository.
|
kserver
|
Run in Kerberos server mode.
|
pserver
|
Run in password server mode.
|
server
|
Run in remote server mode.
|
admin
[ -b[rev] ]
[ -cstring ]
[ -kkflag ]
[ -l[rev] ]
[ -L ]
[ -mrev:msg ]
[ -nname[:[rev]] ]
[ -Nname[:[rev]] ]
[ -orange ]
[ -q ]
[ -sstate[:rev]
[ -t[file] ]
[ -t-string ]
[ -u[rev] ]
[ -U ]
[ files ... ] The admin command is used to perform
administrative functions. If a cvsadmin user group exists, then only the
users in that group will be able to run admin with options other than
-k. Options that
may be used with the admin command
are listed here.
- -b[rev]
-
Set the default branch.
- -cstring
-
Obsolete. Set the comment leader.
- -kkflag
-
Set the default keyword substitution mode.
- -l[rev]
-
Lock the specified revision.
- -L
-
Enable strict locking.
- -mrev:msg
-
Change the revision's log message.
- -nname[:[rev]]
-
Give the specified branch or revision the symbolic name
name.
- -Nname[:[rev]]
-
The same as -n, except that if
name is already in use, it is moved.
- -orange
-
Delete revisions permanently.
- -q
-
Don't print diagnostics.
- -sstate[:rev]
-
Change the state of a revision.
- -t[file]
-
Set the descriptive text in the RCS file.
- -t-string
-
Set the descriptive text in the RCS file to
string.
- -u[rev]
-
Unlock the specified revision.
- -U
-
Disable strict locking.
If the revision specified for -l is
a branch, the latest revision on that branch will be used. If no
revision is given, the latest revision on the default branch is used. If the name given for -n is already
in use, an error is generated. You can use -N to move a tag (change the revision
associated with the tag); however, you should normally use cvs tag or cvs
rtag instead. The -o option is very dangerous and
results in a permanent loss of information from the repository. Use
it with extreme caution and only after careful consideration. See
Table 15-9 for the various ways to specify ranges.
There must not be any branches or locks on the revisions to be
removed. Beware of interactions between this command and symbolic
names. If no file is specified for the -t option, CVS reads from standard input until
it reaches the end of the file or a period on a line by itself. The determination of the target revision for the -u option is the same as for -l. Table 15-9. Range formats
Format
|
Description
|
rev1::rev2
|
Eliminate versions between rev1 and
rev2, retaining only enough information to go
directly from rev1 to rev2.
The two specified versions are retained.
|
::rev2
|
The same as rev1::rev2,
except the first revision is the branchpoint revision.
|
rev1::
|
The same as rev1::rev2,
except the second revision is the end of the branch, and it is
deleted instead of retained.
|
rev
|
Delete the specified revision.
|
rev1:rev2
|
The same as rev1::rev2,
except the two named revisions are deleted as well.
|
:rev2
|
The same as ::rev2, except
the named revision is deleted as well.
|
rev1:
|
The same as rev1::, except the named revision is
deleted as well.
|
The following options are present in CVS for historical reasons and
should not be used. (Using these options may corrupt the repository.)
- -alogins
-
Append the logins to the RCS file's access list.
- -Aoldfile
-
Append the access list of oldfile to the access list of the RCS file.
- -e[logins]
-
Erase logins from the RCS file's access list, or
erase all if a list is not provided.
- -i
-
Create and initialize a new RCS file. Don't use this
option. Instead, use add to add
files to a CVS repository.
- -I
-
Run interactively. This option doesn't work with
client/server CVS and is likely to be removed in a future version.
- -Vn
-
This option specified that the RCS files used by CVS should be made
compatible with a specific version of RCS.
- -xsuffixes
-
This option used to be described as determining the filename suffix
for RCS files, but CVS has always used only ,v
as the RCS file suffix.
 |  |  | 15.4. Gotchas |  | 15.6. CVS User Reference |
Copyright © 2003 O'Reilly & Associates. All rights reserved.
|