Overload the pull command in a Hg extension

252 views Asked by At

I am trying to debug a Mercurial extension. This extension adds some code that should be executed when a pull is performed. The original author setup this hook by changing the class of the repository object.

Here is the relevant code (which is actually a valid Mercurial extension):

def reposetup(ui, repo):
    class myrepo(repo.__class__):
        def pull(self, remote, heads=None, force=False):
            print "pull called"
            return super(myrepo, self).pull(remote, heads, force)

    print "reposetup called"
    if repo.local():
        print "repo is local"
        repo.__class__ = myrepo

When I perform a hg pull with this extension enabled, here is the output:

# hg pull
reposetup called
repo is local
pulling from ssh://hgbox/myrepo
reposetup called
searching for changes
no changes found

Is this a reasonable way to inject the code of the extension in the pull command? Why is the "pull called" statement never reached?

I use Mercurial 3.4.1 on Windows 7 with python 2.7.5.

1

There are 1 answers

4
ryanmce On

According to the code (mercurial/extensions.py), this is the only reasonable way to extend the repository object (https://www.mercurial-scm.org/repo/hg/file/ff5172c83002/mercurial/extensions.py#l227).

However, I looked at the code and the localrepo object does not appear to have a pull method at this point, so I suspect this is why your "pull called" print statement never shows up -- nothing calls it because it's not expected to exist!

There are better ways to inject code into pulls, depending on what you're trying to accomplish. For example, if you simply want to run something whenever the a pull is issued, prefer instead to wrap the exchange.pull function:

extensions.wrapfunction(exchange, 'pull', my_pull_function)

For your specific use case, I'd suggest creating a method with the following code:

def expull(orig, repo, remote, *args, **kwargs):
    transferprojrc(repo.ui, repo, remote)
    return orig(repo, remote, *args, **kwargs)

In the extsetup method, add a line like this:

extensions.wrapfunction(exchange, 'pull', expull)

Finally, in the reposetup method, you can remove the projrcrepo class stuff entirely. Hopefully that will get you the behavior you're looking for.