“Warning: ‘post-commit’ hook failed with error output:”

To save someone time in the future:

If you are fixing a hook in a Subversion repository, such as post-commit, and your clients get the message “Warning: ‘post-commit’ hook failed with error output:” and nothing else, it means that the script exited with a nonzero error status but did not print anything to standard error. However, this is also the effect of attempting to execute a non-executable file, and Subversion does not mention to you if your hook is not set executable. The first thing you should check is whether it is.

Nor shall my sword

After I got out of work, we went to the hairdressers’. Rio decided that she wanted her hair cut short for the first time (like Kit Kittredge), and I think today I saw a strange change between little-girl Rio that was and teenage Rio to come, brief as it was. The hairdresser trimmed my hair and asked me about how it was working out that Rio had three parents living in the same house. Afterwards we went to eat somewhere and the server told me my hair was longer since last time; I think trimming the split ends causes an optical illusion of some kind. Rio and I played a maths game that she taught me, and I told her it would be ideal as a Python exercise. There was no time for a darts match tonight.

Several months ago I volunteered to help with the transition of GNOME Bugzilla towards 3.0, and I haven’t done much work on it since. However, I have come to the decision that potentially scriptable things which are unscriptable annoy me, and this particularly means websites which can only be interacted with by scraping. This has spurred me on to work on writing patches for upstream Bugzilla so we can get some kind of test version of 3.0 up for bgo. Things are going quite swimmingly well with this.

Alex was away on business, but he has returned. There was much rejoicing, for I missed him. Fin has a job interview tomorrow; think good thoughts for her.

Thank you to everyone who sent me suggestions and patches for blt; it’s been inspiring to get so much feedback. I have made a launchpad project for it. New version out soon-ish.

I have a big lazyweb/discussion post about metacity testing frameworks coming up, too, but that’s to come.

You can’t stop the waves, but you can learn to surf

Rio and Alex and I went to St Gabriel’s. The man who had served as the organist and choirmaster there for nineteen years died very suddenly the other week, and the place is still feeling shocked. Mother Donna Jean preached a rather interesting sermon on the parallels between the story of Abraham’s call and the story of Nicodemus. I asked her about other Johannine uses of the metaphor of night to represent the lack of understanding and she joked that I should be preaching next week; I said that was possibly the scariest thing anyone had said for a while. I was a little frustrated that the last hymn was one I didn’t know but the score for Cwm Rhondda was staring at me from the next page. (I am not responsible for that video.)

Later I finished writing a program to compile Metacity Journal entries: in other words, it goes around and finds bug activity, checkins of code and translations, mentions on blogs, and so on, and makes a blog post out of them. Here is the first output. I will be publishing the code, of course, but it will need a bit of tidying.

Later we all went for a walk in the park. Riordon stopped and said “I’ve got something in my shoe”, and when she took it off, balancing on one foot on the towpath, and shook it, out fell a US quarter, a US nickel, and a British 5p. I told her that she must have swept her hearth particularly well, according to the old rhyme. She said that she had actually been cleaning the floor in her room, but that she had been keeping shoes downstairs, and the good folk were hardly going to be able both to see her floor and examine her footwear.

After that we came home and I closed a ton of Metacity bugs.

“When I get a little money I buy books…” I have been wanting for a long time to read three particular books to Rio that I loved as a kid. They are: The Turbulent Term of Tyke Tyler by Gene Kemp, Nothing to be Afraid Of by Jan Mark, and I Like This Poem, which is an anthology edited by Kaye Webb. Amazon in the US doesn’t know TTTOTT, though it has the other two second-hand, which I don’t mind at all and indeed prefer in a lot of ways. Tonight I thought I’d order all three from Amazon in the UK; I was quite pleased to find that most of them were available for prices as low as a penny in some cases until I saw that shipping would be £20 to me in the US and £8 even to my parents in Hertfordshire. I think this must be the result of reasoning in a weak currency, because $20 to ship three books, or $40 overseas, seems rather excessive to me. Is that really what postage costs, and do any of you have advice or even an old copy of TTTOTT that you can send me in return for postage, gratitude, other trinkets, love, bug fixes, sonnets written praising you…? Update: My sister Mandy tells me that the book is called “Tyke Tiler” in the US, for obscure reasons, and it may therefore be findable after all.

