views:

34

answers:

1

What are the relative pros and cons for using hooks vs. using an extension that wraps a command for a particular task?

In other words, what are the criteria for deciding whether to use hooks or wrap a command?

Please also list the cases where one approach is the only option. One case I can think of is to add new arguments for existing commands. You could also change/remove arguments, for example I default log to log -g but graphlog aborts in the presence of some "incompatible" arguments (see graphlog.check_unsupported_flags), so I added a log wrapper to remove -g in those cases, because forced abortion is a crime against humanity.

It feels like hooks are more clean-cut. Python hooks run in the hg process so there's no performance issue. And while it's easy to use extensions.wrapcommand to create command wrappers, it's trivial to create/disable hooks, and to adjust the order in which they are applied (they should be self-contained in the first place).

And here's a quote from hgrc doc that recommends standard hooks over pre/post command hooks, but it also applies to hooks over wrapper:

... hooks like "commit" will be called in all contexts that generate a commit (e.g. tag) and not just the commit command.

Also I guess that hooks are not subjected to GPL (or are they?), whereas command wrappers in extensions are.

(I hope a 1.5k+ user can create a mercurialhooks tag. Git fan boys have beaten us with githooks.)

+2  A: 

I can't speak to licensing issues, but the biggest difference between a hook and an extension is that a hook can be written in any language whereas extensions are always python.

If one's writing in python then there's little difference between a hook and an extension:

  • either can delve deeply into mercurial internals
  • both require users modify their .hgrc to enable them
  • both can wrap/intercept commands

I think your log command argument modification could be done with a pre-log hook in addition to being done as an extension.

TL;DR: If you're writing in python there's little difference, and if you're not hooks are your only option.

Ry4an
Thanks for the important, albeit obvious (to me) difference. But how do you remove command argument in a hook? I tried a pre-log hook like this: `def prelogHook(ui, repo, **kwargs): print kwargs` and it only shows `{'args': 'log', 'hooktype': 'pre-log'}` when I default `log` to `log -g`.
Geoffrey Zheng
I'm not certain where, but I suspect there's a reference path to them through the ui object. In a shell hook you could just check the `$HG_OPTS` for incompatible options, remove `-g` if they're found, and re-run the `hg log` command with the new arg-set, and then return -1. Not totally elegant, but achieving the goal from a totally external hook.
Ry4an