Using mercurial for local FreeBSD development
For a long time The FreeBSD project used CVS as its version control system almost exclusively. Recently a number of more sophisticated version control systems were developed, and it's becoming quite common that the developer uses something other than CVS for local development work. It was shown over years that using CVS for big long-term work on FreeBSD source code, especially when it should be constantly synced with the main FreeBSD repo, can become a major pain. That's why, in part, the FreeBSD projects provides access to a Perforce repo to work on FreeBSD related projects.
This tiny tutorial shows how one can configure and use Mercurial to do his local development work in FreeBSD repo, while keeping in sync with the main development tree.
Checking out the source code
One of the most handy ways to obtain the FreeBSD source code is to use CVSup. This program uses sophisticated algorithms to efficiently transfer a large number of file over network. These also were specifically optimizes to use with CVS, so it tries to transfer deltas, not entire files, whenever possible.
You can find more information about CVSup in the FreeBSD Handbook.
For example, I use the following supfile to keep in sync with the FreeBSD repo.
*default host=CHANGE_THIS.FreeBSD.org *default base=/var/db/mercurial-cvsup/ *default prefix=/usr *default release=cvs tag=. *default delete use-rel-suffix src-all tag=. prefix=/work/src/mercurial/fbsd-src-HEAD src-all tag=RELENG_7 prefix=/work/src/mercurial/fbsd-src-RELENG_7 src-all tag=RELENG_6 prefix=/work/src/mercurial/fbsd-src-RELENG_6 src-all tag=RELENG_5 prefix=/work/src/mercurial/fbsd-src-RELENG_5 src-all tag=RELENG_4 prefix=/work/src/mercurial/fbsd-src-RELENG_4 ports-all tag=. prefix=/work/src/mercurial/fbsd-ports
In this configuration all source files will be placed under /work/src/mercurial/. I use separate Mercurial repos for different FreeBSD branches, though you can probably use native Hg branches for this. I discovered that keeping different repositories works better for me as it's much lesser error probability and doesn't impact the speed much (if it does it at all).
Creating Mercurial repository
After obtaining the source you have to initialize Hg repository for the first time. It's very simple, luckily enough. Just enter into the each of repository folders, e.g. /work/src/mercurial/fbsd-src-HEAD from the above, and type the following commands:
% hg init # will create .hg folder and initialize its contents % hg add # will schedule all new files for the addition % hg forget .svn # Will ignore subversion housekeeping files % hg commit -m 'Initial import of the FreeBSD tree'
After that all downloaded source code will be managed by Mercurial. If you need to ignore some files, use .hgignore(5) file for this.
Keeping repositories in sync
Obviously, you want to be in sync with the main FreeBSD development tree. In fact, it's not harder than creating the repo.
To update your repository you need to perform the following steps:
- Retrieve the fresh source code with the supfile you used in the previous step
Enter to the repository's directory and execute the following commands:
% hg addremove # will schedule new files to the addition and all nonexistent for removal % hg commit -m 'Update from upstream'
You can perform these steps from cron(8) to update your repos e.g. once a day. For example, I use the following script to do this:
set HG=/usr/local/bin/hg set CSUP='/usr/bin/csup -L0' set SUPFILE=/home/stas/mercurial-supfile set BRANCHES=(fbsd-ports fbsd-src-RELENG_7 fbsd-src-RELENG_6 \ fbsd-src-RELENG_5 fbsd-src-RELENG_4 fbsd-src-HEAD) set REPOPATH=/work/src/mercurial echo $BRANCHES # # Update sources via CVSUP # ${CSUP} ${SUPFILE} if ($status != 0) then echo "Error occurred during update" exit 1 endif # # Add and commit changes into mercurial repo # foreach branch (${BRANCHES}) cd ${REPOPATH}/${branch} && ${HG} addremove && ${HG} ci -m 'Update from upstream' end
Performing local development work on the repositories
This is what we have done all the previous steps for.
Mercurial is the true distributed VCS and encourages the use of separate repository for the every project you work on. In fact, the repository clone operation is very fast and cheap - Mercurial uses copy-on-write technology to avoid unnecessary copies.
For example if you're going to do some work on the Project1 for the FreeBSD HEAD you start by creating the corresponding repository:
% hg clone /path/to/repo/fbsd-src-HEAD fbsd-HEAD-project1
After that you can safely use fbsd-HEAD-project1 for all project1-related development work, commit changes, rollback them, view the history. Refer to the Hg documentation to learn more about Mercurial and it's abilities.
In case if you need to merge with the recent HEAD after some time, you can easily do that:
% cd /path/to/fbsd-HEAD-project1 % hg pull /path/to/repo/fbsd-src-HEAD % hg merge
resolve conflicts, etc
% hg commit -m 'Merge upstream'
You can do that whenever you want without any consequences. Mercurial keeps the history of merges, so you won't receive suspicious conflicts. Furthermore, after the merge operation Hg will integrate all the history from the merged tree into your tree, so you'll be able to easily check the difference between your tree and the main tree. Suppose, for example, after some development you've received the following:
changeset: 310:d44952c166fd tag: tip user: Stanislav Sedov <stas@FreeBSD.org> date: Wed Jan 09 18:57:24 2008 +0300 summary: - Add new files. changeset: 309:937d50c4af02 user: Stanislav Sedov <stas@FreeBSD.org> date: Fri Nov 30 19:02:37 2007 +0300 summary: - Fix build. changeset: 308:610151747720 user: Stanislav Sedov <stas@FreeBSD.org> date: Wed Nov 28 11:45:56 2007 +0300 summary: - Fix build. changeset: 307:023d52500562 user: Stanislav Sedov <stas@FreeBSD.org> date: Tue Nov 27 23:17:43 2007 +0300 summary: - Add forgotten file. changeset: 306:af6c5a6c4ff4 parent: 235:28745515f10e parent: 304:4724d224afe3 user: Stanislav Sedov <stas@FreeBSD.org> date: Tue Nov 27 21:40:58 2007 +0300 summary: - Branch merge. changeset: 305:4724d224afe3 user: Stanislav Sedov <stas@FreeBSD.org> date: Tue Nov 27 02:53:22 2007 +0300 summary: Update master tree changeset: 304:4d9fc65e6661 user: Stanislav Sedov <stas@FreeBSD.org> date: Mon Nov 26 02:52:57 2007 +0300 summary: Update master tree
Now you can get the diff between the main tree as on Tue Nov 27 and your last revision by using the following command:
% hg diff -r 305 -r tip
Statistics
- 629M fbsd-ports
- 659M fbsd-src-HEAD
- 481M fbsd-src-RELENG_4
- 568M fbsd-src-RELENG_5
- 600M fbsd-src-RELENG_6
- 657M fbsd-src-RELENG_7
Additional info
For additional information about Mercurial refer to the included manual pages. The Distributed revision control with Mercurial book also is the great source of information about Hg.