Darcs — The source code management system of the future?

Dec 29 2006

Hav­ing already men­tioned some good prac­tices for source code ver­sion­ing and how impor­tant ver­sion­ing is, in any case, I would like now to review and com­ment about what I find the best source code man­age­ment sys­tem out there: darcs.

Darcs is a source con­trol sys­tem writ­ten in Haskell (a func­tional lan­guage), and fea­ture very solid math­e­mat­ics bases, being com­pletely enge­neered on top of a “patch the­ory”. Not only darcs is straight­for­ward and very easy to you, not only it’s very inter­ac­tive and min­i­mizes the chances of mis­takes, but it also gives out fea­tures that the pop­u­lar SVN doesn’t have. Here I’m going to show some use cases, and show how things are eas­ier with darcs.

A brief start up

Before ana­lyz­ing the key fea­tures, let’s have a brief start-up quick tuto­r­ial. The eas­i­est way to get darcs, is to down­load a binary pack­age. These pack­ages con­tain a pre­com­piled release of darcs, with every­thing needed sta­t­i­cally linked inside. You only need o copy that some­where in your $PATH, such as /usr/bin, /usr/local/bin, or what­ever you have in your $PATH. Of course you can down­load the source code and build it your­self if you want.

Let’s now cre­ate a sim­ple Hello World project, and use darcs to ver­sion it.

$ mkdir $HOME/projects/HelloWorld
$ cd !$
$ darcs init

darcs init will cre­ate all the files nec­es­sary to source-control the code. You will find a new direc­tory named _darcs.

Now we can write our HelloWorld.cc main file:

#include <iostream>

using namespace std;

int main(void) {
    cout << "Hello World!"<< endl;
}

Time to add the file to ver­sion control.

$ darcs add HelloWorld.cc

Alright, now we really get into darcs. First of all, in case you didn’t notice, darcs doesn’t really need any server at the other end, like SVN would need an SVN server, or CVS would need a CVS server. This means no has­sle in installing and con­fig­ur­ing a server. Later we will see how darcs man­ages col­lab­o­ra­tion with remote users.

Now it’s time to save our changes to the repository.

$ darcs record
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?
Salvatore Iovene <salvatore@invalid.com>
addfile ./HelloWorld.cc
Shall I record this change?(1/?)[ynWsfqadjkc], or ? for help: y
hunk ./HelloWorld.cc 1
+#include <iostream>
+
+using namespace std;
+
+int main(void) {
+	cout << "Hello World!" << endl;
+	return 0;
+}
+
Shall I record this change?(2/?)[ynWsfqadjkc], or ? for help: y
What is the patch name? First record.
Do you want to add a long comment? [yn] n
Finished recording patch 'First record.'

Some points worth inspec­tion here:

  • Why did darcs what to know my email address? That’s because every­thing you com­mit (they are named patches) will be known as com­ing from you. If you’re work­ing with sev­eral peo­ple, darcs has to know who is com­mit­ting what. Fur­ther­more, peo­ple down­load­ing your repos­i­tory can, e.g. make some changes and improve­ments, and then issue a darcs send which will send you the patch via email, and you can eval­u­ate it and decide if apply it.
  • What is a hunk?hunkis a piece of a patch, i.e. a cer­tain mod­i­fi­ca­tion in some source file. If you have a large file, foo.c, and mod­ify a cer­tain func­tion bar() at the begin­ning of the file, and then a cer­tain other func­tion tar() at the end of the file, this will result in two hunks. What’s the advan­tage of all this? Since darcs is so inter­ac­tive, you may decide to either apply both hunks in the same pathc, so answer ‘y’ to both, or real­ize that they log­i­cally belong to two dif­fer­ent patches, so you will say ‘y’ to one of them, and ‘n’ to the other. Then, after fin­ish­ing record­ing the first patch, you issue a darcs record again, and record the other hunk in a sep­a­rate patch, with a sep­a­rate name, that forms a log­i­cal unit per se.

Now let’s make a small change.

#include <iostream>

int main(void) {
    std::cout << "Hello World!" << std::endl;
}

As you can see, we have removed the using namespace std; dec­la­ra­tion, and added the std:: name­space pre­fix to cout and endl. A very impor­tant darcs com­mand is whatsnew, that shows us how the code dif­fers from the repository.

