Chorus Send/Receive

August 26, 2009

Using Chorus to download a project in your application

Filed under: Chorus — hattonjohn @ 12:52 pm

(Chorus is an open-source version control porcelain (over Mercurial plumbing) designed to enable workflows appropriate for typical language development teams who are geographically distributed.  Chorus is designed to be integrated into other applications, and installed with their installers.  This blog is the third in which I describe what an application developer needs to do to incorporate Chorus.)

Last time, I showed how it’s easy to let Chorus deal with finding USB keys, find projects on then, and get a clone to the user’s computer.  This time, we’ll see that you do about the same thing on your end, but the user gets a different dialog.   For some context, here’s a portion of WeSay “Welcome” screen:



Here’s the code WeSay runs when the user clicks the “Get from Internet”:

private void OnGetFromInternet(object sender, LinkLabelLinkClickedEventArgs e)
   using (var dlg = new Chorus.UI.Clone.GetCloneFromInternetDialog(WeSay.Project.WeSayWordsProject.NewProjectDirectory))
        if (DialogResult.Cancel == dlg.ShowDialog())

And here’s what Chorus puts up in response:


This dialog has a lot of code to help the user over many of the little things that can go wrong, but with the URL and the intended destination.  When you type in a valid URL, a destination folder is filled in for you,  and it tells you if there is already a folder with that name there:


Once everybody is happy, the “Download” button is enabled:


And clicking it starts the download:






If something goes wrong, the dialog will attempt to interpret some common network errors to help the user figure out the problem:



Final Notes

Chorus enters the URL that was used in the .hgrc file of the downloaded project, so when the user goes to sync, the location is presented to the user as the place they probably want to synchronize with.

Not shown here, because I haven’t done anything about it yet, is user names and passwords.  For the moment, these can just be embedded in the URL in the usual way:


August 24, 2009

Using Chorus to grab a project from a USB drive

Filed under: Chorus — hattonjohn @ 12:47 pm

(Chorus is an open-source version control porcelain (over Mercurial plumbing) designed to enable workflows appropriate for typical language development teams who are geographically distributed.  Chorus is designed to be integrated into other applications, and installed with their installers.  This blog is the second in which I describe what an application developer needs to do to incorporate Chorus.)

In Language Software, we are perhaps more keenly aware than many developers just how complicated computers are for folks who haven’t grown up driving them.  Even well-intentioned informational dialog boxes act as stumbling blocks to the people I consult with here in Papua New Guinea, expat and national alike.  And the worst thing we can do, of course, is to take for granted how challenging the “Open File” and “Choose Directory” dialog boxes are to many users.  So, we need an easier way to help users get a Chorus-enabled project off of a USB flash drive and onto the right place on their computer.  They’ll want to do this when they’re setting up a new computer, recovering from a broken hard drive, or just adding  a new person to the team.  (If they have a good internet connection, they could instead pull directly from a distant repository, and how to help them do that will be the subject of my next post.)   Chorus gives you an simple way to help these users rapidly grab the right thing and put it in the right place, without ever dealing with the file system.

Let’s walk through some sample client code (this sample taken from WeSay):

private void OnGetFromUsb(object sender, LinkLabelLinkClickedEventArgs e)
    using (var dlg = new Chorus.UI.Clone.GetCloneFromUsbDialog(WeSay.Project.WeSayWordsProject.NewProjectDirectory))

The first line makes us the dialog and tells it where we put WeSay projects, by default.  That way we don’t have to bother asking our users, most of whom don’t care and shouldn’t be asked. The next line sets up a callback so that projects from other applications (or just raw Mercurial directories) won’t be listed:

dlg.Model.ProjectFilter = dir => GetLooksLikeWeSayProject(dir);

And finally, we fire off the dialog and, after a successful completion, we go ahead and open the newly-cloned project in WeSay:

        if (DialogResult.Cancel == dlg.ShowDialog())

Here’s what the user sees:

If no USB drives are found, the dialog prompts the user with an icon and message:


Once one or more USB drives are found, the dialog walks the devices (only to a level of 2 deep), and displays those Mercurial projects which pass our filter:



Note, if the project already exists at the default location on the user’s computer, what should we do?  The answer is difficult, because there are several possible scenarios.  The user might be confused, and trying to synchronize. In that case, we had better NOT make it easy for him to make and start using a second copy. The user might not have realized that they already had the project. They might just want to have a parallel “branch” of the project. Or they may know they have it, but are trying to use this vector to replace what they have.  With all those choices, I’m giving up for now and just show this notification box.  Maybe we can do better in the future.



A final note:  you don’t have to use this UI.  If you want, you can code against the underlying to the  CloneFromUsb class:



Ok, next time, I’ll describe our first pass at a dialog for grabbing projects from internet-hosted repositories.

