4

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.)

Niall C.
  • 10,878
  • 7
  • 69
  • 61
Geoffrey Zheng
  • 6,562
  • 2
  • 38
  • 47

1 Answers1

4

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 Brase
  • 78,112
  • 7
  • 148
  • 169
  • 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 Oct 04 '10 at 19:09
  • 1
    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 Brase Oct 05 '10 at 02:14