Importing and tracking vendor source

CVS has special capabilities for tracking local modifications to vendor source. What that means is that you can put the source tree of a package, as downloaded off the net or received from the vendor, into CVS, make modifications to it like any other set of files in CVS, and then when the next version comes out, have CVS merge your changes into the new version automatically for you.

It's possible to do this on a small scale using diffs and patch, but it's much more difficult for patch to figure out how to apply changes to a new version since it doesn't have as much context. CVS is capable of doing a full three-way merge and detecting conflicts, which makes it much more reliable and powerful for this feature.

Minor modifications to vendor source, like installation directories and minor compile fixes, are probably best kept as simple patches to avoid having to import mostly unchanged vendor source into CVS. If we make any extensive local modifications, however, it's best to use these facilities of CVS to make updating to newer releases easier down the road.

In the following, I'll use as an example the Kerberos V5 sources.

For the initial import, decide what the path in the repository to the source will be (see the other CVS documentation to help decide this, or talk to me) and then enter a command like:

    cvs import -m "Import of MIT Kerberos V5 1.0.6" kerberos/krb5 \
        MIT KRB5-1_0_6

This will input a tree of files starting at the current directory, so it should be run from the top level directory of the untarred source tree.

You may want to add the -I! flag to the import command (right before the -m flag, after the word import) if the vendor tree contains files that would normally be ignored by CVS. That makes sure that you import the entire tree. (Note that ! is a special character for csh shells and has to be written \! if you're using a csh-derived shell.)

The first argument (after the -m) is a comment and should probably be something like the above (with the right vendor and product name, obviously). The next argument is the repository path; in this case, the krb5 directory under the kerberos top-level directory. The third argument is the vendor, which should be the organization producing the sources in all caps. (For free software products from individual people, I usually use their last name; for GNU software, I use FSF. As long as you're consistent, it doesn't matter that much.) The final argument is the specific version that you're importing; I usually use a short version of the product name, a dash, and the version number with periods replaced by underscores.

Note that tags can consist of numbers, letters, -, and _. No other characters should be used, and by convention tags are normally in all caps. Period in particular isn't allowed; replacing it with _ is the most common approach.

After running the above command, you have a copy of Kerberos V5 in the repository. You can then check out that copy somewhere and start working on it. Note that the directory from which you do the import does not turn into a working copy of the source; you can't immediately start doing commits. You need to check out a working copy with the normal CVS checkout commands and then work on that copy. In this case, that command would be:

    cvs checkout krb5

since there's a krb5 module corresponding to the kerberos/krb5 repository path.

With the checked out copy, you can do commits as normal, just like with any other CVS tree.

When the time comes to update to a newer release of the vendor source, start by running another import in the top level of the untarred source tree of the new version. In other words, for release 1.1, you'd do:

    cvs import -m "Import of MIT Kerberos V5 1.1" kerberos/krb5 \
        MIT KRB5-1_1

after untarring. (Remember to double-check what part of the tree is actually in the repository; for example, for krb5, we only import the src tree and not the doc tree. You don't want to import from a level higher in the directory structure than from when you imported the last time.)

The import command will warn you of any merging of local changes that's necessary. To do that merge, you'll do a checkout into a temporary directory. For example, to do a merge between the current krb5 tree and the just-imported 1.1 sources from above, checking out the tree into a temporary directory named krb5, use:

    cvs checkout -jMIT:yesterday -jMIT krb5

(this uses the fact that krb5 is a module name; if you don't have a module name, you'd need to use the full path of kerberos/krb5 here, and you may want to specify the temporary directory used with -d). If any conflicts show up, CVS will warn about them, they should be resolved in the normal fashion. Any files that contain merges will then need to be committed; use cvs update to see where the conflicts and modified files are.

Note that this takes advantage of the fact that the previous vendor source was the most current version as of yesterday; that way, you don't have to use the specific version tags. If you import more than one vendor version in one day, or if you just want to be more precise, you can instead do:

    cvs checkout -jKRB5-1_0_6 -jKRB5-1_1 krb5

Finally, if the vendor source contains RCS keywords like $Id$ or the like, that will cause all sorts of conflicts during the merge. To get around that, add the -ko flag to the import command. This preserves the RCS keywords that were in the original imported files, rather than replacing them with version numbers from your local CVS repository. This is useful if the original author was using RCS identifiers as version strings.

Last modified and spun 2014-08-17