There are two hunks, as expected. Let's record the changes.

$ darcs record
hunk ./HelloWorld.cc 3
-using namespace std;
-
Shall I record this change?(1/?)[ynWsfqadjkc], or ? for help: y
hunk ./HelloWorld.cc 4
-	cout << "Hello World!" << endl;
+	std::cout << "Hello World!" << std::endl;
Shall I record this change?(2/?)[ynWsfqadjkc], or ? for help: y
What is the patch name? Removing the std namespace \
declaration.
Do you want to add a long comment? [yn]n
Finished recording patch 'Removing the std namespace
declaration.'

Obvi­ously those two hunks must form one sin­gle patch, because we don’t want any patch to leave the repos­i­tory in a bro­ken state. Now we get to the cool stuff. Darcs lets you unrecord your changes, i.e. inter­ac­tively roll­out the patches until you are sat­is­fied. We might change our mind about the last patch, and think that using namespace std; is not tha bad after all. No problem.

$ darcs unrecord

Fri Dec 29 12:53:32 EET 2006
Salvatore Iovene <salvatore@invalid.com>
* Removing the std namespace declaration.
Shall I unrecord this patch?(1/2)[ynWvpxqadjk], or ? for help: y

Fri Dec 29 12:37:33 EET 2006
Salvatore Iovene <salvatore@invalid.com>
* First record.
Shall I unrecord this patch?(2/2)[ynWvpxqadjk], or ? for help: n
Finished unrecording

Now there we are again, back as if noth­ing happened.

Imag­ine you want to have a copy of your repos­i­tory, maybe on a dif­fer­ent par­ti­tion of your disk, or maybe on a USB stor­age drive:

$ cd ..
$ mkdir RepoCopy
$ cd RepoCopy/
$ darcs init
$ darcs pull ../HelloWorld/

Fri Dec 29 12:37:33 EET 2006
Salvatore Iovene <salvatore@invalid.com>
* First record.
Shall I pull this patch?(1/1)[ynWvpxqadjk], or ? for help: y
Finished pulling and applying.

Another direc­tory is not the only way you can move your repos­i­tory around, you can use SSH to copy it to another machine, and HTTP to fetch it. This is actu­ally the way you han­dle col­lab­o­ra­tion. Imag­ine you have a server some­where, named www.server.com, and there you want to have your cen­tral repos­i­tory, with which you can col­lab­o­rate with your devel­op­ment peers.

$ darcs push \
username@www.server.com:/var/www/htdocs/HelloWorld/repo

This will ask you which patches you want to push to that server, one by one, in the usual darcs inter­ac­tive mode. I’m assum­ing that the direc­tory /var/www/htdocs/HelloWorld/ on the server, hosts the http://www.server.com/HelloWorld/ web­site. Every­body can now get a copy of your project just by doing this:

$ darcs get http://www.server.com/HelloWorld/repo

And any­body with an account on that server, will be able to push patches, if they of course have write per­mis­sion to the direc­tory where the repos­i­tory is.

Where to go from here

Here fol­low some must-read links if you’re inter­ested in darcs. Prob­a­bly in the future I will write more about it. Thanks for reading.

4 responses so far

  1. […] I have already given a brief intro­duc­tion to the Darcs source con­trol sys­tem, and I would like here to talk about a very strong point it’s got against SVN. […]

  2. […] Ver­sion­ing sys­tems like CVS, SVN or Darcs are very impor­tant tools, that no seri­ous pro­gram­mers can omit to use. If you started a project with­out using any ver­sion­ing tools, I really rec­om­mend that you start using one imme­di­ately; but I’m not dis­cussing this right now. […]

  3. […] Inspired by a cer­tain patch that hit a darcs repos­i­tory to which I con­cur, I would like to talk about one thing that devel­op­ers don’t seem to get very often, when using revi­sion con­trol sys­tems: the struc­ture of your files in the repos­i­tory should have noth­ing to do with the log­i­cal units that make your patches, or with the com­ment of your patches themselves. […]

  4. Thank you for the post, I am very inter­ested and was won­der­ing if any­one else had any other related arti­cles they could sug­gest. I enjoy writ­ing arti­cles myself and would like to gather as much infor­ma­tion as I can.

Leave a Reply