Software we’d like to see: I have always been in slight awe of IMAP. It does everything POP3 does, everything SMTP does (and a lot better)[1], everything NNTP does, and it does its own useful things as well. You even could use it, if you were monomaniac enough, for a ton of other things, including as a replacement for FTP, or as an RPC transport. If some Emperor of the Internet was to decree tomorrow that henceforth nobody was to use POP3, even the people who only want what POP3 does could run IMAP and just only allow or only use its “recent” mode. Really, I think there are two things that puzzle me about it:

  • Why anyone is still using POP3, and more so, why they are still using SMTP.
  • Why everything-but-the-wire-protocol of IMAP is still travelling over a custom protocol and not REST. It seems to me as though it would mean we could reuse existing and well-tested code, it would mean you’d get all the existing bonuses of the HTTP protocol like its ubiquity and gateway support and so on, and the IMAP protocol is very REST-like already: it would be a pretty simple one-to-one mapping.

I haven’t seen anyone seriously suggest this, although Google showed me a thought-experiment as a teaching aid. If I was still working for an email provider I would suggest it, but I’m not.

[1] Ryan Lovett has pointed out that IMAP specifically doesn’t allow for sending mail, and he’s right: I misread the RFC and thought I saw something that wasn’t there. I’m sorry. I do think it should be included into a system such as the one I discuss above: something which allowed access to a group of messages/files over HTTP in the style of WebDAV (although possibly simpler), so that you could read and write and sort them into folders, and then also have a way to send them and to search for ones with flags like “recent”, would be a hugely useful grand unified protocol.

Webtoys
I fixed the “partlock” bug in Joule, which annoyed a small number of people a whole lot. Also, I thought you might be interested to see the usage of the cupid script:

The community was quite quiet this year compared to last, I think. I would show you the world map for just the script if I could figure out how to generate it. I can only seem to get Google Analytics to show maps for the whole site.

(Very brief) link soup:

(I apologise for those of you reading this on blogo/tthurman who think it clashes; I’m trying to make it look like marnanel.org and so far I’ve only got as far as playing with the CSS.)

Valentine’s and after

Valentine’s day was actually quite quiet for the most part. Our company gave us a bag of sweets, mostly those little love-heart ones which say things on them like EMAIL ME and YOU’RE THE BEST and CLOSE MY BUG((Not an actual example, sadly. Maybe we could make some GNOME sweets for next year.)), and chocolate hearts with mottos inside. My team lead was told “Be your own Valentine!” which sounds like a polite way of saying something else.

When we got home, Fin had made an amazing meal for all of us, each with our favourite thing to eat. Some of them had tomatoes and things cut into heart shapes. It must have taken ages.

I also discovered a not terribly obvious problem with GMail. I wrote a script which would tell you who had left you Valentine’s messages on LiveJournal, and it worked by turning on email notification, sending each LJ comment received to a GMail account, and every hour having a cronjob which read the account using IMAP, indexed them all in a Postgres database, and then having a cgi which could display search results. That was all very well, but on Valentine’s day itself, something inside GMail decided that the account was being used for IMAP in some kind of inappropriate way, and shut it down wth the error Lockdown in Sector 4! I disabled the cronjob, but it meant that some people didn’t see their valentine messages for another day or so.

On Friday it was pretty quiet again. I wrote a triolet.

Lines Written on the 15th of February

Today’s just a day
That’s not Valentine.
No roses, no wine.
Today’s just a day
I still want to say
I’m glad that you’re mine.
Today’s just a day
That’s not Valentine.

I also spent far too long trying to remember the visibility rules in GNOME bug 509165.

Link soup:

When Wednesday was quiet

I had a doctor’s appointment on Tuesday; I told Fin and Alex about it on the Monday and asked them to drop me off there. On Tuesday they went to see this cat that I mentioned earlier, and came to pick me up afterwards, and as I also mentioned we decided to go out to eat. I’d thought that meant after the appointment, and I was so sleepy I fell right asleep. When I woke up, we were coming up to the restaurant, and I was faced with the dilemma of whether to say, “But we’re missing my appointment” (and go back, have missed the appointment anyway, and have ruined the meal), or to keep quiet for now. I decided to keep quiet. Either way I’d have to pay for the missed appointment.

The next day I phoned the doctor to reschedule and they were very apologetic: they said, “Oh, we were trying to contact you: the doctor was off sick yesterday. We’ll phone in a refill for you.”

I didn’t go to see the cat after all on Wednesday, because she behaves nothing like our cat did and doesn’t respond to her name, and people were afraid I’d give a false positive because I miss our cat so.

I spent much of the evening writing about GMarkup instead of fixing bugs.

I also had a very interesting email, which I might tell you all about later.

This morning, the company has given us all bags of love heart sweets and teddy bears. Thank you to the people who left comments for me on valentinr and places like that! If anyone sent one of those mutual things where you have to send another of the same kind in order to see them– well, I didn’t send any like that, so I won’t see them.

Fin, Alex: I am going to get you trees. But it is too cold to plant trees, so later in the year I will get them.

Link soup:

XML, GMarkup, and all that jazz

