Custom merging with Mercurial, on Windows

February 7th, 2008 by hatton

Today I had one of those 1/2 hour projects that turn into most of the day. I set out to try out mercurial and see how difficult it would be to get it to use a custom program to do a merge, based on the file extension. When the file type is a .lift (which is xml), I want it to run my program that knows about lift files. Simple enough. The web was littered with pages claiming ways to accomlish this… but like so often in open source stuff, a given page is for some past version on some other platform, though you as a newbie have no idea of this, so you spend all day trying things.

I’ll spare you the rest of sob story. Here’s what finally worked:

1) I installed a recent tortoisehg distribution.

2) I installed python 2.5, made sure python was part of my PATH

3) I grabbed the hgmerge.py python script

4) I learned enough python to make the script actually work (must have worked in some previous version of python… surely!)

The part of the script that inserts the values for the file paths had lines like this:

cmd.replace(’$base’, base)

Which I had to change to:

self.cmd = string.replace(self.cmd,’$base’, base)

Also the part that recognizes the “external” word didn’t work, so I rewrote it as:

elif string.find(inter, ‘external’) > -1:
start = string.find(inter, ‘external’)
tool = External()
tool.set_command(inter[9+start:])
return (noninteractive, tool, ext_filter)

5) in the .hg folder which is the mercurial repository, I edited the hgrc file:

[ui] merge = python E:\Users\John\Documents\WeSay\hgTest1\hgmerge.py

6) I edited the E:\Program Files\TortoiseHg\mercurial.ini file:

[hgmerge] ext.lift = external C:\WeSay\lib\LIFT\LIFTDotNet\output\debug\LiftMerge.exe $base $local $other $output

Beating the Disposal Blues

January 18th, 2008 by hatton

This blog is largely a note to my future self, as I know I’ll be here again, and hopefully will google for the right terms to find this entry.

I had just added our standard code to ensure that a control was disposed of properly:

~DetailList()
{
    if (!this._disposed)
    {
        throw new InvalidOperationException("Disposed not explicitly called on "
                                    + GetType().FullName + ".");
    }
}

Using Resharper’s Unit Test Runner, all my tests passed. I checked it in, and fired up the build machine. The build uses NUNIT console to run its tests; they all passed there, too, but the build failed because this code was throwing this InvalidOperationException all over!

Notice, the key problem here is that this exception is thrown on the finalization thread, at indeterminate times. So ReSharper might not notice it at all, and no test runner really knows which test caused it. Even with Nunit, the message was listed under the wrong test method a couple of times; this is quite understandable; suddenly this exception comes through, how’s the test runner supposed to know that the fault was actually 8 tests back? If you have a thousand or so unit tests, it can be tough to figure out which one forgot to dispose of the object.

I got out of this mess by storing the stack trace, at the time of construction, with the object:

public DetailList()
{
     #if DEBUG
        _stackAtConstruction = new StackTrace();
     #endif

Then, in the finalizer, I just cough that back up:
~DetailList()
{
    if (!this._disposed)
    {
        string trace = "Was not recorded.";
        if (_stackAtConstruction != null)
        {
            trace = _stackAtConstruction.ToString();
        }
        throw new InvalidOperationException("Disposed not explicitly called on "
               + GetType().FullName + ".  Stack at creation was "+trace);
    }
}


				

Steps toward running a Mono app on the OLPC XO

December 11th, 2007 by Eric Albright

I created a sd card image to boot the XO separately for our Mono environment.

  • Image the sd card using a developer image as documented here
  • Change all instances of ‘disk:\’ to ’sd:\’ in /boot/olpc.fth
  • add mono.repo to /etc/yum.repos.d as documented here and here
  • yum install mono-winforms

To launch a mono application, run: DISPLAY=:0.0 mono AppName.exe at the developer console. (Alt+= will bring up the developer console.)

We did find that the 200 dpi was not getting picked up by mono. In order to get that working, run echo 'Xft.dpi:200' | xrdb -merge at the developer console.

Giving new life to Spart

September 30th, 2007 by Eric Albright

As part of implementing our strategy for simplified sorting rules I needed to write a parser for the rules. Of course I started out looking at parser generators but wasn’t very excited by what I could find. Eventually I came across Spart (an implementation of Spirit in C#). I liked what I saw but it isn’t maintained anymore and it was written before .Net 2.0 so I cleaned it up a bit, took advantage of .Net 2.0 features, and added it to our Palaso library.

Running a Word macro on multiple files

August 28th, 2007 by Eric Albright

Last time I wrote about the need to save lots of Word files as another type. Since then, I needed to run a Word macro on a bunch of files so figured I could use the same process but just run a macro before saving the file so now I have added another little utility that will allow you to do that.

Mass conversion of Word documents to Office Open

July 24th, 2007 by Eric Albright

I needed to convert hundreds of documents from Word .doc files to standalone Office Open XML files. The Office Migration Planning Manager includes an Office File Converter utility for bulk conversions but best I can tell, it only produces the zipped docx variety. (See Doug Mahugh’s description). I need to process these with an XSLT file.

After much digging around, I found the PrimaryInteropAssembly redistributable for Office. I figured I could make a simple utility to do the conversion using that. After installing the PIA, it would not show up in the list of .Net assemblies and I was really puzzled until I finally looked in the COM assemblies. Sure enough there it was.

I ended up making a little utility that will open a Word document and save it as whatever type you specify. For multiple files, I just used the FOR command:

FOR %f IN (*.doc) DO WordConvert %f %~nf.xml FlatXML

Releasing the COM objects proved to be harder than I thought. When I first ran the application, (on fifty odd files) I got an instance of WinWord for each time it ran! Eventually had to force garbage collection twice at the end.