hgext/directaccess.py
author Pierre-Yves David <pierre-yves.david@fb.com>
Mon, 01 Jun 2015 10:58:50 -0700
changeset 1353 935508184d47
parent 1347 b00c2fe51ac8
child 1360 5c13945b32fc
permissions -rw-r--r--
test: adapt test to less frequent branch warning The 701df761aa94 changeset in mercurial core made the branch warning issue only for the first branch created. We adapt the tests to reflect this change.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1339
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     1
""" This extension provides direct access
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     2
It is the ability to refer and access hidden sha in commands provided that you 
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     3
know their value.
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     4
For example hg log -r xxx where xxx is a commit has should work whether xxx is
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     5
hidden or not as we assume that the user knows what he is doing when referring
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     6
to xxx.
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     7
"""
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     8
from mercurial import extensions
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
     9
from mercurial import cmdutil
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    10
from mercurial import repoview
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    11
from mercurial import branchmap
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    12
from mercurial import revset
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    13
from mercurial import error
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    14
from mercurial import commands
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    15
from mercurial.i18n import _
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    16
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    17
cmdtable = {}
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    18
command = cmdutil.command(cmdtable)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    19
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    20
# List of commands where no warning is shown for direct access
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    21
directaccesslevel = [
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    22
    # warning or not, extension (None if core), command name
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    23
    (False, None, 'update'), 
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    24
    (False, None, 'export'),
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    25
    (True,  'rebase', 'rebase'),
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    26
    (False,  'evolve', 'prune'),
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    27
]
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    28
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    29
def reposetup(ui, repo):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    30
    repo._explicitaccess = set()
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    31
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    32
def _computehidden(repo):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    33
    hidden = repoview.computehidden(repo)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    34
    cl = repo.changelog
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    35
    dynamic = hidden & repo._explicitaccess
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    36
    if dynamic:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    37
        blocked = cl.ancestors(dynamic, inclusive=True)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    38
        hidden = frozenset(r for r in hidden if r not in blocked)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    39
    return hidden
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    40
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    41
def setupdirectaccess():
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    42
    """ Add two new filtername that behave like visible to provide direct access
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    43
    and direct access with warning. Wraps the commands to setup direct access """
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    44
    repoview.filtertable.update({'visible-directaccess-nowarn': _computehidden})
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    45
    repoview.filtertable.update({'visible-directaccess-warn': _computehidden})
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    46
    branchmap.subsettable['visible-directaccess-nowarn'] = 'visible'
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    47
    branchmap.subsettable['visible-directaccess-warn'] = 'visible'
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    48
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    49
    for warn, ext, cmd in directaccesslevel:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    50
        try:
1347
b00c2fe51ac8 directaccess: don't crash when evolve is not loaded
Laurent Charignon <lcharignon@fb.com>
parents: 1339
diff changeset
    51
            cmdtable = extensions.find(ext).cmdtable if ext else commands.table
b00c2fe51ac8 directaccess: don't crash when evolve is not loaded
Laurent Charignon <lcharignon@fb.com>
parents: 1339
diff changeset
    52
            wrapper = wrapwithwarning if warn else wrapwithoutwarning
1339
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    53
            extensions.wrapcommand(cmdtable, cmd, wrapper)
1347
b00c2fe51ac8 directaccess: don't crash when evolve is not loaded
Laurent Charignon <lcharignon@fb.com>
parents: 1339
diff changeset
    54
        except (error.UnknownCommand, KeyError):
1339
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    55
            pass
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    56
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    57
def wrapwithoutwarning(orig, ui, repo, *args, **kwargs):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    58
    if repo and repo.filtername == 'visible':
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    59
        repo = repo.filtered("visible-directaccess-nowarn")
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    60
    return orig(ui, repo, *args, **kwargs)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    61
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    62
def wrapwithwarning(orig, ui, repo, *args, **kwargs):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    63
    if repo and repo.filtername == 'visible':
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    64
        repo = repo.filtered("visible-directaccess-warn")
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    65
    return orig(ui, repo, *args, **kwargs)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    66
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    67
def extsetup(ui):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    68
    extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    69
    setupdirectaccess()
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    70
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    71
def gethashsymbols(tree):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    72
    # Returns the list of symbols of the tree that look like hashes
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    73
    # for example for the revset 3::abe3ff it will return ('abe3ff')
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    74
    if not tree:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    75
        return []
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    76
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    77
    if len(tree) == 2 and tree[0] == "symbol":
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    78
        try:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    79
            int(tree[1])
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    80
            return []
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    81
        except ValueError as e:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    82
            return [tree[1]]
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    83
    elif len(tree) == 3:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    84
        return gethashsymbols(tree[1]) + gethashsymbols(tree[2])
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    85
    else:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    86
        return []
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    87
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    88
def _posttreebuilthook(orig, tree, repo):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    89
    # This is use to enabled direct hash access
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    90
    # We extract the symbols that look like hashes and add them to the
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    91
    # explicitaccess set
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    92
    orig(tree, repo)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    93
    filternm = ""
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    94
    if repo is not None:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    95
        filternm = repo.filtername
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    96
    if filternm is not None and filternm.startswith('visible-directaccess'):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    97
        prelength = len(repo._explicitaccess)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    98
        accessbefore = set(repo._explicitaccess)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
    99
        repo.symbols = gethashsymbols(tree)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   100
        cl = repo.unfiltered().changelog
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   101
        for node in repo.symbols:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   102
            try:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   103
                node = cl._partialmatch(node)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   104
            except error.LookupError:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   105
                node = None
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   106
            if node is not None:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   107
                rev = cl.rev(node)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   108
                if rev not in repo.changelog:
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   109
                    repo._explicitaccess.add(rev)
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   110
        if prelength != len(repo._explicitaccess):
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   111
            if repo.filtername != 'visible-directaccess-nowarn':
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   112
                unhiddencommits = repo._explicitaccess - accessbefore
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   113
                repo.ui.warn( _("Warning: accessing hidden changesets %s " 
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   114
                                "for write operation\n") % 
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   115
                                (",".join([str(repo.unfiltered()[l]) 
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   116
                                    for l in unhiddencommits])))
0e2eb196923a inhibit: create direct access extension
Laurent Charignon <lcharignon@fb.com>
parents:
diff changeset
   117
            repo.invalidatevolatilesets()