====== 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 [[http://www.selenic.com/mercurial/|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:
#!/bin/csh
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
date: Wed Jan 09 18:57:24 2008 +0300
summary: - Add new files.
changeset: 309:937d50c4af02
user: Stanislav Sedov
date: Fri Nov 30 19:02:37 2007 +0300
summary: - Fix build.
changeset: 308:610151747720
user: Stanislav Sedov
date: Wed Nov 28 11:45:56 2007 +0300
summary: - Fix build.
changeset: 307:023d52500562
user: Stanislav Sedov
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
date: Tue Nov 27 21:40:58 2007 +0300
summary: - Branch merge.
changeset: 305:4724d224afe3
user: Stanislav Sedov
date: Tue Nov 27 02:53:22 2007 +0300
summary: Update master tree
changeset: 304:4d9fc65e6661
user: Stanislav Sedov
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 [[http://hgbook.red-bean.com/hgbook.html|Distributed revision control with Mercurial]] book also is
the great source of information about Hg.