xmlchick.jpgI was asked to talk about how to use GMarkup. This is a brief introduction; there are many people more qualified to talk about it than I am. These are my opinions and not those of the project or my employer. If you want to suggest a change or report a mistake, suggest away.

Firstly, why you shouldn’t use GMarkup.
Don’t use GMarkup if all you want is to store a simple list of settings. Instead, either use gconf, or if what you want is a file on disk, use GKeyFile, which lets you write things like:

[favourites]
icecream=chocolate
film=Better Than Chocolate
poem=Jenny kiss'd me when we met

in the style of .ini files. These are much more user-friendly.

Don’t use GMarkup if you want to parse actual arbitrary XML files. Instead, use libxml, which is beautiful and wonderful and fast and accurate. GMarkup is made to be easy to use.

Do use GMarkup if you want a reasonably complicated way to store files on disk, in a new format you’re making up.

Why GMarkup files are not XML.
XML is big and scary and complicated and spiky. People pretend it is simple. It isn’t. GMarkup files differ in many ways from XML, which makes them easier to use but also less flexible. Here are some ways in which a file can be XML but not GMarkup:

  • There is no character code but Unicode, and UTF-8 is its encoding. GMarkup does not attempt to screw around with UTF-16, ASCII, ISO646, or, heaven help us, EBCDIC. That way madness lies.
  • There are five predefined entities: &amp; for &, &lt; for <, &gt; for >, &quot; for ", and &apos; for '. You cannot define any new ones, but you can use character references (giving the code point explicitly, like &#9731; or &#X2603; for a snowman, ☃).
  • Processing instructions (including doctypes and comments) aren’t specially treated, and there is no validation.

There are also a few subtle ways in which a file can be parsable by GMarkup but not be valid XML. However, these are officially invalid GMarkup even though they work fine, if you can follow that. Many people don’t care, but they should.

Okay, so how do we get going?
There are two ways people deal with XML: either as a tree, or as a series of events. GMarkup always sees them as a series of events. There are five kinds of event which can happen:

  • The start of an element
  • The end of an element
  • Some text (inside an element)
  • Some other stuff (processing instructions, mainly, including comments and doctypes)
  • An error

Let’s imagine we have this file, called simple.xml:

<zoo>
  <animal noise="roar">lion</animal>
  <animal noise="sniffle">bunny</animal>
  <animal noise="lol">cat</animal>
  <keeper/>
</zoo>

This will be seen by the parser as a series of events, as follows:

  • Start of “zoo”.
  • Start of “animal”, with a “noise” attribute of “roar”.
  • The text “lion”.
  • End of “animal”.
  • Start of “animal”, with a “noise” attribute of “sniffle”.
  • The text “bunny”.
  • End of “animal”.
  • Start of “animal”, with a “noise” attribute of “lol”.
  • The text “cat”.
  • End of “animal”.
  • Start of “keeper”.
  • End of “keeper”.
  • End of “zoo”.

(Actually there’ll be some extra text which is just whitespace, but let’s ignore that for now.)

There are two kinds of objects to deal with.
One is a GMarkupParser: it lists what to do in each of the five cases given above. In each case we give a function which knows how to handle opening elements, or closing elements, or whatever. If we don’t care about that case, we can say NULL. The signatures needed for each of these functions are given in the API documentation.

The second kind of object is a GMarkupParseContext. You construct this, feed it text, which it will parse, and then eventually destroy it. It would be nice if there was a function which would just read in a file and deal with it, but there isn’t. Fortunately, we have g_file_get_contents(), which is almost as good, if we can assume there’s memory available to store the whole file at once.

So let’s say we want to print the animals’ noises from the file above.

  1. Decide which kinds of events we need to know about. We need to know when elements open so that we can pick up the animal noise, and when text comes past giving the animal name, so we can print it. It would be possible to free the noise when we need to get the next noise, but it would be easier to free it when we see </animal>, so let’s do it like that. Processing instructions and errors we can ignore for the sake of example.
  2. Write functions to handle each one.
  3. Write a GMarkupParser listing the name of each function.
  4. Write something to load the file into memory and parse it.

Here’s some less-than-beautiful example code to do that.

#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

gchar *current_animal_noise = NULL;

/* The handler functions. */

void start_element (GMarkupParseContext *context,
    const gchar         *element_name,
    const gchar        **attribute_names,
    const gchar        **attribute_values,
    gpointer             user_data,
    GError             **error) {

  const gchar **name_cursor = attribute_names;
  const gchar **value_cursor = attribute_values;

  while (*name_cursor) {
    if (strcmp (*name_cursor, "noise") == 0)
      current_animal_noise = g_strdup (*value_cursor);

    name_cursor++;
    value_cursor++;
  }
}

