hgext/directaccess.py
author Laurent Charignon <lcharignon@fb.com>
Fri, 22 May 2015 10:38:16 -0700
changeset 1347 b00c2fe51ac8
parent 1339 0e2eb196923a
child 1360 5c13945b32fc
permissions -rw-r--r--
directaccess: don't crash when evolve is not loaded Before this patch, when evolve was not loaded direct access was crashing. This patch catches the error and prevents the crash.
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()