August 15, 2009

Using the Chorus Synchronization Dialog

Filed under: Chorus — hattonjohn @ 7:06 am

Chorus is an open-source version control porcelain (over Mercurial plumbing) designed to enable workflows appropriate for typical language development teams who are geographically distributed.  Chorus is designed to be integrated into other applications, and installed with their installers.  This blog is the first of several in which I will describe what an application developer needs to do to incorporate Chorus.  It is not logically the first thing I should write about, but there are a couple projects which already have the more basic stuff worked out, so I’ve decided to just start with the next thing they need.  Someday, I’ll go back and blog about some previous steps to incorporating Chorus into your application.  Note that for now, you need to use a .net language to use Chorus. If there is demand, it will be simple matter to provide the most important functionality via the command line, so that apps can use Chorus as well.  Chorus works with mono, so you can use this on linux as well.

The easiest way to start a synchronization job is to use Chorus’ new “SyncDialog”.  Using this, you give the user feedback and offer some control over the process. You don’t have to use it, but it will improve over time at little cost to you, and it is designed to be customizable for your needs. It is also available as a Control, so you can embed it in some other view, if you don’t want the whole dialog.

Using Chorus for Backup

One common use of Chorus will be for performing automated backup.  This is a big issue in many Language Software applications, because the user often

  1. possesses relatively low computer-skills
  2. in environmental conditions which are hard on computer hardware (dust, sea-spray, humidity, lightning)
  3. subject to high theft rates, particularly of expensive, light-weight things like netbooks

So automated backup is  a great thing to build into your applications.  Simply by “checking in” to the local version control in the folder holding your application’s documents, you provide a full history of the project so that it is possible to roll-back to a previous state.  By adding a secondary media backup location, like an SD card, you decrease the chance that a hardware failure will result in loss of work. 

For this kind of synchronization, which we’ll call “backup”, you just want to assure the user that it is happening and let them know if something went wrong.  You could do this in various ways which are less intrusive than a dialog box.  But if you do use the SyncDialog to do it, you’ll want to keep it pretty minimal. For example, when WeSay does its automated backup, it invokes the dialog like this:

var dlg = new SyncDialog(configuration,
dlg.Text = "Wesay Automatic Backup";
dlg.SyncOptions.DoMergeWithOthers = false;
dlg.SyncOptions.DoPullFromOthers = false;
dlg.SyncOptions.DoPushToLocalSources = true;

 Which gives us:


When the backup is over, the user sees the following for about a second, and then the box closes.


(Note, I’ll describe the “configuration” parameter above in a separate post.  It basically tells Chorus what file types you want checked in.  Also not described in this post is how you can tell the Chorus Synchronizer whether you’re interested in pulling from other sources, or just pushing to them, as in the case of backup).

Using Chorus For Synchronization

Whereas backup should be totally automated, there are other times when its appropriate to give the user full control. For example, when an advanced user clicks “Send/Receive” in your application, you may want to give the user the chance to clarify which devices/people/servers he’s planning to synchronize with, view the steps Chorus is taking to locate, pull, merge, and push back to remote servers, etc.  To simply bring up a dialog box with all the controls the dialog has to offer, we use code like this:

var dlg = new SyncDialog(configuration,




Which gives us:




When you click the Send/Receive button, it switches you to the log tab:


And if there is a problem, it plays an error sound and displays a warning icon:


If you click the “Show diagnostic information” box, you get exhaustive details on everything Chorus and Mercurial are saying to each other :



Some applications, like WeSay, need to allow the administrator to lock things down a bit, so that the user doesn’t uncheck the team repository and then forget to ever check it again.  To do that, instead of the everything flag, we might limit it to just one tasks tab (not shown), plus a confirmation sound. For example, we might say:

 var dlg = newSyncDialog(configuration,


        SyncUIFeatures.PlaySoundIfSuccessful | SyncUIFeatures.TaskList))

Which would leave out the “choose repositories” and “log” tabs, and instead show the (not yet implemented) tasks tab (see below).


At the time of this posting, here are the compete set of  flags you can tailor its startup/close down behavior.

public enum SyncUIDialogBehaviors
} ;
public enum SyncUIFeatures
    Minimal =0,
    Log = 8,
    RepositoryChooser = 16,
    PlaySoundIfSuccessful = 32,
    Everything = 0xFFFF


  • Add the tasks tab, which shows you an outline of the tasks that will be attempted and the status of each one (similar to the dialog in MS Outlook).
  • The cancel button currently doesn’t have the ability to kill a long-running mercurial operation (I’m a bit scared of doing it). So the cancellation only happens in-between steps chorus itself is taking.
  • Nothing in Chorus is internationalized yet.
  • The progress bar is just one of those “I’m alive” ones at this point… it has no idea how much progress has been made.

Create a free website or blog at