of historical interest only.
This page describes the FreeBSD Subversion to CVS exporter AKA svn2cvs.
The exporter runs on repoman.FreeBSD.org (mostly) in the directory /r/svn2cvs/.
Currently the page is work in progress and should not be relied on to be accurate!
Contents
svn2cvs overview
The basic purpose of the FreeBSD svn2cvs system is to replicate commits in the FreeBSD Subversion repository to the old CVS repository. svn2cvs preserves full commit information (as much as CVS allows) by exporting:
- commit actually change content
- commit comment
- commit date / time
- commit author
- svn revision number (in the CVS commit comment)
svn2cvs exporter basically works by examining each subversion commit and then replicating it as good as possible into CVS.
Due to the way CVS works $FreeBSD$ is changed by CVS so the original $FreeBSD$ set by Subversion is overwritten by CVS. To find out which Subversion revision a file in CVS is based on, one has to see the commit log which includes the revision ID.
svn2cvs parts
svn2cvs consists of the following parts:
The main svn2cvs python script export.py
- A counter stored as a SVN property telling the exporter the last SVN revision exported
A mapping table (called maptable and stored in export.py) which maps from SVN to CVS branches (IE, stable/7 -> RELENG_7)
- Modified version of cvs
- Local FreeBSD svn mirror updated every 5 seconds
- Checked out version of each active CVS branch
Python 'export.py' script
TODO - Location (repo stored in, public access, etc...) and dependancies
Last exported revision property
The counter with the last exported revision is stored as a revision property stored on revision 0 and is called fbsd:lastexp. Note that the property is stored on the mirrored repository used by the exporter, not the main FreeBSD repository. The current value for /r/svnmirror/base can be retrieved using:
svn pg fbsd:lastexp --revprop -r 0 file:///r/svnmirror/base
maptable
TODO
Modified CVS
The modified version of CVS is changed from stock CVS as follows:
If the environment variable CVS_TIMESTAMP is set, use that as the commit time-stamp instead of the current 'wall clock'.
If the environment variable CVS_AUTHOR is set, use that to set author in CVS commit instead if the actual user which are performing the commit action (svn2cvs)
- Do not allow 'cvs imports' to be run on the 'ncvs' repository.
All the changes to the CVS repository is done with the modified cvs binary so there is no "magic" manipulation of the CVS repository.
Local FreeBSD svn mirror
TODO - setup, why needed, etc...
Create branch checklist
XXX This may _very_ well miss required steps!
Make sure maptable contains the new branch.
Create the branch in CVS e.g. using cvs tag -b RELENG_9 - XXX svn2cvs should actually handle it by itself
- Perform the branch in svn.
How svn2cvs works, per commit
TODO
Caveats
Manual CVS work
If the CVS repository is every updated directly for whatever reason, the checkouts used by svn2cvs must also manually be updated. Otherwise, on the first export to the directory containing the manually modified files, the export will fail with an CVS up-to-date-check.
To recover from this situation, simply manually (as user svn2cvs) run cvs update in the affected directory, and revert the changes made for the export which fails. Now the exporter can be restarted.
Current problems
It doesn't like when a file is 'replaced' in Subversion.
As of this writing no files are out of sync.
Tips
The following command can be used to get all commits to a branch e.g. for hand exporting:
svn log --xml --stop-on-copy file:///r/svnmirror/base/releng/9.1 | xmllint --format /dev/stdin | awk -F\" '/<logentry revision="/ { print $2 }' | sort -n | awk '{ printf "echo \"Press enter to export r%s\"\nread line\npython export.py -r %s\n", $1, $1 }'
Simon's original suggestion:
svn log --xml --stop-on-copy file:///r/svnmirror/base/releng/9.1 | xmllint --format /dev/stdin | grep 'logentry revision' | sed -Ee 's/.*revision="(.*)">.*/\1/' | sort