wrapfunction: use functools.partial if possible
Every `extensions.bind` call inserts a frame in traceback:
... in closure
return func(*(args + a), **kw)
which makes traceback noisy.
The Python stdlib has a `functools.partial` which is backed by C code and
does not pollute traceback. However it does not support instancemethod and
sets `args` attribute which could be problematic for alias handling.
This patch makes `wrapfunction` use `functools.partial` if we are wrapping a
function directly exported by a module (so it's impossible to be a class or
instance method), and special handles `wrapfunction` results so alias
handling code could handle `args` just fine.
As an example, `hg rebase -s . -d . --traceback` got 6 lines removed in my
setup:
File "hg/mercurial/dispatch.py", line 898, in _dispatch
cmdpats, cmdoptions)
-File "hg/mercurial/extensions.py", line 333, in closure
- return func(*(args + a), **kw)
File "hg/hgext/journal.py", line 84, in runcommand
return orig(lui, repo, cmd, fullargs, *args)
-File "hg/mercurial/extensions.py", line 333, in closure
- return func(*(args + a), **kw)
File "fb-hgext/hgext3rd/fbamend/hiddenoverride.py", line 119, in runcommand
result = orig(lui, repo, cmd, fullargs, *args)
File "hg/mercurial/dispatch.py", line 660, in runcommand
ret = _runcommand(ui, options, cmd, d)
-File "hg/mercurial/extensions.py", line 333, in closure
- return func(*(args + a), **kw)
File "hg/hgext/pager.py", line 69, in pagecmd
return orig(ui, options, cmd, cmdfunc)
....
Differential Revision: https://phab.mercurial-scm.org/D632
#require execbit
Create extension that can disable exec checks:
$ cat > noexec.py <<EOF
> from mercurial import extensions, util
> def setflags(orig, f, l, x):
> pass
> def checkexec(orig, path):
> return False
> def extsetup(ui):
> extensions.wrapfunction(util, 'setflags', setflags)
> extensions.wrapfunction(util, 'checkexec', checkexec)
> EOF
$ hg init unix-repo
$ cd unix-repo
$ touch a
$ hg add a
$ hg commit -m 'unix: add a'
$ hg clone . ../win-repo
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ chmod +x a
$ hg commit -m 'unix: chmod a'
$ hg manifest -v
755 * a
$ cd ../win-repo
$ touch b
$ hg add b
$ hg commit -m 'win: add b'
$ hg manifest -v
644 a
644 b
$ hg pull
pulling from $TESTTMP/unix-repo
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 0 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
$ hg manifest -v -r tip
755 * a
Simulate a Windows merge:
$ hg --config extensions.n=$TESTTMP/noexec.py merge --debug
searching for copies back to rev 1
unmatched files in local:
b
resolving manifests
branchmerge: True, force: False, partial: False
ancestor: a03b0deabf2b, local: d6fa54f68ae1+, remote: 2d8bcf2dda39
a: update permissions -> e
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
Simulate a Windows commit:
$ hg --config extensions.n=$TESTTMP/noexec.py commit -m 'win: merge'
$ hg manifest -v
755 * a
644 b
$ cd ..