Whole document tree
Repository AdministrationIn An Overview of CVS, you learned enough CVS to use it effectively as a project participant. If you're going to be a project maintainer, however, you'll need to know how to install CVS and administer repositories. In this chapter, we'll throw back the curtain and look in detail at how the repository is structured, and how CVS uses it. You'll learn all the major steps CVS goes through during updates and commits, and how you can modify its behavior. By understanding how CVS works, you'll also be able to trace problems to their causes, and fix them in maintainable ways. This may sound very involved, but remember that CVS has already proven quite long-lived, and will probably be around for many years to come. Whatever you learn now will be useful for a long time. CVS also tends to become more indispensable the more you use it. If you're going to be that dependent on something (and trust me, you are), it's worth really getting to know it. With that in mind, let's begin at the beginning: putting CVS on your system.
1.4 Getting And Installing CVSIn many cases, you won't have to go out and get CVS, because it will already be on your system. If you run one of the major Linux or FreeBSD distributions, it's probably already installed in /usr/bin or some other likely location. If not, Red Hat Linux users can usually find an RPM (Red Hat Package) for the latest, or nearly latest, version of CVS in their distributions. And Debian users can install the latest Debian package with these commands:
If CVS isn't already on your machine, you'll probably have to build it from source. If you're a non-Unix user, you'll probably find it easier to get a prebuilt binary for your operating system (more on that later). Fortunately, CVS is fully autoconfiscated -- that is, it uses the GNU autoconfiguration mechanism, making compilation from source surprisingly easy.
1.4.1 Getting And Building CVS Under UnixAs of this writing, there are two canonical sites from which you can download CVS. One is the Free Software Foundation's FTP site, ftp://ftp.gnu.org/gnu/cvs/, which offers CVS as an official GNU tool. The other is Cyclic Software's download site. Cyclic Software is, if not the maintainer of CVS, then the "maintainer of the maintainers", by providing a repository server and download access for users and developers. They distribute releases from http://download.cyclic.com/pub/. Either location is fine. In the following example, I use Cyclic Software's site. If you point your FTP client (probably your Web browser) there, you'll see a list of directories, something like this:
Pay attention to the directories beginning with "cvs-" (you can ignore most of the others). There are three such directories, which means that you're already faced with a choice: Get the designated "stable" release, or go with a newer (but less-tested) interim release. The stable releases have only one decimal point, as in "cvs-1.10", whereas the interim releases have minor version increments tacked on the end, as in "1.10.5". The GNU site usually only offers the major releases, not the interim ones, so you won't see all of this if you get CVS from there. In general, the interim releases have been pretty safe, and sometimes contain fixes to bugs that were found in the major release. Your best policy is to go with the highest interim release, but if you encounter any problems with it, be prepared to drop back to the previous release, as many times as necessary. The highest release listed in the earlier example is cvs-1.10.6. Entering that directory, we see this:
That's it -- the full source code to CVS. Just download it to your machine, and you're ready to build. At this point, if you're already familiar with the standard build process for GNU tools, you know what to do and probably don't need to read anything between here and the section 1.5 Anatomy Of A CVS Distribution. On the other hand, if you're not sure how to proceed, then read on.... The following compilation instructions and examples assume that you have a fairly standard distribution of Unix. Any of the free versions of Unix (for example, FreeBSD or Linux) should work with no problem, as should the major commercial Unix versions (such as SunOS/Solaris, AIX, HP-UX, or Ultrix). Even if these instructions don't work for you exactly as written, don't give up hope. Although covering the details of compiling on every operating system is beyond the scope of this book, I'll give some pointers to other help resources later in this chapter. Anyway, to proceed with the compilation, first unpack the tar file using GNU gunzip and tar (if you don't have these installed on your system, you can get gunzip from ftp://ftp.gnu.org/gnu/gzip/ and GNU's version of tar from ftp://ftp.gnu.org/gnu/tar/):
You'll see a lot of file names fly by on your screen. Now you have a new directory on your machine -- cvs-1.10.6 -- and it is populated with the CVS source code. Go into that directory and configure CVS for your system, by using the provided configure script:
When the configure command finishes, the source tree will know everything it needs to know about compiling on your machine. The next step is to type:
You'll see lots of output fly by, then type:
You'll see yet more output fly by; when it's all over, CVS will be installed on your system. (You will probably need to do that last step as the superuser.) By default, the CVS executable will end up as `/usr/local/bin/cvs'. This assumes you have a decent make program installed on your system (again, if you don't have one, get the GNU project's make from ftp://ftp.gnu.org/gnu/make/). If you want CVS to install to a location other than /usr/local/bin, you should change how you run the initial configuration step. For example,
results in CVS being installed as /usr/bin/cvs (it always ends up as PREFIX/bin/cvs). The default prefix is /usr/local, which is fine for most installations. Note To Experienced Users: Although older versions of CVS consisted of more than just an executable in that they depended on having RCS installed as well, this has not been the case since Version 1.10. Therefore, you don't need to worry about any libraries or executables other than cvs itself. If you just intend to use CVS to access remote repositories, the preceding is all you need to do. If you also plan to serve a repository from this system, a few additional steps are necessary, which are covered later in this chapter.
1.4.2 Getting And Installing CVS Under WindowsUnless you're truly religious about having the source code to your executable, you don't need to compile CVS from source on your Windows box. Unlike Unix, the necessary compilation tools probably do not already exist on your system, so a source build would involve first going out and getting those tools. Because such a project is beyond the scope of this book, I'll just give instructions for getting a precompiled CVS binary. First, note that Windows binary distributions of CVS are usually made only for major releases of CVS -- not for the interim releases -- and are not found on the GNU FTP site. So you'll need to go to Cyclic Software's download site, where in the major version directory, http://download.cyclic.com/pub/cvs-1.10/, you'll see an extra subdirectory
inside of which is a ZIP file:
This ZIP file contains a binary distribution of CVS. Download and extract that ZIP file:
The README there contains detailed instructions. For most installations, they can be summarized as follows: Put all of the EXE and DLL files in a directory in your PATH. Additionally, if you're going to be using the pserver method to access a remote repository, you may need to put the following in your `C:\AUTOEXEC.BAT' file and reboot:
This tells CVS where to store the .cvspass file. CVS running under Windows cannot currently serve repositories to remote machines; it can be a client (connecting to remote repositories), and operate in local mode (using a repository on the same machine). For the most part, this book assumes that CVS under Windows is operating as a client. However, it shouldn't be too hard to set up a local repository under Windows after reading the Unix-oriented instructions in the rest of this chapter. If you are only accessing remote repositories, you may not even need to run CVS. There is a tool called WinCvs that implements only the client-side portion of CVS. It is distributed separately from CVS itself but, like CVS, is freely available under the GNU General Public License. More information is available from http://www.wincvs.org.
1.4.3 Getting And Installing CVS On A MacintoshCVS is available for the Macintosh, but not as part of the main distribution. At the moment, there are actually three separate Macintosh CVS clients available:
Frankly, I have no idea which one is best. Try them all, not necessarily in the order given, and see which one you like. MacCVS Pro seems to be under active development. MacCvs is apparently a companion project of WinCVS and shares a home page with it. (As of this writing, a notice on the WinCVS page states, "Development of MacCvs will be resumed soon.", whatever that means.)
1.4.4 Limitations Of The Windows And Macintosh VersionsThe Windows and Macintosh distributions of CVS are generally limited in functionality. They can all act as clients, meaning that they can contact a repository server to obtain a working copy, commit, update, and so on. But they can't serve repositories themselves. If you set it up right, the Windows port can use a local-disk repository, but it still can't serve projects from that repository to other machines. In general, if you want to have a network-accessible CVS repository, you must run the CVS server on a Unix box.
1.5 Anatomy Of A CVS DistributionThe preceding instructions are designed to get you up and running quickly, but there's a lot more inside a CVS source distribution than just the code. Here's a quick road map to the source tree, so you'll know which parts are useful resources and which can be ignored.
1.5.1 Informational FilesIn the top level of the distribution tree, you'll find several files containing useful information (and pointers to further information). They are, in approximate order of importance:
1.5.2 SubdirectoriesThe CVS distribution contains a number of subdirectories. In the course of a normal installation, you won't have to navigate among them, but if you want to go poking around in the sources, it's nice to know what each one does. Here they are:
The majority of these can be ignored. The emx/, os2/, vms/, and windows-NT/ subdirectories all contain operating-system-specific source code, which you would only need if you're actually trying to debug a code-level problem in CVS (an unlikely situation, though not unheard of). The diff/ and zlib/ subdirectories contain CVS's internal implementations of the diff program and the GNU gzip compression library, respectively. (CVS uses the latter to reduce the number of bits it has to send over the network when accessing remote repositories.) The contrib/ and tools/ subdirectories contain free third-party software meant to be used with CVS. In contrib/, you will find an assortment of small, specialized shell scripts (read contrib/README to find out what they do). The tools/ subdirectory used to contain contributed software, but now contains a README file, which says in part:
The PCL-CVS package it's referring to is very handy, and I'll have more to say about it in Third-Party Tools. The src/ and lib/ subdirectories contain the bulk of the CVS source code, which involves the CVS internals. The main data structures and commands are implemented in src/, whereas lib/ contains small code modules of general utility that CVS uses. The man/ subdirectory contains the CVS man pages (intended for the Unix online manual system). When you ran make install, they were incorporated into your Unix system's regular man pages, so you can type
and get a rather terse introduction and subcommand reference to CVS. Although useful as a quick reference, the man pages may not be as up to date or complete as the Cederqvist manual (see the next section); however, the man pages are more likely to be incomplete than actually wrong, if it's any comfort.
1.5.3 The Cederqvist ManualThat leaves the doc/ subdirectory, whose most important inhabitant is the famed Cederqvist. These days, it's probably a stretch to call it "the Cederqvist". Although Per Cederqvist (of Signum Support, Linkoping Sweden, www.signum.se) wrote the first version around 1992, it has been updated since then by many other people. For example, when contributors add a new feature to CVS, they usually also document it in the Cederqvist. The Cederqvist manual is written in Texinfo format, which is used by the GNU project because it's relatively easy to produce both online and printed output from it (in Info and PostScript formats, respectively). The Texinfo master file is doc/cvs.texinfo, but CVS distributions come with the Info and PostScript pregenerated, so you don't have to worry about running any Texinfo tools yourself. Although the Cederqvist can be used as an introduction and tutorial, it is probably most useful as a reference document. For that reason, most people browse it online instead of printing it out (although the PostScript file is `doc/cvs.ps', for those with paper to spare). If this is the first time you've installed CVS on your system, you'll have to take an extra step to make sure the manual is accessible online. The Info files (doc/cvs.info, doc/cvs.info-1, doc/cvs.info-2, and so on) were installed for you when you ran make install. Although the files were copied into the system's Info tree, you may still have to add a line for CVS to the Info table of contents, the "Top" node. (This will only be necessary if this is the first time CVS has been installed on your system; otherwise, the entry from previous installations should already be in the table of contents.) If you've added new Info documentation before, you may be familiar with the process. First figure out where the Info pages were installed. If you used the default installation (in /usr/local/), then the Info files are /usr/local/info/cvs.info*. If you installed using
the files ended up as /usr/info/cvs.*. After you locate the files, you'll need to add a line for CVS to the Info table of contents, which is in a file named dir in that directory (so in the latter case, it would be /usr/info/dir). If you don't have root access, ask your system administrator to do it. Here is an excerpt from dir before the reference to CVS documentation was added:
And here is the same region of dir afterwards:
The format of the line is very important. You must include the asterisk, spaces, and colon in `* Cvs:' and the parentheses and period in `(cvs).' after it. If any of these elements are missing, the Info dir format will be corrupt, and you'll be unable to read the Cederqvist. Once the manual is installed and referred to from the table of contents, you can read it with any Info-compatible browser. The ones most likely to be installed on a typical Unix system are either the command-line Info reader, which can be invoked this way if you want to go straight to the CVS pages
and the one within Emacs, which is invoked by typing
or
Take whatever time is necessary to get the Cederqvist set up properly on your system when you install CVS; it will pay off many times down the road when you need to look something up.
1.5.4 Other Sources Of InformationIn addition to the Cederqvist, the FAQ, and the other files in the distribution itself, there are Internet resources devoted to CVS. If you're going to administrate a CVS server, you'll probably want to join the info-cvs mailing list. To subscribe, send email to info-cvs-request@gnu.org (the list itself is info-cvs@gnu.org). Traffic can be medium to heavy, around 10 to 20 emails a day, most of them questions seeking answers. The majority of these can be deleted without reading (unless you want to help people by answering their questions, which is always nice), but every now and then someone will announce the discovery of a bug or announce a patch that implements some feature you've been wanting. You can also join the formal bug report mailing list, which includes every bug report sent in. This probably isn't necessary, unless you intend to help fix the bugs, which would be great, or you're terrifically paranoid and want to know about every problem other people find with CVS. If you do want to join, send email to bug-cvs-request@gnu.org.
There's also a Usenet newsgroup, Finally, there are at least three Web sites devoted to CVS. Cyclic Software's http://www.cyclic.com has been CVS's informal home site for a few years, and probably will continue to be for the foreseeable future. Cyclic Software also provides server space and Net access for the repository where the CVS sources are kept. The Cyclic Web pages contain comprehensive links to experimental patches for CVS, third-party tools that work with CVS, documentation, mailing list archives, and just about everything else. If you can't find what you need in the distribution, http://www.cyclic.com is the place to start looking. Two other good sites are Pascal Molli's http://www.loria.fr/~molli/cvs-index.html and Sean Dreilinger's http://durak.org/cvswebsites/. The biggest attraction at Molli's site is, of course, the FAQ, but it also has links to CVS-related tools and mailing list archives. Dreilinger's site specializes in information about using CVS to manage Web documents and also has a CVS-specific search engine.
1.6 Starting A RepositoryOnce the CVS executable is installed on your system, you can start using it right away as a client to access remote repositories, following the procedures described in An Overview of CVS. However, if you want to serve revisions from your machine, you have to create a repository there. The command to do that is
where `/usr/local/newrepos' is a path to wherever you want the repository to be (of course, you must have write permission to that location, which may imply running the command as the root user). It may seem somewhat counterintuitive that the location of the new repository is specified before the init subcommand instead of after it, but by using the -d option, it stays consistent with other CVS commands. The command will return silently after it is run. Let's examine the new directory:
The single subdirectory in the new repository -- CVSROOT/ -- contains various administrative files that control CVS's behavior. Later on, we'll examine those files one by one; for now, the goal is just to get the repository working. In this case, "working" means users can import, check out, update, and commit projects. Don't confuse the CVSROOT environment variable introduced in An Overview of CVS with this CVSROOT subdirectory in the repository. They are unrelated -- it is an unfortunate coincidence that they share the same name. The former is a way for users to avoid having to type `-d <repository-location>' every time they use CVS; the latter is the administrative subdirectory of a repository. Once the repository is created, you must take care of its permissions. CVS does not require any particular, standardized permission or file ownership scheme; it merely needs write access to the repository. However -- partly for security reasons, but mainly for your own sanity as an administrator -- I highly recommend that you take the following steps:
Now any of the users listed in that group can start a project by running
If your repository is intended to serve projects to the general public, where contributors won't necessarily have accounts on the repository machine, you should set up the password-authenticating server now (see section 1.7 The Password-Authenticating Server). It's necessary for anonymous read-only access, and it's also probably the easiest way to grant commit access to certain people without giving them full accounts on the machine.
1.7 The Password-Authenticating Server
Before running through the steps needed to set up the password server,
let's examine how such connections work in the abstract. When a remote
CVS client uses the The CVS server is not actually waiting for connections at that port -- the server won't get started up until a connection actually arrives. Instead, the Unix inetd (InterNET Daemon) program is listening on that port, and needs to know that when it receives a connection request there, it should start up the CVS server and connect it to the incoming client. This is accomplished by modifying inetd's configuration files: `/etc/services' and `/etc/inetd.conf'. The services file maps raw port numbers to service names and then inetd.conf tells inetd what to do for a given service name. First, put a line like this into /etc/services (after checking to make sure it isn't already there):
Then in /etc/inetd.conf, put this:
(In the actual file, this should be all one long line, with no backslash.) If your system uses tcpwrappers, you may want to use something like this instead:
Now, restart inetd so it notices the changes to its configuration files (if you don't know how to restart the daemon, just reboot the machine -- that will work too). That's enough to permit connections, but you'll also want to set up special CVS passwords -- separate from the users' regular login passwords -- so people can access the repository without compromising overall system security. The CVS password file is CVSROOT/passwd in the repository. It was not created by default when you ran cvs init, because CVS doesn't know for sure that you'll be using pserver. Even if the password file had been created, CVS would have no way of knowing what usernames and passwords to create. So, you'll have to create one yourself; here's a sample CVSRoot/passwd file:
The format is as simple as it looks. Each line is:
The extra colon followed by an optional system username tells CVS that connections authenticated with USERNAME should run as the system account SYSTEM_USERNAME -- in other words, that CVS session would only be able to do things in the repository that someone logged in as SYSTEM_USERNAME could do. If no system username is given, USERNAME must match an actual login account name on the system, and the session will run with that user's permissions. In either case, the encrypted password should not be the same as the user's actual login password. It should be an independent password used only for CVS pserver connections. The password is encrypted using the same algorithm as the standard Unix system passwords stored in /etc/passwd. You may be wondering at this point, how does one acquire an encrypted version of a password? For Unix system passwords, the passwd command takes care of the encryption in /etc/passwd for you. Unfortunately, there is no corresponding cvs passwd command (it has been proposed several times, but no one's gotten around to writing it -- perhaps you'll do it?). This is an inconvenience, but only a slight one. If nothing else, you can always temporarily change a regular user's system password using passwd, cut and paste the encrypted text from /etc/passwd into CVSROOT/passwd, and then restore the old password (note that on some systems, the encrypted passwords are found in /etc/shadow and are readable only by root.) That scheme is workable but rather cumbersome. It would be much easier to have a command-line utility that takes a plain text password as its argument and outputs the encrypted version. Here is such a tool, written in Perl:
I keep the preceding script in `/usr/local/bin/cryptout.pl':
If I took the output of this example and used it to create the following entry in CVSROOT/passwd
then someone could connect to the repository with the following command:
They could then type If someone attempts to authenticate with a username and password that don't appear in CVSROOT/passwd, CVS will check to see if that username and password are present in /etc/passwd. If they are (and if the password matches, of course), CVS will grant access. It behaves this way for the administrator's convenience, so that separate CVSROOT/passwd entries don't have to be set up for regular system users. However, this behavior is also a security hole, because it means that if one of those users does connect to the CVS server, her regular login password will have crossed over the network in cleartext, potentially vulnerable to the eyes of password sniffers. A bit further on, you'll learn how to turn off this "fallback" behavior, so that CVS consults only its own passwd file. Whether you leave it on or off, you should probably force any CVS users who also have login accounts to maintain different passwords for the two functions. Although the passwd file authenticates for the whole repository, with a little extra work you can still use it to grant project-specific access. Here's one method:
Suppose you want to grant some remote developers access to project
Here's the relevant excerpt from /etc/passwd
and from /etc/group
and, finally, CVSROOT/passwd:
Some of the CVS usernames map onto the system user account
1.8 Anonymous Access
So far we've only seen how to use the password-authenticating server to
grant normal full access to the repository (although admittedly one can
restrict that access through carefully arranged Unix file permissions).
Turning this into anonymous, read-only access is a simple step: You just
have to add a new file, or possibly two, in CVSROOT/. The files' names
are If you list a username in CVSROOT/readers, that user will have only read access to all projects in the repository. If you list a username in CVSROOT/writers, that user will have write access, and every pserver user not listed in writers will have read-only access (that is, if the writers file exists at all, it implies read-only access for all those not listed in it). If the same username is listed in both files, CVS resolves the conflict in the more conservative way: the user will have read-only access. The format of the files is very simple: one user per line (don't forget to put a newline after the last user). Here is a sample readers file:
Note that the files apply to CVS usernames, not system usernames. If you use user aliasing in the CVSROOT/passwd file (putting a system username after a second colon), the leftmost username is the one to list in a readers or writers file. Just to be painfully accurate about it, here is a formal description of the server's behavior in deciding whether to grant read-only or read-write access: If a readers file exists and this user is listed in it, then she gets read-only access. If a writers file exists and this user is not listed in it, then she also gets read-only access (this is true even if a readers file exists but that person is not listed there). If that person is listed in both, she gets read-only access. In all other cases, that person gets full read-write access. Thus, a typical repository with anonymous CVS access has this (or something like it) in CVSROOT/passwd
this (or something like it) in /etc/passwd
and this in CVSROOT/readers:
And, of course, the aforementioned setup in /etc/services and /etc/inetd.conf. That's all there is to it!
Note that some older Unix systems don't support usernames longer than
eight characters. One way to get around this would be to call the user
(and then of course use
would actually run on the server as cvsanon (or whatever). But they wouldn't need to know or care about how things are set up on the server side -- they'd only see the published address.
1.9 Repository StructureThe new repository still has no projects in it. Let's re-run the initial import from An Overview of CVS, watching what happens to the repository. (For simplicity's sake, all commands will assume that the CVSROOT environment variable has been set to /usr/local/newrepos, so there's no need to specify the repository with -d on imports and checkouts.)
Before the import, the repository contained only its administrative
area, CVSROOT. After the import, a new directory -- `myproj' --
appeared. The files and subdirectories inside that new directory look
suspiciously like the project we imported, except that the files have
the suffix
1.10 RCS FormatYou do not need to know any of the RCS format to use CVS (although there is an excellent writeup included with the source distribution, see doc/RCSFILES). However, a basic understanding of the format can be of immense help in troubleshooting CVS problems, so we'll take a brief peek into one of the files, `hello.c,v'. Here are its contents:
Whew! Most of that you can ignore; don't worry about the relationship between 1.1 and 1.1.1.1, for example, or the implied 1.1.1 branch -- they aren't really significant from a user's or even an administrator's point of view. What you should try to grok is the overall format. At the top is a collection of header fields:
Farther down in the file are groups of meta-information about each revision (but still not showing the contents of that revision), such as:
And finally, the log message and text of an actual revision:
If you look closely, you'll see that the first revision's contents are
stored under the heading 1.1, but that the log message there is "Initial
revision", whereas the log message we actually used at import time was
"initial import into CVS", which appears farther down, under
The file becomes even more revealing after we commit the first modification to hello.c:
If you look at hello.c,v in the repository now, you can see the effect of the commit:
Now the full contents of Revision 1.2 are stored in the file, and the text for Revision 1.1 has been replaced with the cryptic formula:
The This demonstrates the basic principle of RCS format: It stores only the differences between revisions, thereby saving a lot of space compared with storing each revision in full. To go backwards from the most recent revision to the previous one, it patches the later revision using the stored diff. Of course, this means that the further back you travel in the revision history, the more patch operations must be performed (for example, if the file is on Revision 1.7 and CVS is asked to retrieve Revision 1.4, it has to produce 1.6 by patching backwards from 1.7, then 1.5 by patching 1.6, then 1.4 by patching 1.5). Fortunately, old revisions are also the ones least often retrieved, so the RCS system works out pretty well in practice: The more recent the revision, the cheaper it is to obtain. As for the header information at the top of the file, you don't need to know what all of it means. However, the effects of certain operations show up very clearly in the headers, and a passing familiarity with them may prove useful.
When you commit a new revision on the trunk, the
Now examine the header section of foo.jpg,v in the repository:
Notice the b in the expand line at the end -- it's due to our having used the -kb flag when adding the file, and means the file won't undergo any keyword or newline expansions, which would normally occur during checkouts and updates if it were a regular text file. The tags appear in the symbols section, one tag per line -- both of them are attached to the first revision, since that's what was tagged both times. (This also helps explain why tag names can only contain letters, numbers, hyphens, and underscores. If the tag itself contained colons or dots, the RCS file's record of it might be ambiguous, because there would be no way to find the textual boundary between the tag and the revision to which it is attached.) RCS Format Always Quotes @ Signs
The
which is stored in foo.jpg,v like this:
The @ sign in jrandom@@red-bean.com will be automatically unquoted whenever CVS retrieves the log message:
The only reason you should care is that if you ever find yourself hand-editing RCS files (a rare circumstance, but not unheard of), you must remember to use double @ signs in revision contents and log messages. If you don't, the RCS file will be corrupt and will probably exhibit strange and undesirable behaviors. Speaking of hand-editing RCS files, don't be fooled by the permissions in the repository:
(For those not fluent in Unix ls output, the
The myproj/ directory itself -- and its subdirectories -- are all writeable by the owner (jrandom) and the group (users). This means that CVS (running as jrandom, or as anyone in the users group) can create and delete files in those directories, even if it can't directly edit files already present. CVS edits an RCS file by making a separate copy of it, so you should also make all of your changes in a temporary copy, and then replace the existing RCS file with the new one. (But please don't ask why the files themselves are read-only -- there are historical reasons for that, having to do with the way RCS works when run as a standalone program.)
Incidentally, having the files' group be
The usual Unix file-creation rules govern which group is assigned to new
files that appear in the repository, so once in a while you may need to
run chgrp or chmod on certain files or directories in the repository
(setting the SGID bit with
1.11 What Happens When You Remove A File
When you remove a file from a project, it doesn't just disappear. CVS
must be able to retrieve such files when you request an old snapshot of
the project. Instead, the file gets put in the
In each repository directory of a project, the presence of an
`Attic/' subdirectory means that at least one file has been removed
from that directory (this means that you shouldn't use directories named
Attic in your projects). CVS doesn't merely move the RCS file into
Attic/, however; it also commits a new revision into the file, with a
special revision state of
If the file is later brought back to life, CVS has a way of recording that it was dead at some point in the past and is now alive again. This means that if you want to restore a removed file, you can't just take it out of the Attic/ and put it back into the project. Instead, you have to do something like this in a working copy:
There's a lot more to know about RCS format, but this is sufficient for a CVS adminstrator to maintain a repository. It's quite rare to actually edit an RCS file; you'll usually just have to tweak file permissions in the repository, at least if my own experience is any guide. Nevertheless, when CVS starts behaving truly weirdly (rare, but not completely outside the realm of possibility), you may want to actually look inside the RCS files to figure out what's going on.
1.12 The CVSROOT/ Administrative DirectoryThe files in newrepos/CVSROOT/ are not part of any project, but are used to control CVS's behavior in the repository. The best way to edit those files is to check out a working copy of CVSROOT, just like a regular project:
We'll take the files in their approximate order of importance. Note
that each of the files comes with an explanatory comment at the
beginning (the comment convention is the same across all of them: A
If you're extremely security conscious, you may want to arrange the Unix-level permissions on CVSROOT to be different from permissions elsewhere in the repository, in order to have fine-grained control over who can commit changes to CVSROOT. As you'll see a little later, being able to modify the files in CVSROOT essentially gives any CVS user -- even remote ones -- the ability to run arbitrary commands on the repository machine.
1.12.1 The config FileThe config file allows you to configure certain global behavioral parameters. It follows a very strict format
with no extra spaces allowed. For example, here is a possible config file:
(An absent entry would be equivalent to
The
There are no other parameters at this time, but future versions of CVS may add new ones; you should always check the Cederqvist or the distribution config file itself for updates.
1.12.2 The modules FileIn modules, you can define aliases and alternate groupings for projects in the repository. The most basic module line is of the form:
for example,
(The paths given on the right are relative to the top of the repository.) This gives developers an alternate name by which to check out a project or a portion of a project:
or
Notice how in both cases the module's name became the name of the directory created for the working copy. In the case of asub, it didn't even bother with the intermediate myproj/ directory, but created a top-level asub/ instead, even though it came from myproj/a-subdir in the repository. Updates, commits, and all other CVS commands will behave normally in those working copies -- the only thing unusual about them are their names. By putting file names after the directory name, you can define a module consisting of just some of the files in a given repository directory. For example
and
would permit the following checkouts, respectively:
You can define a module that will include multiple repository
directories by using the -a (for
would allow you to do this (assuming that both myproj/ and yourproj/ are in the repository):
The name Modules can even refer to other modules, by prefixing them with an ampersand:
Doing a checkout of There are a few other tricks you can do with modules, most of them less frequently used than the ones just presented. See the node modules in the Cederqvist for information about them.
1.12.3 The commitinfo And loginfo And rcsinfo FilesMost of the other administrative files provide programmatic hooks into various parts of the commit process (for example, the ability to validate log messages or file states before permitting the commit, or the ability to notify a group of developers whenever a commit happens in a certain directory of the repository). The files generally share a common syntax. Each line is of the form:
The regular expression will be tested against the directory into which the commit is taking place (with the directory name relative to the top of the repository). If it matches, the designated program will be run. The program will be passed the names of each of the files in the commit; it can do whatever it likes with those names, including opening up the files and examining their contents. If the program returns with a nonzero exit status, the commit is prevented from taking place.
(Regular expressions are a system for concisely describing classes
of strings. If you aren't familiar with regular expressions, you can
get by with the following short summary: The commitinfo file is for generic hooks you want run on every commit. Here are some example commitinfo lines:
So any commit into myproj/a-subdir/ would match the first line, which
would then run the check-asubdir.sh script. A commit in any project
whose name (actual repository directory name, not necessarily module
name) contained the string
In place of a regular expression, the word The file names passed to the program do not refer to RCS files -- they point to normal files, whose contents are exactly the same as the working-copy files being committed. The only unusual aspect is that CVS has them temporarily placed inside the repository, so they'll be available to programs running on the machine where the repository is located. The loginfo file is similar to commitinfo, except that instead of acting on the files' contents, it acts on the log message. The left side of the loginfo file contains regular expressions, including possibly DEFAULT and ALL lines. The program invoked on the right side receives the log message on its standard input; it can do whatever it wants with that input.
The program on the right side can also take an arbitrary number of
command-line arguments. One of those arguments can be a special
The expansion always begins with the repository subdirectory (relative
to the top of the repository), followed by the per-file information.
For example, if the files committed were foo, bar, and baz, all in
`myproj/a-subdir', then
whereas
and
You can combine
and
(You may have to look carefully to distinguish the commas from the periods in those examples.) Here is a sample loginfo file:
In the first line, any commit in the myproj subdirectory of the repository invokes `log.pl', passing it an email address (to which `log.pl' will send a mail containing the log message), followed by the repository, followed by all the files in the commit.
In the second line, any commit in a repository subdirectory containing
the string The third line invokes the (equally imaginary) `default-notify.pl' script for any commit that didn't match either of the two previous lines, passing it all possible information (path to repository, file names, old revisions, and new revisions).
1.12.4 The verifymsg And rcsinfo Files
Sometimes you may just want a program to automatically verify that the
log message conforms to a certain standard and to stop the commit if
that standard is not met. This can be accomplished by using
The verifymsg file is the usual combination of regular expressions and programs. The program receives the log message on standard input; presumably it runs some checks to verify that the log message meets certain criteria, then it exits with status zero or nonzero. If the latter, the commit will fail. Meanwhile, the left side of rcsinfo has the usual regular expressions, but the right side points to template files instead of programs. A template file might be something like this
or some other collection of fields that a developer is supposed to fill out to form a valid log message. The template is not very useful if everyone commits using the -m option explicitly, but many developers prefer not to do that. Instead, they run
and wait for CVS to automatically fire up a text editor (as specified in the EDITOR environment variable). There they write a log message, then save the file and exit the editor, after which CVS continues with the commit. In that scenario, an rcsinfo template would insert itself into the editor before the user starts typing, so the fields would be displayed along with a reminder to fill them in. Then when the user commits, the appropriate program in `verifymsg' is invoked. Presumably, it will check that the message does follow that format, and its exit status will reflect the results of its inquiry (with zero meaning success).
As an aid to the verification programs, the path to the template from
the rcsinfo file is appended as the last argument to the program command
line in Note that when someone checks out a working copy to a remote machine, the appropriate rcsinfo template file is sent to the client as well (it's stored in the CVS/ subdirectory of the working copy). However, this means that if the rcsinfo file on the server is changed after that, the client won't see the changes without re-checking out the project (merely doing an update won't work). Note also that in the verifymsg file, the ALL keyword is not supported (although DEFAULT still is). This is to make it easier to override default verification scripts with subdirectory-specific ones.
1.12.5 The taginfo FileWhat loginfo does for log messages, taginfo does for tags. The left side of taginfo is regular expressions, as usual, and the right side is programs. Each program is automatically handed arguments when CVS tag is invoked, in this order:
If the program returns nonzero, the tag is aborted.
We haven't covered the -F option to tag before now, but it's exactly
what the above implies: a way to move a tag from one revision to
another. For example, if the tag
which removes the tag from 1.7, or wherever it was previously in that file, and puts it at 1.11.
1.12.6 The cvswrappers FileThe redundantly-named cvswrappers file gives you a way to specify that certain files should be treated as binary, based on their file name. CVS does not assume that all .jpg files are JPG image data, for example, so it doesn't automatically use -kb when adding JPG files. Nonetheless, certain projects would find it very useful to simply designate all JPG files as binary. Here is a line in cvswrappers to do that:
The There are a few other modes that can be specified from the wrappers file, but they're for such rare situations that they're probably not worth documenting here (translation: your author has never had to use them). See the node Wrappers in the Cederqvist if you're curious.
1.12.7 The editinfo FileThis file is obsolete, even though it's still included in distributions. Just ignore it.
1.12.8 The notify File
This file is used in conjunction with CVS's
1.12.9 The checkoutlist FileIf you look inside CVSROOT/, you'll see that working copies of the files exist side by side with their RCS revision files:
CVS only pays attention to the working versions, not the RCS files, when it's looking for guidance on how to behave. Therefore, whenever you commit your working copy of CVSROOT/ (which might, after all, even be checked out to a different machine), CVS automatically updates any changed files in the repository itself. You will know that this has happened because CVS will print a message at the end of such commits:
CVS automatically knows about the standard administrative files, and will rebuild them in CVSROOT/ as necessary. If you decide to put custom files in CVSROOT/ (such as programs or rcsinfo template files), you'll have to tell CVS explicitly to treat them the same way. That's the purpose of the checkoutlist file. It has a different format from most of the files we've looked at so far
for example,
Certain files in CVSROOT are traditionally not kept under revision
control. One such is the history file, which keeps a running
record of all actions in the repository, for use by the Note: sometimes the history file is the cause of permission problems, and the easiest way to solve them is to either make it world-writeable or just remove it.
Another Two final notes about the CVSROOT/ directory: It is possible, if you make a big enough mistake, to commit an administrative file that is broken in such a way as to prevent any commits from happening at all. If you do that, naturally you won't be able to commit a fixed version of the administrative file! The solution is to go in and hand-edit the repository's working copy of the administrative file to correct the problem; the whole repository may stay inaccessible until you do that.
Also, for security's sake, make sure your CVSROOT/ directory is only
writeable by users you trust (by
1.13 Commit EmailsThe loginfo file is how one sets up commit emails -- automated emails that go out to everyone working on a project whenever a commit takes place. (It may seem counterintuitive that this is done in loginfo instead of commitinfo, but the point is that one wants to include the log message in the email). The program to do the mailing -- `contrib/log.pl' in the CVS source distribution -- can be installed anywhere on your system. I customarily put it in the repository's CVSROOT/ subdirectory, but that's just a matter of taste. You may need to edit `log.pl' a bit to get it to work on your system, possibly changing the first line to point to your Perl interpreter, and maybe changing this line
to invoke your preferred mailer, which may or may not be named
The
1.14 Finding Out MoreAlthough this chapter tries to give a complete introduction to installing and administering CVS, I've left out things that are either too rarely used to be worth mentioning or already well documented in the Cederqvist manual. The latter category includes setting up the other remote access methods: RSH/SSH, kserver (Kerberos 4), and GSSAPI (which includes Kerberos 5, among other things). It should be noted that nothing special needs to be done for RSH/SSH connections, other than making sure that the user in question can log into the repository machine using RSH or SSH. If they can and CVS is installed on both client and server, and they have the right permissions to use the repository directly from the server machine, then they should be able to access the repository remotely via the :ext: method. Descriptions of certain specialized features of CVS have been deferred to later chapters, so they can be introduced in contexts where their usefulness is obvious. General CVS troubleshooting tips are found in Tips And Troubleshooting. Although it's not necessary to read the entire Cederqvist manual, you should familiarize yourself with it; it will be an invaluable reference tool. If for some reason you don't have Info working on your machine and don't want to print the manual, you can browse it online at http://durak.org/cvswebsites/doc/ or http://www.loria.fr/~molli/cvs/doc/cvs_toc.html.
This document was generated by Joey Hess on February, 11 2002 using texi2html |