void text(GMarkupParseContext *context,
    const gchar         *text,
    gsize                text_len,
    gpointer             user_data,
    GError             **error)
{
  /* Note that "text" is not a regular C string: it is
   * not null-terminated. This is the reason for the
   * unusual %*s format below.
   */
  if (current_animal_noise)
    printf("I am a %*s and I go %s. Can you do it?\n",
        text_len, text, current_animal_noise);
}

void end_element (GMarkupParseContext *context,
    const gchar         *element_name,
    gpointer             user_data,
    GError             **error)
{
  if (current_animal_noise)
    { 
      g_free (current_animal_noise);
      current_animal_noise = NULL;
    }
}

/* The list of what handler does what. */
static GMarkupParser parser = {
  start_element,
  end_element,
  text,
  NULL,
  NULL
};

/* Code to grab the file into memory and parse it. */
int main() {
  char *text;
  gsize length;
  GMarkupParseContext *context = g_markup_parse_context_new (
      &parser,
      0,
      NULL,
      NULL);

  /* seriously crummy error checking */

  if (g_file_get_contents ("simple.xml", &text, &length, NULL) == FALSE) {
    printf("Couldn't load XML\n");
    exit(255);
  }

  if (g_markup_parse_context_parse (context, text, length, NULL) == FALSE) {
    printf("Parse failed\n");
    exit(255);
  }

  g_free(text);
  g_markup_parse_context_free (context);
}
/* EOF */

Save that as simple.c. If you have the GNOME libraries properly installed, then typing

gcc simple.c $(pkg-config glib-2.0 --cflags --libs) -o simple

will compile the program, and running it with ./simple will give you

I am a lion and I go roar. Can you do it?
I am a bunny and I go sniffle. Can you do it?
I am a cat and I go lol. Can you do it?

I think that was enough to whet your appetite, but there’s a whole lot more to know. You can read more here. If you want to see a real-life example, Metacity uses exactly this sort of arrangement for its theme files. (Later: Julien Puydt shares memories of how schema handling in gconf was written using GMarkup.) Any questions?

Photo: Day-old chick, GFDL, from here, by Fir0002, modified by Dcoetzee, Editor at Large, and tthurman.

Zaratbee

I have had a moderately successful day. I branched metacity for 2.22. (I wish I could write more about work here; it feels silly not writing about the thing I spend most of my time doing.) I made a list of things which need dealing with now we’ve branched, and as a diversion fixed up some map SVGs for Wikipedia (and another project). Someone came around with bagels.

Fin phoned and told me the SPCA had come by and told them they’d found a cat who looked just like our cat Zarate, who ran away shortly before Kirsten came to visit; Fin and Alex and Rio went to see, but the new cat (let’s say her name is Zaratbee) didn’t respond to her name or the feeding song, despite being about the right size and shape and colour. Fin thought it was her; Alex didn’t. I will go along tomorrow and see.

It snowed a lot. I was told I gave the best hugs. I came home and it snowed a lot and Fin in her awesomeness said “Why not let’s go to Los Aztecas?” So we did and the food was even better than it usually is, and almost nobody was there because of the snow. We talked about politics, and came home. I worked on some simple breadboard electronics on the dining-room table with Rio before she went to bed; she wrote up the findings in her lab notebook, which has a picture of Strawberry Shortcake on the front. Did I mention she has dyed her hair grape-soda purple? It really suits her.

I learned, or re-learned, about the __import__ statement in Python for a project I’m doing with the Metacity Journal (more will be revealed later). I asked jdub to move my public planet feed to blogs.gnome.org and I will automagically duplicate all content to LJ and blogo. I have not decided what I will do about comments. I also need to put some time into copying the stylesheets and formatting from marnanel.org to blogs.gnome.org.

Ande: I have started work on the river story. It is progressing nicely.

Things I wanted to share (because they were an interesting read):

Now I will make more tea and then go and get out of these clothes and sit in bed and fix bugs, which I can do because Alex has fixed wireless networking, so hallelujah, say I.

an update

Sharon came over and made us lasagne as a belated birthday tea for me.

I have done a good amount of hacking; it was fun and got stuff done. Yay.

Later, we went to the park and walked by the river, and Riordon and I discussed high-voltage electricity transmission.

Metacity’s translation into Welsh has not been touched in almost two years. It is a shame. If one of you Welsh speakers who reads this would like to give it a shot (there are about 500 phrases, mostly short, about 80% of them already filled in, and most of them guessed by the computer from the others and you only have to make minor adjustments), I will show you how to do so and you will have your name all over the credits. If not, I am happy to try to do the work myself, but I would like it if someone would check my work since I’m hardly confident in my own fluency.

Oh, and I learned how to say “fish and chips” in Welsh. It’s “sgod a sglod”. Makes sense.

I think this does not sound like a very exciting entry. Sorry :(