VCP::Source::cvs - A CVS repository source
vcp cvs:module/... -d ">=2000-11-18 5:26:30" <dest>
# All file revs newer than a date/time
vcp cvs:module/... -r foo # all files in module and below labelled foo
vcp cvs:module/... -r foo: # All revs of files labelled foo and newer,
# including files not tagged with foo.
vcp cvs:module/... -r 1.1:1.10 # revs 1.1..1.10
vcp cvs:module/... -r 1.1: # revs 1.1 and up on main trunk
## NOTE: Unlike cvs, vcp requires spaces after option letters.
Source driver enabling "vcp" to extract versions form a cvs
The source specification for CVS looks like:
or optionally, if the "CVSROOT" environment variable is set:
The cvsroot is passed to "cvs" with cvs' "-d" option.
The filespec and <options> determine what revisions to extract.
"filespec" may contain trailing wildcards, like "/a/b/..."
to extract an entire directory tree.
If the cvsroot looks like a local filesystem (if it doesn't start with
":" and if it points to an existing directory or file), this module
will read the RCS files directly from the hard drive unless --use-cvs is
passed. This is more accurate (due to poor design of the cvs log command) and
much, much faster.
- Used to set the CVS working directory. VCP::Source::cvs will cd to this
directory before calling cvs, and won't initialize a CVS workspace of it's
own (normally, VCP::Source::cvs does a "cvs checkout" in a
This is an advanced option that allows you to use a CVS workspace you
establish instead of letting vcp create one in a temporary directory
somewhere. This is useful if you want to read from a CVS branch or if you
want to delete some files or subdirectories in the workspace.
If this option is a relative directory, then it is treated as relative to
the current directory.
Pass the CVS -k options through to the underlying CVS command.
- Pass the -kb option to cvs, forces a binary checkout. This is useful when
you want a text file to be checked out with Unix linends, or if you know
that some files in the repository are not flagged as binary files and
Passed to "cvs log" as a "-r" revision specification.
This corresponds to the "-r" option for the rlog command, not
either of the "-r" options for the cvs command. Yes, it's
confusing, but "cvs log" calls "rlog" and passes the
- Do not try to read local repositories directly; use the cvs command line
interface. This is much slower than reading the files directly but is
useful to see if there is a bug in the RCS file parser or possibly when
dealing with corrupt RCS files that cvs will read.
If you find that this option makes something work, then there is a
discrepancy between the code that reads the RCS files directly (in the
absence of this option) and cvs itself. Please let me know
-d "2000-11-18 5:26:30<="
Passed to 'cvs log' as a "-d" date specification.
WARNING: if this string doesn't contain a '>' or '<', you're probably
doing something wrong, since you're not specifying a range. vcp may warn
about this in the future.
see "log" command in cvs(1) man page for syntax of the date
CVS has one peculiarity that this driver works around.
If a file does not contain the tag(s) used to select the source files, "cvs
log" outputs the entire life history of that file. We don't want to
capture the entire history of such files, so VCP::Source::cvs ignores any
revisions before and after the oldest and newest tagged file.
CVS allows branches to be tagged with multiple tags using a command like
cvs admin second_branch_tag:branch_tag
When VCP::Source::cvs notices this, it creates multiple branches with identical
revisions. This is done by choosing the first branch tag for the branches to
be the primary branch and applying all actual changes to it then
"clone"ing each revision from that branch to all others.
For instance, if file foo is branched once in to a branch tagged with
"bar" and later a "goof" tag is aliased to the
"bar" tag, then
trunk branch bar branch goof
======= ================ ==================
This is EXPERIMENTAL and it's likely to give VCP::Dest::cvs fits. It is tested
with CVS->p4 transfers.
If you only want the primary branch, you may use a Map: section in the .vcp file
to discard non-primary branches:
Currently, there is no way to ignore the primary branch other than getting rid
of that branch tag in the RCS files or hacking VCP::Source::cvs's source code
to ignore it.
(EXPERIMENTAL) It's possible somehow (I've never done it) to set the state on
edited revisions to "dead", which may result in a series of
revisions all marked "dead". CVS, at least older versions, deleted a
file by marking the head rev as state "dead" instead of adding a new
revision. So a dead revision is both an edit and a deletion. I am not sure
whether the metadata on the rev refers to the time and user that committed the
edit, or the time and user that committed the delete.
VCP::Source::cvs detects consecutive "dead" revisions and
"dead" revisions that are also edits and issues a normal
"edit" revision followed by a concocted "delete" revision
with a ".0" appended to the rev_id.
Stores all revisions for a file in RAM before sending so it can link all the
revisions properly. Also stores all branch parents and the first revision on
every branch for all files scanned so it can insert placeholders for branches
with no revs. Except for these branch point revisions, all other revs for each
file are sent before the next file is scanned.
TODO: just send placeholders for all branches that match the filespec and
Does not yet set the same time in all branch creation revisions. This may be
necessary in order to help the changeset aggregator. It will probably take
buffering all branch revs before sending them on. Also, it is not possible in
the general case: not all files on a branch are actually branched from parents
that are checked in before the first file on a branch is created. It also
makes no sense to do this for untagged branches as there is no detectable
semantic association between untagged branches.
CVS does not try to protect itself from people checking in things that look like
snippets of CVS log file: they come out exactly like they went in, confusing
the log file parser. So, if a repository contains messages in the log file
that look like the output from some other "cvs log" command, things
will likely go awry when using remote repositories (local repositories are
read directly and do not suffer this problem). The direct RCS file parser does
not have this problem.
CVS stores the -k keyword expansion setting per file, not per revision, so vcp
will mark all revisions of a file with the current setting of the -k flag for
At least one cvs repository out there has multiple revisions of a single file
with the same rev number. The second and later revisions with the same rev
number are ignored with a warning like "Can't add same revision
The xfree86 repository has several files
1.2 dead lines +1, -1
1.1 Exp lines
184.108.40.206 Exp lines +1, -1
220.127.116.11 Exp lines +1, -1
In this case, VCP::Source::cvs doesn't know how to retrieve rev 1.2 to create
the branch 1.2.2.x, so it uses 1.1. If you know how to force it to get rev
1.2, please let me know (in the future, the RCS parser will allow this, but
currently we always use cvs checkout to retrieve versions). I'd like to know
how to use the cvs command to modify a revision and then force it to the dead
state without upping the revision number, as that appears to have happened
here. I suspect something other than the cvs command at play here, like the
rcs command or RCS file editing by hand or by script
VCP::Dest::cvs, vcp, VCP::Process.
Barrie Slaymaker <firstname.lastname@example.org>
Copyright (c) 2000, 2001, 2002 Perforce Software, Inc. All rights reserved.