Differences in functionality in inprocess hooks for CLI and API

Chris Scott Chris.Scott at mmodal.com
Mon Oct 31 14:13:05 UTC 2011


> > Should my hooks be GPL?
>
> If your hook is a shell script using the command line API, then my opinion is "definitely not".
>
> If your hook is written in Python, then my opinion is "very likely".

This is in response to Matt's response in "Re: Mercurial in-process hook, GPLv2+ "derived work" or not?", but I thought this question sufficiently different to start another thread.  In the context of this thread, I will use "CLI" to indicate the command-line API and "API" to indicate the internal in-process API.

Question:

* If an in-process hook only uses the CLI (via popen/subprocess) is it still counted as a derived work?

Presumably since it's "linked" into hg, then yes, but there are a number of reasons for wanting to write an in-process hook.  First and foremost, is the ability to write cross-platform hooks without having to have bash or python installed as a pre-req, (i.e. Windows).  Also, having access to the ui object to give feedback to user on controlling hooks is very convenient.

Secondly, during my experimentation it seems like there were some functionality differences in what you are able to do in with the API that isn't (apparently) accessible via the CLI.

For example, take the following pretxnchangegroup hook that tries to get the commit message of every inbound changeset:

def checkAllCommitMessage(ui, repo, **kwargs):
    # node is the first incoming changeset
    node = kwargs["node"]
    #get the commit messages for all of the changesets in the push
    p = subprocess.Popen('hg log -r {0}: --template "{{desc}}\\n"'.format(node), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (out,err) = p.communicate()
    for line in out:
       handleMessage(line)
    ...

This works when the hook source is push or pull (i.e. a local operation), but fails to give any output when the source is serve (i.e. a remote ssh push).  Two things were different in my experimentation, first the PWD was the user's home directory and thus failed to find a repo, but even when run in the repository, the log command doesn't return the incoming changesets.  I had avoided using the API since its use is discouraged, but wound up with the following:


def checkAllCommitMessage(ui, repo, node, **kwargs):
    for rev in xrange(repo[node].rev(), len(repo)):
	message = repo[rev].description()
      handleMessage(message)
      ...

The "for rev in xrange" wasn't clearly documented and it took trudging through the mailing lists to figure out how to do it.

Am I missing something on the CLI side, or is it not currently possible to do?  If not, shouldn't there be an easy way for people to write portable hooks without having to resort to using the not-very-well documented or stable API?  I don't really care about GPL infecting my hooks since they are very simple, but it'd be nice to be able to use the CLI instead of the API.

~Chris



More information about the Mercurial mailing list