tests/test-extensions-wrapfunction.py
author Martin von Zweigbergk <martinvonz@google.com>
Mon, 06 Dec 2021 23:17:43 -0800
changeset 48507 58a3be48ddd2
parent 43076 2372284d9457
child 48875 6000f5b25c9b
permissions -rw-r--r--
simplemerge: stop merging file flags As 384df4db6520 (merge: merge file flags together with file content, 2013-01-09) explains, we shouldn't do a 3-way merge of the symlink. However, since 84614212ae39 (flags: actually merge flags in simplemerge, 2020-05-16), we do that in `simplemerge.simplemerge()`. What's more, the merging of the executable flag there isn't actually necessary; it was made a no-op by the very next commit, i.e. 4234c9af515d (flags: read flag from dirstate/disk for workingcopyctx (issue5743), 2020-05-16). I found the overall flag-merging code (not the bit in `simplemerge.py`) very hard to follow, but I think I now finally understand how it works. `mergestate.resolve()` calculates the merged file flags and sets them on the local side of the merge (confusingly by calling `_restore_backup()`). Then it calls `filemerge.filemerge()`, which in turn calls `simplemerge.simplemerge()` (if premerge is enabled). That means that the flags on the local side `fcs.flags()` are already correct when the flag-merging code in `simplemerge.simplemerge()` runs. Interestingly, that code still works when the local side already has the merged value, it just doesn't change the value. Here's a truth table to explain why: ``` BLOMCAR 0000000 0011111 0101011 0111111 1000000 1010000 1100000 1111101 ``` B: Base L: Local O: Other M: Merged flags from `mergestate.resolve()`, i.e. what's called "local" when we get to `simplemerge.simplemerge()` C: `commonflags` in `simplemerge.simplemerge()`, i.e. `M & O` A: `addedflags` in `simplemerge.simplemerge()`, i.e. `(M ^ O) - B` R: Re-merged flags `simplemerge.simplemerge()`, i.e. `C | A` As you can see, the re-merged flags are always unchanged compared to the initial merged flags (R equals M). Therefore, this patch effectively backs out 84614212ae39. (I might later refactor this code to have the flags explicitly passed in.) `simplemerge.simplemerge()` is also called from `contrib/simplemerge.py`, but that code never passes any flags. Differential Revision: https://phab.mercurial-scm.org/D11879
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
     1
from __future__ import absolute_import, print_function
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
     2
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
     3
from mercurial import extensions
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
     4
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
     5
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
     6
def genwrapper(x):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
     7
    def f(orig, *args, **kwds):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
     8
        return [x] + orig(*args, **kwds)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
     9
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    10
    f.x = x
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    11
    return f
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    12
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    13
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    14
def getid(wrapper):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    15
    return getattr(wrapper, 'x', '-')
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    16
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    17
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    18
wrappers = [genwrapper(i) for i in range(5)]
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    19
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    20
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    21
class dummyclass(object):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    22
    def getstack(self):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    23
        return ['orig']
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    24
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    25
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    26
dummy = dummyclass()
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    27
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    28
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    29
def batchwrap(wrappers):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    30
    for w in wrappers:
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    31
        extensions.wrapfunction(dummy, 'getstack', w)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    32
        print('wrap %d: %s' % (getid(w), dummy.getstack()))
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    33
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    34
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    35
def batchunwrap(wrappers):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    36
    for w in wrappers:
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    37
        result = None
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    38
        try:
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    39
            result = extensions.unwrapfunction(dummy, 'getstack', w)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    40
            msg = str(dummy.getstack())
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    41
        except (ValueError, IndexError) as e:
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    42
            msg = e.__class__.__name__
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    43
        print('unwrap %s: %s: %s' % (getid(w), getid(result), msg))
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    44
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    45
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents:
diff changeset
    46
batchwrap(wrappers + [wrappers[0]])
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    47
batchunwrap(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    48
    [
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    49
        (wrappers[i] if i is not None and i >= 0 else None)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    50
        for i in [3, None, 0, 4, 0, 2, 1, None]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    51
    ]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    52
)
34014
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    53
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    54
wrap0 = extensions.wrappedfunction(dummy, 'getstack', wrappers[0])
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    55
wrap1 = extensions.wrappedfunction(dummy, 'getstack', wrappers[1])
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    56
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    57
# Use them in a different order from how they were created to check that
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    58
# the wrapping happens in __enter__, not in __init__
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    59
print('context manager', dummy.getstack())
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    60
with wrap1:
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    61
    print('context manager', dummy.getstack())
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    62
    with wrap0:
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    63
        print('context manager', dummy.getstack())
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    64
        # Bad programmer forgets to unwrap the function, but the context
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    65
        # managers still unwrap their wrappings.
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    66
        extensions.wrapfunction(dummy, 'getstack', wrappers[2])
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    67
        print('context manager', dummy.getstack())
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    68
    print('context manager', dummy.getstack())
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 29765
diff changeset
    69
print('context manager', dummy.getstack())
34128
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    70
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    71
# Wrap callable object which has no __name__
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    72
class callableobj(object):
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    73
    def __call__(self):
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    74
        return ['orig']
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    75
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37938
diff changeset
    76
34128
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    77
dummy.cobj = callableobj()
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    78
extensions.wrapfunction(dummy, 'cobj', wrappers[0])
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34014
diff changeset
    79
print('wrap callable object', dummy.cobj())