You can clip our wings but we will always remember what it was like to fly.

Posts from February 2011

Differences between Mercurial and Subversion

People at my current job are using Subversion, and our project will be tracked using it. I never used Subversion before, the only versionning system I ever used was Mercurial. And moving from one to the other meant changing a lot of reflexs I had.
Here is a little list of changes, mostly as a reminder for myself.


Mercurial uses a single .hg directory at the root of your project to store all your project history while Subversion adds multiple .svn directories in each directory, to track history changes to that directory only.

I prefer the Mercurial approach, it keeps all changes centralized in one place. You can simply remove the .hg directory to transform your versionned version into a stand-alone one.

While the Subversion approach litters your app with countless hidden directories, making copy and pasting a real pain.

Centralised vs Distributed

Subversion is centralised while Mercurial is distributed.
As far as I understand the difference, it means that Subversion uses one main directory to store the versionned version and can deploy (export) a specific revision at anytime.

That revision do not hold any history information, it is only a copy of your project at a given time.

On the other hand, each Mercurial repository holds both the current public version and all the history. You do not have to deploy anything anywhere, just update your current repo with data from one of the revision.


I am using both TortoiseSVN and TortoiseHg. When you commit with TortoiseSVN it displays the list of files that where updated since the last commit. If you added new files, they won't show unless the "Show unversionned files" is checked.

In TortoiseHg, all new files are automatically seen in the commit window, as well as a diff. It allows me the easily see what changes where made, and help me write my commit message.
I really like the TortoiseHg vision better.

Tracking directories

Subversion can track empty directory, just by adding them. Mercurial can't. You have to add an empty file in each to allow tracking.

Also, when doing a commit in a specific directory in Mercurial, it will commit the whole repo, while with Subversion it will only commit the current repo. I can see the benefits of both and I'm not quite sure which is better.

Subversion will allow me to do a commit of one special feature by committing only one directory, but the TortoiseHg integration help me doing commits more easily no matter where I'm browsing.

Ignoring files

I have some files in my project I don't want to track (like auto-generated cache files). In Mercurial, all I need is editing the .hgignore file with regexps. The syntax can be a little strange sometimes, it took me a while to correcly understand it, but it definitely works.

On Subversion, I can add files to the ignore list so they don't show as "unversionned", but I can also add a svn:ignore property to a specific directory to set regexp to files that I don't want to track. The end result is the same, but the way Mercurial handle it with one file is more appealing to me.


Having all history in one dir and all ignore rules in one files seems a better approach to me. I guess on some aspects Mercurial is still more centralised than Subversion.

cakePHP wrapper for EmailComponent::send()

As I already wrote in a previous post, the cakePHP EmailComponent seems to have some quirks, forcing me to add more code to send an email.

I stumbled upon one more issue today : a View poisoning coming from the EmailComponent. Some vars I was passing to my view through the use of a custom Helper were wipe away if I send a mail in the same request.

It took me some time to track it down, but I finally decided that I'll now wrap calls to $this->Email->send() into a __sendEmail() custom method where I'll add my tweaks.

This will help migrating to a newer cake version easier when those bugs will be fixed.

Easy debug

Debugging emails is not an easy task, but is greatly eased by cake. One can set the delivery type to debug and the mail will be generated like a normal mail, but won't be sent. Instead, its content will be saved in Session.

My wrapper will allow switching from normal to debug mail thanks to an argument.

View cleaning

I'll also clear the ClassRegistry from the View created by the EmailComponent. The Email view is shared with the display view and this can result in vars being lost or not correctly set. I think all those troubles are gone in cake 2.0 but I haven't tested it yet.

The __sendMail method

Here is the method code. You should add it to your AppController :

function __sendMail($sendAsDebug = false) {
if (empty($this->Email)) {
return false;
// Debug mode
if (!empty($sendAsDebug)) {
$this->Email->delivery = 'debug';
// We force adding the boundaries and header otherwise some webmail (like SquirelMail) won't correctly display them
$this->Email->__header[] = 'MIME-Version: 1.0';


// We display debug info
if (!empty($sendAsDebug)) {
debug($this->Session->read('Message.email.message'), true);
// We also need to clear the generated view so our display does not get poisoned by the Email display


Getting raw JSON POST in PHP

Sometimes you need to post raw POST data without following the key/value convention, like when you need to post to some webservices.

Accessing it from PHP can be a little obsure at first, but all that is needed is to read the input buffer by doing : file_get_contents("php://input")

This can be useful when posting raw JSON without adding the overhead of all the keys.

Malformed POST request made to an absolute url with Flash

Sometimes you encounter bugs that smacks you in the face with their strangeness. And even when you defeated them you still have this sour taste of puzzlement.

I encountered one of them today.

While testing in a local environment and doing POST requests from Flash to a distant cake app, I could get the request just fine.

But when uploading the SWF on the server and embedding it in a Facebook App Iframe, the POST data seemed corrupted and I couldn't get it.

Replacing the distant POST call to a local one (removing the whole http:// part) fixed this strange bug.

So we ended by adding a check to see if we were online or local and make an absolute or relative call depending on the environment.

So far, no more issues.