How to write a patch for Octave

Often people will find ways to improve Octave’s source and provide a patch, but in a way that is slightly inconvenient to analyse and apply. I will now present instructions for creating a patch for Octave in a manner that is easiest for core Octave developers to apply. In what follows, I assume that you have already managed to install Mercurial, that you’re using some sort of shell (probably even Windows), and that hg is already in your shell’s PATH.

First, you should work with an hg clone of the repository:

hg clone http://www.octave.org/hg/octave
cd octave

Once you’re in there, you probably would want to build Octave so you can test your patch. On a Unix-like system, assuming you’ve installed all the dependencies (and that’s a big assumption, because Octave dependencies can be difficult to track down), you should run autogen.sh in the hg clone before you follow the general build instructions.

Then you can proceed to modify Octave sources however you see fit. You can run the hg st command to see which files you’ve modified and hg diff to get a detailed diff of your changes which will eventually become your patch. I personally find the hg colour extension to be a very nice visual aid for these two commands. You should also try to build Octave again with your changes as a minimum sanity check that your patch is good.

A word on building when patching Octave: the deeper in the build dependencies you patch, the longer you’ll spend rebuilding Octave. So, for example, liboctave depends on libcruft, and liboctinterp (most of the stuff under src/) depends on liboctave, so if you touch a file in libcruft, it’s very likely that you’ll have to rebuild liboctave and liboctinterp. The rough depth of things that can be patched by their directory locations is this: libcruft/liboctave/srcsrc/DLD-FUNCTIONSscripts/, in fact, for scripts, you almost never need to rebuild Octave when patching stuff there (unless you want to rebuild the documentation); but sometimes you do need to restart Octave when testing.

Once you think your patch is in good shape, and you’ve written some tests for it (look for assert commands near the bottom of source files to see how tests are written) you should commit it so that it becomes a (semi-)permanent part of your local hg clone. If it’s your first time using Mercurial, you should create an .hgrc on a Unix-like system or Mercurial.ini in Windows and put in there lines to identify you, like so:

[ui]
username = Your Real Name <some@email.com>

Now do

hg ci
hg export . -o my_fix.patch

to record your change. When you type the first command, hg should open an editor where you will now have to write a commit message. Now your change has become part of your local repository, and the second command has exported your patch to a file named my_fix.patch in a format that is easy for others to apply. Now just send that patch to the Octave patch tracker or attach it to an open bug report, and we’ll take care of it!

I hate git

… or at least I hate it for now.

I’m a Mercurial kinda guy (hereafter hg). Mercurial is the version control system (VCS) that Octave uses, so that’s mostly the reason why I started using it too. I started reading about it, and learning it, and liking it a lot. It makes a lot of sense to me. It’s simple when it needs to be simple and flexible when it needs to be complex.

The other big contender for a VCS is usually git. In fact, it’s quite a large contender. Just going by comparing github and bitbucket, the two large commercial hosts for git and hg respectively (don’t let that .org domain fool you, bitbucket is definitely a commercial venture), github is way larger. It is by far easier to find people praising git in the blogs, the discussion forums, and the mailing lists than it is to find people cheering for hg. I have dabbled with git in the past, and I always found it difficult to understand. I always chalked up this difficulty to just being more familiar with hg, and being nothing more than a personal preference. However, I have recently seen that I am not alone in thinking that git is complicated. Regardless, seeing how immensely popular, vastly more popular than hg it is, I decided to try git again today.

I decided to make a conscious effort again today to learn and use git. I had a practical reason too, to fix a Debian RC bug (perhaps a little late, I hope the release managers let the package back into testing after this). Also, I wanted to streamline the flow for hacking on Debian packages. The Debian packaging of Octave used to be under svn, and later turned into git packages. One thing that makes a lot of sense under svn, since it tracks individual directories, not whole projects, is to only put the debian/ directory under source control. This practice got inherited with the git repositories, and it’s really awkward. Setting yourself up to hack a Debian Octave package goes something like this:

apt-get source octave-foo
rm -r octave-foo-$version/debian
cd octave-foo
git clone git+ssh://git.debian.org/git/pkg-octave/octave-foo.git

    # ...
    # hack hack hack
    # ...

dpkg-buildpackage

which is really awkward. My goal was to get to this:

