darcs is becoming my favorite VCS

2007-10-26 02:42:26 UTC

Here’s a real-world situation that tells you why I’m falling in love with darcs.

I’m working on a plug-in that logs all notifications posted by Apple Mail to a couple of files. The idea of this plug-in is to enable Mail-bundle developers to develop more reliable plug-ins by listening for notifications rather than posing as Mail’s classes or swizzling its methods.

(As you know, I don’t ordinarily announce what I’m working on before it’s ready; for this post, it’s important to provide context.)

The first revision of the plug-in used NSLog, but I found that this spammed console.log rather heavily. So I changed it to use two separate log files, which I write to using NSFileHandles.

Then I started work on a new feature: datestamps. While working on that, however, I noticed that I had forgotten to close and release my two file handles in -dealloc. Oops.

Now, remember that I had local changes. If this code were versioned in svn, I would have to:

  1. bzip2 the source file (which renames it as a side-effect).
  2. svn up the file in order to restore the pristine copy.
  3. Open it in a separate editor (so as not to lose undo history) and add the closeFile and release messages that I’d forgotten.
  4. Save and exit.
  5. Commit.
  6. Delete the committed file and bunzip2 my original one.
  7. Go through an svn diff and redo the fix in my modified file so I don’t clobber the changes in my next commit.

What a hassle. But darcs has first-class support for just this situation.

All I had to do was darcs amend-record. darcs asked me whether the most recent commit was the one I wanted to amend, then it offered me the choice of which hunks of local changes I wanted to include in the amendment. I said yes to the one with the closeFile and release messages and no to all the others. That’s all I had to do.

Let me summarize that for you: I was able to retroactively fix my previous commit while I had other local changes in the same file, without sweeping up those other changes into the commit.

That’s awesome.

10 Responses to “darcs is becoming my favorite VCS”

  1. ssp Says:

    The versioning system may be great for your purposes. But if you end up using it, please make sure that it still remains feasible for people who don’t have it installed to play with your code.

    I’ve run into the situation where I found a project I was interested in a number of times but it was using some strange/new/hyped/stupid versioning system and offered that as the only way to access the files (plus some file-by-file HTML formatted version perhaps). This raised the level of inconvenience for actually accessing the source to locating, installing, (quite possibly kicking and screaming in the process) that software and learning enough to use it. All that just to download a few files. Which, of course I didn’t do.

    So if you want to use an exotic versioning system (or in fact any versioning system), please make sure there is also a convenient one-click link that downloads an archived version of the source. It seems very simple, but loads of sites just don’t do that.

    All that only if you are interested in actually publishing your work of course.

  2. Peter Hosey Says:

    ssp: Agreed. If your VCS of choice is the only way for other people to get your source, you fail, and the test will be terminated. A tarball or zip archive is mandatory (unless your app is closed-source, of course). darcs makes this easy: Use the darcs dist command.

    I wouldn’t exactly call darcs new nor hyped. The project has been around since at least 2004. It is a bit strange/exotic, though: It’s written in Haskell, and it’s the least Subversion-/CVS-like of all the DVCSs. (Bazaar, at the other extreme, is the most SVN-like.)

    That said, I’m growing to love it, precisely because of the features that it offers that other DVCSs don’t (as far as I know). Besides the amend-record command, its second and third coolest features are:

    • darcs send, which emails the patch to the repository’s maintainer. Yes, that’s right: First-class support for submitting patches by email. The converse command is darcs apply, which applies patches from an email sent using darcs send.
    • darcs dist, mentioned above.
  3. dave glasser Says:

    It’s a shame that darcs combines some great usability features like this one and a solid conceptual basis with some other serious UI problems and a general lack of performance predictability. For example, unless something has changed, you can easily get your repository in a state where pulling from upstream takes double-exponential time (read: might as well be an infinite loop). And as far as I can tell there’s no easy way to refer to specific patches by anything other than log message regexp; if you have two patches with the same log message, I could never figure out how to simply say “show me the diff for this particular one”.

    (Interactive commit is great though; SVK has it as well, and it is likely to come to Subversion in a future revision.)

    (Bias: I am a Subversion developer (in fact, it’s now my day job), lapsed SVK developer, occasional happy Mercurial user, and thoroughly disappointed darcs user.)

  4. Peter Hosey Says:

    dave glasser: Those who want to know more about the exponential-time-pull problem can read about it on the ConflictMisery page on the darcs wiki.

  5. Colin Barrett Says:

    I already pointed you at this on IM, but for posterity (and your readers), give Mercurial and the (built in) mq extension a try. I’m not an mq user myself, but a lot of people like it and Mercurial itself is great. Simple & easy to grok model, written in Python (so it’s actually hackable), and it scales up quite nicely.

  6. Colin Barrett Says:

    I should also mention the record extension (also built-in — putting extra features like this into built in extensions you toggle on with a config file change is one of the nice parts about Mercurial). The record extension gives you a darcs record-like command to select which hunk of your incoming changes to actually commit.

  7. Peter Hosey Says:

    Colin: Tasty.

  8. dave glasser Says:

    Peter: Yeah, I had something like this with something incredibly trivial. Cloned a small repository (XMonad), and made and committed local changes to one file (Config.hs), once. That was enough to trigger conflict misery on a “darcs pull”. I do hope that darcs fixes this: it’s a promising concept developed by smart people, but until they make it so that normal use doesn’t trigger this bug, I can’t imagine using it on any project with multiple users. (Mercurial handles the above situation marvelously, as does SVK, and Subversion branches (especially with upcoming merge-tracking features) is OK but with the obvious nit that the branches are going to be server-side.)

  9. Eric Kow Says:

    Hi all. We’ve very recently put together a Conflicts FAQ on the darcs wiki. It contains some tips for staying out of exponential-time conflicts trouble and maybe even recovering from it. Furthermore, it is where you can find the latest darcs-2.0 news (we’re thinking 2008-02 for alpha testing and second quarter that year for release).

    Please shout if there are any errors in the FAQ, or if you think there are ways it could be more helpful.

  10. Mark Stosberg Says:

    David Glasser:

    Regarding how to diff a specific patch with the same name: Darcs handles this, and I don’t mind that it encourages you to use unique patch names!

    You can use “darcs changes –xml” (and other commands that support XML output) to see the unique hash that goes with each patch. Then you can do:

    darcs pull –match ‘hash xu3234amy’

    … using whatever hash you found.

    I’ve been using darcs on a four person team with a large project for a while (a couple years?) and it works great. I’ve used CVS, SVN, and SVK and definitely prefer darcs over them all for features and ease of use.

Leave a Reply

Do not delete the second sentence.