Source code management with darcs: a first look 
I have been managing the
LectroTest project with the
monotone revision control
system. For the last few months, monotone has been undergoing some
growing pains that have made it less stable than I would like for everyday
use. Thus I thought that I would give
darcs a try.
I have been following the progress of darcs since it was first
announced on the Haskell-Cafe mailing list on 9 April 2003. Darcs is
written in
Haskell, one of my favorite programming languages, and
that was my initial draw. Still, until yesterday I had never
used it for any of my projects because I felt it was immature and
needed some more real-world testing before I committed work to it.
In the last three months, Darcs has gained mainstream attention
(triggered by a
favorable write-up in Linux Weekly News) and a growing user base. Under
the gaze of these new eyeballs, darcs has matured much. I thought it
was time for another look.
Darcs has a small, easy-to-understand command set and yet offers
"modern" source-code management features such as distributed
development (via HTTP, ssh, and email), change sets, and cherry
picking. Want to start an experimental branch of your project? Just
check out another copy and use it for the branch. Each working copy
is a complete, independent repo. Want to publish a project repository
to the world? Just copy it to a public web server. Want to start
working on someone else's project? A single "darcs get
http://other.project.com/project" gives you a complete, stand-alone
copy. Your own personal branch. Start hacking.
To try darcs on something I was familiar with, I decided manage my
LectroTest development with it. The first thing I did was change to
the LT working directory and use "darcs init" to create a darcs
repository there.
[tom@bifur Flippi]$ cd ~/work/research/perl/qc/ # LT root dir
[tom@bifur qc]$ darcs init
[tom@bifur qc]$ l
blib/ mt.db
_build/ mtdb.dump
Build* perl-Test-LectroTest-0.2007-1.src.rpm
Build.PL pod2htmd.tmp
Build.PL~ pod2htmi.tmp
buildrpm* posts/
buildrpm~ prop2.pl
Changes prop2.pl~
Changes~ README
checkpods* t/
checkpods~ Test-LectroTest-0.2001.tar.gz
ctime.pl Test-LectroTest-0.2002.tar.gz
ctime.pl~ Test-LectroTest-0.2003.tar.gz
CVS/ Test-LectroTest-0.2004.tar
_darcs/ Test-LectroTest-0.2004.tar.gz
Example1.pl~ Test-LectroTest-0.2005.tar.gz
lib/ Test-LectroTest-0.2006.tar.gz
Makefile.PL Test-LectroTest-0.2007.tar.gz
MANIFEST Test-LectroTest-0.2008.tar.gz
MANIFEST~ Test-LectroTest-0.2009.tar.gz
MANIFEST.bak Test-LectroTest-0.201.tar.gz
MANIFEST.SKIP tex/
MANIFEST.SKIP~ THANKS
META.yml THANKS~
monotone.db TODO
monotone.db.bak TODO~
monotone.db.pre-changesets toms-notes.txt
monotone.db-pre-sql3 toms-notes.txt~
MT/
You can see that there is a lot of accumulated cruft
in my working directory, including CVS, monotone, and
now darcs revision-control artifacts. To prevent
Perl's Module::Build from thinking the
_darcs
directory is meaningful, I added it to the manifest-skip file.
[tom@bifur qc]$ echo '\b_darcs\b' >> MANIFEST.SKIP
Next I added my LectroTest sources, docs, and related files
to the darcs repo.
[tom@bifur qc]$ darcs add Build.PL buildrpm Changes \
checkpods MANIFEST MANIFEST.SKIP tex THANKS TODO \
toms-notes.txt tex/Makefile tex/titlepage.ltxThe "darcs whatsnew" command asks darcs to tell me what is
changed in the working directory with respect to the repository
state.
[tom@bifur qc]$ darcs whatsnew -s
A ./Build.PL
A ./Changes
A ./MANIFEST
A ./MANIFEST.SKIP
A ./THANKS
A ./TODO
A ./buildrpm
A ./checkpods
A ./tex/
A ./tex/Makefile
A ./tex/titlepage.ltx
A ./toms-notes.txt
The files that I added are new because I had not yet recorded
them to the repository. Before I did that, I added the
remaining LT assets.
[tom@bifur qc]$ darcs add t # add the tests dir
[tom@bifur qc]$ darcs add t/*.t
[tom@bifur qc]$ darcs add lib
[tom@bifur qc]$ cd lib
[tom@bifur lib]$ l
Test/
[tom@bifur lib]$ darcs add Test
[tom@bifur lib]$ cd Test
[tom@bifur Test]$ l
LectroTest/ LectroTest.pm~ LectroTest::Tutorial.pod~
LectroTest.pm LectroTest.pm.bak
[tom@bifur Test]$ darcs add LectroTest LectroTest.pm
[tom@bifur Test]$ cd LectroTest
[tom@bifur LectroTest]$ l
Compat.pm Generator.pm~ Simple.pm~ Tutorial.pod
Compat.pm~ Generator.pm.bak Test.pm~ Tutorial.pod~
Compat.pm.bak Property.pm TestRunner.pm Tutorial.pod.bak
CVS/ Property.pm~ TestRunner.pm~
Generator.pm Property.pm.bak TestRunner.pm.bak
[tom@bifur LectroTest]$ darcs add *.pm *.pod
At this point, it looked like I had all of the files under
darcs's watchful eye.
[tom@bifur LectroTest]$ darcs w -s # abbreviated: w -> whatsnew
A ./Build.PL
A ./Changes
A ./MANIFEST
A ./MANIFEST.SKIP
A ./THANKS
A ./TODO
A ./buildrpm
A ./checkpods
A ./lib/
A ./lib/Test/
A ./lib/Test/LectroTest/
A ./lib/Test/LectroTest.pm
A ./lib/Test/LectroTest/Compat.pm
A ./lib/Test/LectroTest/Generator.pm
A ./lib/Test/LectroTest/Property.pm
A ./lib/Test/LectroTest/TestRunner.pm
A ./lib/Test/LectroTest/Tutorial.pod
A ./t/
A ./t/001.t
A ./t/002.t
A ./t/003.t
A ./t/004.t
A ./t/005.t
A ./t/compat.t
A ./tex/
A ./tex/Makefile
A ./tex/titlepage.ltx
A ./toms-notes.txt
[tom@bifur LectroTest]$ cd ../../.. # back up to project home
That looked right. It was time to record my changes.
This was straightforward.
[tom@bifur qc]$ darcs record --all # record all changes
Darcs needs to know what name (conventionally an email address) to use as the
patch author, e.g. 'Fred Bloggs <fred@bloggs.invalid>'. If you provide one
now it will be stored in the file '_darcs/prefs/author' and used as a default
in the future. To change your preferred author address, simply delete or edit
this file.What is your email address? Tom Moertel <tom@moertel.com>
What is the patch name? Initial checkin of sources
Do you want to add a long comment? [yn] nFinished recording patch 'Initial checkin of sources'
Now what did darcs think has changed?
[tom@bifur qc]$ darcs w -s
No changes!
Excellent.
One cool feature of darcs is that every working directory
is also a complete, independent repository. To make a branch,
then, is as simple as checking out a new repository.
Of course, because there is no central repository in the darcs model,
"checking out" is a concept that does not really apply. Rather, what
I must do is set up a new repository and then "push" my existing
repository's patches to it. I can push in many ways, including
via ssh to a remotely hosted repository, but here I will just set up
a new repo in /tmp and push to it on the local filesystem.
[tom@bifur qc]$ mkdir /tmp/lt && pushd /tmp/lt
/tmp/lt ~/work/research/perl/qc
[tom@bifur lt]$ darcs init # set up new repo at /tmp/lt
[tom@bifur lt]$ popd
~/work/research/perl/qc
[tom@bifur qc]$ darcs push /tmp/lt # push to repo at /tmp/ltSat Feb 12 01:26:15 EST 2005 Tom Moertel <tom@moertel.com>
* Initial checkin of sources
Shall I push this patch? (1/1) [ynWvxqadjk], or ? for help: yFinished applying...
Now, I can begin working on my new branch in the /tmp/lt working
directory.
[tom@bifur qc]$ cd /tmp/lt
[tom@bifur lt]$ l
Build.PL Changes _darcs/ MANIFEST posts/ tex/ TODO
buildrpm checkpods lib/ MANIFEST.SKIP t/ THANKS toms-notes.txt
[tom@bifur lt]$ emacs lib/Test/LectroTest.pm # fix typo
[tom@bifur lt]$ darcs record
hunk ./lib/Test/LectroTest.pm 38
-of your software. LectroTest then checks your software see whether
+of your software. LectroTest then checks your software to see whether
Shall I record this patch? (1/1) [ynWsfqadjk], or ? for help: yWhat is the patch name? Fixed stupid typo in intro text of T::LectroTest.pm
Do you want to add a long comment? [yn] nFinished recording patch 'Fixed stupid typo in intro text of T::LectroTest.pm'
Now my branch repository contains two patches:
[tom@bifur lt]$ darcs changes
Sat Feb 12 13:20:07 EST 2005 Tom Moertel <tom@moertel.com>
* Fixed stupid typo in intro text of T::LectroTest.pmSat Feb 12 01:26:15 EST 2005 Tom Moertel <tom@moertel.com>
* Initial checkin of sources
Because the typo that I fixed is not unique to my new branch, I ought
to make sure that the original branch gets the fix, too. To do so, I
just push it:
[tom@bifur lt]$ darcs push ~/work/research/perl/qc
Pushing to /home/thor/work/research/perl/qc...Sat Feb 12 13:20:07 EST 2005 Tom Moertel <tom@moertel.com>
* Fixed stupid typo in intro text of T::LectroTest.pm
Shall I push this patch? (1/1) [ynWvxqadjk], or ? for help: yFinished applying...
And now my patch has been pushed back up to the mainstream
branch!
This is an attractive development model.
So far, I like darcs. Its source code–management model is
simple and powerful. Its command set is small enough to actually
grok. Using darcs has me wondering why other SCM systems have made
the problem seem so complicated. My life is complicated enough as it
is.
I think I just switched to darcs.