[PATCH 3 of 3] extensions: add unwrapfunction to undo wrapfunction

Yuya Nishihara yuya at tcha.org
Sun Jul 3 04:11:00 EDT 2016


On Fri, 1 Jul 2016 13:09:05 +0100, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <quark at fb.com>
> # Date 1467374153 -3600
> #      Fri Jul 01 12:55:53 2016 +0100
> # Node ID 7a68b01000d12e1795d142cdb32fdd62a5ffc8cb
> # Parent  de798903374922317eb2cbca9733ba0cea415780
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #              hg pull https://bitbucket.org/quark-zju/hg-draft -r 7a68b01000d1
> extensions: add unwrapfunction to undo wrapfunction
> 
> Before this patch, we don't have a safe way to undo a wrapfunction because
> other extensions may wrap the same function and calling setattr will undo
> them accidentally.
> 
> This patch adds an "unwrapfunction" to address the issue. It removes the
> wrapper from the wrapper chain, and re-wraps everything, which is not the
> most efficient but short and easy to understand. We can revisit the code
> if we have perf issues with long chains.
> 
> The "undo" feature is useful in cases like wrapping a function just in
> a scope. And it allows extensions running with chg to add and remove their
> wrappers dynamically in reposetup without starting a new chgserver.
> 
> diff --git a/mercurial/extensions.py b/mercurial/extensions.py
> --- a/mercurial/extensions.py
> +++ b/mercurial/extensions.py
> @@ -303,6 +303,19 @@ def wrapfunction(container, funcname, wr
>      setattr(container, funcname, wrap)
>      return origfn
>  
> +def unwrapfunction(container, funcname, wrapper):
> +    '''Undo wrapfunction
> +
> +    Pass the same arguments with wrapfunction to undo a wrap.
> +    Handles stacked wrappers correctly.
> +    '''

"unwrap" sounds different to me from what this function does. I expected it
would do unwrapfunction(container, funcname) -> last_wrapper. Any idea?

> +    chain = getwrapperchain(container, funcname)
> +    origfn = chain.pop()
> +    chain.remove(wrapper)
> +    setattr(container, funcname, origfn)
> +    for wrapper in reversed(chain):
> +        wrapfunction(container, funcname, wrapper)

I noticed we can't apply unwrapfunction() to wrapped commands even though
they have _origfunc and _unboundwrapper attributes. But that should be okay
because wrapcommand() has distinct interface from wrapfunction().


More information about the Mercurial-devel mailing list