CVS, the veteran workhorse
CVS, or Concurrent Versions System, was the de-facto standard open source version control system for a long time. It came up in the late 80s and grew popular enough to manage the source repositories of virtually all open source projects until only a few years ago (when Subversion started to take over). It's still widely used, including on drupal.org, but hardly deployed on newly created repositories anymore. Development is strictly fixed to a centralized client-server methology, and while distributed version control systems (or Subversion with svk) strive to make a checkout independent from the server, with CVS you're completely dependent on a fast and reliable connection to upstream.
In summary, there's little surprises in this CVS coverage, especially for the resident drupal.org admins. But necessary nevertheless, if only for later reference. Obviously, no new requirements for the API module were found, as the CVS setup on drupal.org together with the Project module is the status quo at the moment.
Basics
CVS offers the standard operations that you would expect from a version control system: checkout, add, delete, diff, status, log, annotate, commit and friends. It versions files, but not directories, and it doesn't store symlinks as such. Files can be moved by deleting and re-adding them in their new location, but previous history is lost for the new file, or it has to be moved directly on the server. When merging from other branches (possible with the '-j' option), the history of changes in that branch is lost as well. Little more than the file contents themselves are stored in the working copy, so for each diff and revert operation (and of course, log and annotate), the developer has to connect to the server.
There are no atomic commits, so no global revision identifiers either, CVS only knows about single files. In order to revert to a previous state of the whole repository, you can still pass the date when a revision was committed. File revisions follow a logical numbering scheme: they start at "1.1" for the initial commit, then go up to "1.2", "1.3" and so on, in case no branches are made. When a branch is created, subsequent revisions to the 1.2 version of the file will be named 1.2.2.x (for the first branch), 1.2.4.x (for a second branch), etc.
This means that you can derive all previous revision numbers just by looking at the current one, but it also means that you're advised not to regularly branch off of branches (like, starting DRUPAL-6 from DRUPAL-5) or you'll get ridiculously long revision numbers.
Branching, tagging, and file structure
CVS does both branching and tagging natively. In fact, a branch is just a special case of a tag, and it's also presented this way. So when files are marked with a "sticky tag" by 'cvs status', those are actually branches. Both can be deleted or renamed, but in practice this functionality is hardly used because it's cumbersome and error-prone. Branches and tags are normally assigned to files and directories, but there's also an 'rtag' command which can manage repository-wide ones.
Once a file is added, it exists in every branch, and is not supposed to go away anymore. In branches where they should not be visible (or when they have been deleted), those files are said to reside in the "Attic", and thus are in a hidden state.
Like Subversion, a CVS repository is one single directory tree with internal subdivisions for different projects. Those subdivisions are explicitely marked, and are called "modules". With both branches and tags supported by CVS, there's no standard conventions on the directory layout; specifically, there's no need to introduce additional directory structures like SVN's trunk/, branches/ and tags/.
Authentication and hook scripts
Authentication in CVS can be done by various means (including rsh and Kerberos), but the most common one is to use cvs' built-in password server - the one which makes for the ":pserver:" prefix to your checkout path. When using the pserver method, the admin specifies the list of users and their (encrypted) passwords with a configuration file. If users are not present in this configuration file, CVS can optionally fall back to system authentication. The downside of all authentication methods in CVS except the Kerberos one is that the password can easily be retrieved by sniffing the network traffic - pserver just uses obfuscated passwords for remote connections, without real, effective encryption.
A set of hook scripts (together with specific configuration files) can be provided in order to do verification of commit access, commit messages and tag names before allowing the commit to be executed. One can also have notification and logging with a few more scripts. Those commit hooks are quite capable and make it possible for drupal.org to restrict branch and tag creation, or capturing commit info directly in the MySQL database.
In other news
I have finally taken the time to inspect Mercurial. Expect another posting in this fashion soon (including at least one new finding that could influence the API). No changes in the code this time.



...oh, and before it's pointed out again
cvs.module has a workaround for the lack of global revision identifiers, it introduced its own commit ids. So the reason that you can still view all the commits on http://drupal.org/cvs in a per-commit fashion is a bit of work behind the scenes that cvs.module puts on top of the actual CVS.