Archive for the ‘Tools’ Category

I’ve been using Mercurial at work for two months now and the expectations I had about it didn’t change to anything better. I guess it looks cool for people who are used to SVN, or even CVS, and are not familiar with other DVCS. I must say that as a Bazaar user, I miss a lot of things. There are some that can be worked around, for something you just have to be extra careful and for something you are out of luck. I really don’t get how people use Mercurial for managing large projects.

Cheap Branches

One of the main reason people use DVCS is cheap branching. The most surprising thing for me was that Mercurial doesn’t offer many choices. It doesn’t have the concept of branches, like Bazaar or Git. All you have is an immutable repository that can contain multiple head revisions. By default, you are expected to clone the whole repository. As I mentioned earlier, I tend to work with many feature branches, so I prefer to have just one working tree.

One way to partially solve this problem is the bookmarks extension. It basically allows you to have dynamic tags that move to new revisions as you commit. The initial configuration looks like this:

[extensions]
bookmarks =
[bookmarks]
track.current = True

The next step is to go to your clone and set the main/trunk/master/etc. bookmark:

hg bookmark main

This is necessary, so that you easily know which revisions represents the project’s “mainline”. With the configuration I mentioned, the extension will track your current bookmark and update only that one. To set the current bookmark, you can use update:

hg up -r main

It’s important to always have the current bookmark set to main whenever you are fetching changes from the mainline. Otherwise you will have to manually fix the bookmark’s revision.

Creating new “feature branches” is easy then:

hg bookmark -r main my-feature
hg up -r my-feature

One important thing to remember is that after you use this, the repository will contain multiple heads. This means you can’t use plain hg push to push changes to remote repositories. You always have to specify the revision, for example:

hg push -r main https://hg.example.com/projects/trunk

Merging

When it comes to merging, Mercurial doesn’t make your life easier at all. The default assumption is that visual merging is the preferred way to go. Maybe I’m just too stupid, but I don’t get visual merge tools. I just don’t know how to use them. I prefer merging changes manually in my text editor, after I see the changes for the whole project. Mercurial would start up the merge tool for each file linearly, which means you don’t have a global picture of impact on the project, when you are supposed to resolve a merge. I just can’t work that way.

Fortunately, Mercurial does have an internal three-way merge algorithm, that can leave conflict markers in the merged files and let me do my job. You can configure it this way:

[ui]
merge = internal:merge

This actually uses the merge code from Bazaar, so I expected I’ll be done quickly. There is one problem though. Instead of using patience diff, like Bazaar, it uses its own diff algorithm. The result is that in Bazaar the algorithm works just fine, in Mercurial it produces horrible results. That’s actually pretty funny, considering the fact that I used ideas from Mercurial’s diff code to implement the C version of patience diff in Bazaar.

Next step, the Mercurial wiki suggests diff3 as a possible non-interactive merge tool. There are no examples how to configure it, but something like this technically works:

[ui]
merge = diff3
[merge-tools]
diff3.args = -m $local $base $other > $output

In my experience, this produces even worse results than internal:merge, so there is no reason to use it.

The last idea was to use the merge program from RCS (yes, that’s right, using an ancient VCS to fix issues in a “modern” VCS). I must say that installing RCS in 2010 feels weird, but as long as I can get my job done… Once it was installed, I used this configuration:

[ui]
merge = merge

I was surprised that the results were acceptably good. Not perfect, but I knew I can’t expect more from a three-way merge. Ideally I’d like Bazaar’s merge algorithm with patience diff, but I probably won’t find time to port it, so merge will stay as my default merge tool for some time.

That’s only the first part of the problem though. Now you have files with conflict markers and you need to resolve them. Based on my experience with other version control systems, I assumed conflicts would be listed in hg status, but I was wrong. They are nicely hidden here:

hg resolve -l | grep '^U'

After manually resolving the conflicts, you can use the following command to mark the files as resolved:

hg resolve -m path/to/file

To be continued…

One more short snippet, that might be useful to me in the future. If you have a website served by Apache and want your clients to only use HTTPS, you can use this mod_rewrite configuration:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]

If the server then gets any HTTP request, it will redirect the client to the same URL, but with the https scheme. This means that actual requests will be only ever served via HTTPS.

My faculty has it’s own thesis LaTex style, which makes it very easy to get a decent looking thesis out of LaTeX without too much effort. The problem is that the style requires you to use ISO-8859-2 in your document, which is something I can’t really live with. :) Here are instructions how to convert the style to UTF-8. I’m posting them here in hope that it will help some other student of Faculty of Informatics, Masaryk University in the future.

I’m doing this on an Ubuntu laptop, so first I’ll need LaTeX:

sudo apt-get install texlive

Then download fithesis:

wget http://www.fi.muni.cz/~xpavlov/fithesis/install.sh
wget http://www.fi.muni.cz/~xpavlov/fithesis/fithesis-0.2.12.tar.gz
tar -zxvf fithesis-0.2.12.tar.gz
cd fithesis-0.2.12

Convert the sources to UTF-8 and change the package options in the file:

recode latin2..utf8 fithesis.dtx
sed -i 's/latin2/utf8/' fithesis.dtx

And now we can install it:

cd ..
chmod a+x install.sh
./install.sh 0.2.12 /usr/share

At this point you can use the package in your UTF-8 encoded LaTeX document.

Another post mainly for myself, just so I know where to find the information quickly the next time I need it. If you have swap on a LVM volume, these commands can be used to resize it (in this case, increase by 100MB):

swapoff /dev/vg_foo/lv_swap
lvextend -L+100M /dev/vg_foo/lv_swap
mkswap /dev/vg_foo/lv_swap
swapon /dev/vg_foo/lv_swap

That is: disable swapping on the volume, extend it, re-create the swap area and enable swapping again.

I maintain a few open source projects that use SVN, so notes like “Fixes bug #123, patch by J. Random Hacker” in commit messages are more than usual. When I started using Bazaar for Picard, I thought it would be nice to handle these natively. Bazaar could store bug metadata since version 0.16, using the bzr commit --fixes option, so that was nice. It kind of inspired me to add the other part, the author name, which was a little more important for me than bug numbers. I wanted contributors who send plain patches to be equally credited for their work in the default branch viewing tools. I knew that Git had the concept of separated “committer” and “change author” and I really liked the idea, so I submitted a patch to Bazaar to add something similar (that was in bzr 0.91). The change allows you specify the author name on commit, that would be stored along in the revision along with the committer name. So you can run a command like this:

bzr commit --author "J. Random Hacker <jr@example.com>" --fixes project:123 -m "Blah, blah, ..."

And then see the author name in other tools like bzr log or bzr annotate:

------------------------------------------------------------
revno: 1
author: J. Random Hacker <jr@example.com>
committer: Lukáš Lalinský <lalinsky@gmail.com>
[...]

Naturally, commit, log and annotate from QBzr also supported this since the day I wrote the patch. It’s a shame that bzr log only displays author names, not the bug information, because that makes the useful feature quite hidden if you are not using any GUI plugin. I think QBzr users tend to use these features more often, because the commit dialog make it very visible that there is a possibility to do so, but also because bzr qlog will then nicely present the metadata (labels in the revision graph, clickable links, search for bug numbers, etc.). Here you can see an example with revision that fixes two bugs and the committer is different from the change author:

qlog-picard