git clone git+ssh://git.debian.org/git/pkg-octave/octave-foo.git

    # ...
    # hack hack hack
    # ...

git-buildpackage

So I set out to do that. With somewhat unfortunate results.

Let me talk a little more about where I’m coming from: hg. In hg, there are some guiding philosophical principles that have become second nature to me when working with source. One of the core hg principles is that it’s really hard to destroy data, in particular history. There are certain destructive operations with hg, but they almost all create backups, and are disabled by default. The way to enable them is to turn on extensions. In particular, hg makes it virtually impossible to destroy any data remotely unless the person who controls that remote repository somehow enables it with hooks. That is, the person would have to write a script that when you manipulate their repository remotely (and the only commands to do this are pull and push), that script would delete some data.

This vibes really well with me. One of the things that git users praise the most is how easy it is to edit history, to undo mistakes, to rebase changes… hg doesn’t make these tasks impossible, merely difficult or disabled by default; and I tend to side with that point of view. It’s safer. Mercurial takes care of my data when I want it to, and when I need it to do dangerous things, I first have to remove its muzzle, and the muzzle snaps back into place when hg is done doing its dastardly deed. It’s a bit like using “sudo” to perform just one dangerous operation instead of “su”, and then staying in the root shell, while performing several operations, none of which really needs the extra permissions.

So on to what happened: during my work of trying to make it easier to work with Debian, I had created several git branches (which are nothing like hg branches, but whatever, that’s not a big deal). When it looked like my work was in good shape, I pushed it to the Debian git repo. Oh, oops, that only pushes one branch. That’s quite unlike hg which pushes all of the work here that doesn’t exist there. Well, not a big deal, that’s a bit like git’s staging area I thought. Just one more step to get what I want. But I had like three different branches here that weren’t there, so I figured there must be some command to get them all there at once. I asked around in IRC, and someone naïvely suggested using the --mirror command, and I naïvely trusted them without checking what that option would do. I thought it would just copy all of my branches from here to there, mirroring all of them.

And so it did. However, it also checked that there were some branches there that I didn’t have in my local clone, and it erased them. I blinked. Wait. Did git just remotely remove some branches? Oh, well, I’m sure it’s just some metadata that got moved around. Where’s the undo button? Rollback? Restore? I went to #git in IRC to ask.

“… you do have backups, don’t you?”

I blinked again.

Whiskey.

Tango.

Foxtrot.

You’re telling me… that a VCS… one of the most popular ones out there… allows me to delete data remotely? With a command that isn’t called even called “delete” or “wipe” or “force” but innocuously called “mirror”?

I was aghast.

My conversational partners in #git gave me the usual spiel about backups, about how it’s great to be able to shoot yourself in the foot, about how it was my fault, about how I should have read the manual… but I was unable to accept any of this. I just couldn’t conceive that a tool that is supposed to keep my history … to be a little “bit-hoarder” … to never lose data … not only lets me lose data locally, which is ok, but furthermore lets me delete data remotely.

Now, granted, this wasn’t terribly important data. Nothing of great value was lost. Since branches in git are more like tags (but not what git calls tags), it’s just metadata that was lost. The functional part is all there. At the same time, a user’s most valuable possession, data, was harmed by the very tool that’s supposed to protect it. I hate the idea of having to tiptoe around my VCS, which should be a tool that lets me experiment wildly with my source, to try out crazy ideas, and at the same time keep my source safe, multiply backed up, fully mirrored in every clone of the source whether local or remote. Mercurial, for example, doesn’t let me delete data remotely. The worst I can do is add a lot of useless data remotely, but that’s much better than being able to delete it.

Reeling, I did the only thing that could be done and emailed the Debian Octave Group mailing list, asking if someone had a clone of the repository with the missing branches. I hoped that I could recover the lost data by copying it from them. If not, it won’t be a great loss, just an awkward inconvenience. The whole experience, though, has given me a great distaste for git. I still find it much more complicated than hg, even despite my best attempts to understand it. And it’s shown me that I can’t treat it carelessly, that I have to read its gargantuan manpages and thoroughly understand each and every command and option before I use them, lest I provoke damage.

Next time, I’m using the hg-git extension, and I don’t think I’ll be touching git again for a while until I recover from this nasty experience.