hgext/beautifygraph.py
author Gregory Szorc <gregory.szorc@gmail.com>
Tue, 18 Sep 2018 15:29:42 -0700
changeset 39764 e4e881572382
parent 39262 5b9f116104f9
child 40457 c2a0bc6412db
permissions -rw-r--r--
localrepo: iteratively derive local repository type This commit implements the dynamic local repository type derivation that was explained in the recent commit bfeab472e3c0 "localrepo: create new function for instantiating a local repo object." Instead of a static localrepository class/type which must be customized after construction, we now dynamically construct a type by building up base classes/types to represent specific repository interfaces. Conceptually, the end state is similar to what was happening when various extensions would monkeypatch the __class__ of newly-constructed repo instances. However, the approach is inverted. Instead of making the instance then customizing it, we do the customization up front by influencing the behavior of the type then we instantiate that custom type. This approach gives us much more flexibility. For example, we can use completely separate classes for implementing different aspects of the repository. For example, we could have one class representing revlog-based file storage and another representing non-revlog based file storage. When then choose which implementation to use based on the presence of repo requirements. A concern with this approach is that it creates a lot more types and complexity and that complexity adds overhead. Yes, it is true that this approach will result in more types being created. Yes, this is more complicated than traditional "instantiate a static type." However, I believe the alternatives to supporting alternate storage backends are just as complicated. (Before I arrived at this solution, I had patches storing factory functions on local repo instances for e.g. constructing a file storage instance. We ended up having a handful of these. And this was logically identical to assigning custom methods. Since we were logically changing the type of the instance, I figured it would be better to just use specialized types instead of introducing levels of abstraction at run-time.) On the performance front, I don't believe that having N base classes has any significant performance overhead compared to just a single base class. Intuition says that Python will need to iterate the base classes to find an attribute. However, CPython caches method lookups: as long as the __class__ or MRO isn't changing, method attribute lookup should be constant time after first access. And non-method attributes are stored in __dict__, of which there is only 1 per object, so the number of base classes for __dict__ is irrelevant. Anyway, this commit splits up the monolithic completelocalrepository interface into sub-interfaces: 1 for file storage and 1 representing everything else. We've taught ``makelocalrepository()`` to call a series of factory functions which will produce types implementing specific interfaces. It then calls type() to create a new type from the built-up list of base types. This commit should be considered a start and not the end state. I suspect we'll hit a number of problems as we start to implement alternate storage backends: * Passing custom arguments to __init__ and setting custom attributes on __dict__. * Customizing the set of interfaces that are needed. e.g. the "readonly" intent could translate to not requesting an interface providing methods related to writing. * More ergonomic way for extensions to insert themselves so their callbacks aren't unconditionally called. * Wanting to modify vfs instances, other arguments passed to __init__. That being said, this code is usable in its current state and I'm convinced future commits will demonstrate the value in this approach. Differential Revision: https://phab.mercurial-scm.org/D4642
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38340
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     1
# -*- coding: UTF-8 -*-
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     2
# beautifygraph.py - improve graph output by using Unicode characters
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     3
#
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     4
# Copyright 2018 John Stiles <johnstiles@gmail.com>
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     5
#
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     6
# This software may be used and distributed according to the terms of the
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     7
# GNU General Public License version 2 or any later version.
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     8
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
     9
'''beautify log -G output by using Unicode characters (EXPERIMENTAL)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    10
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    11
   A terminal with UTF-8 support and monospace narrow text are required.
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    12
'''
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    13
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    14
from __future__ import absolute_import
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    15
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    16
from mercurial.i18n import _
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    17
from mercurial import (
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    18
    encoding,
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    19
    extensions,
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    20
    graphmod,
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38340
diff changeset
    21
    pycompat,
38340
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    22
    templatekw,
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    23
)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    24
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    25
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    26
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    27
# be specifying the version(s) of Mercurial they are tested with, or
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    28
# leave the attribute unspecified.
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    29
testedwith = 'ships-with-hg-core'
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    30
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    31
def prettyedge(before, edge, after):
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    32
    if edge == '~':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    33
        return '\xE2\x95\xA7' # U+2567 ╧
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    34
    if edge == 'X':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    35
        return '\xE2\x95\xB3' # U+2573 ╳
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    36
    if edge == '/':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    37
        return '\xE2\x95\xB1' # U+2571 ╱
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    38
    if edge == '-':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    39
        return '\xE2\x94\x80' # U+2500 ─
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    40
    if edge == '|':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    41
        return '\xE2\x94\x82' # U+2502 │
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    42
    if edge == ':':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    43
        return '\xE2\x94\x86' # U+2506 ┆
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    44
    if edge == '\\':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    45
        return '\xE2\x95\xB2' # U+2572 ╲
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    46
    if edge == '+':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    47
        if before == ' ' and not after  == ' ':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    48
            return '\xE2\x94\x9C' # U+251C ├
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    49
        if after  == ' ' and not before == ' ':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    50
            return '\xE2\x94\xA4' # U+2524 ┤
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    51
        return '\xE2\x94\xBC' # U+253C ┼
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    52
    return edge
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    53
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    54
def convertedges(line):
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    55
    line = ' %s ' % line
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    56
    pretty = []
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38340
diff changeset
    57
    for idx in pycompat.xrange(len(line) - 2):
39054
de3a9d7ec1c2 beautifygraph: use slicing instead of subscripting on bytestr
Augie Fackler <augie@google.com>
parents: 39053
diff changeset
    58
        pretty.append(prettyedge(line[idx:idx + 1],
de3a9d7ec1c2 beautifygraph: use slicing instead of subscripting on bytestr
Augie Fackler <augie@google.com>
parents: 39053
diff changeset
    59
                                 line[idx + 1:idx + 2],
de3a9d7ec1c2 beautifygraph: use slicing instead of subscripting on bytestr
Augie Fackler <augie@google.com>
parents: 39053
diff changeset
    60
                                 line[idx + 2:idx + 3]))
38340
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    61
    return ''.join(pretty)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    62
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    63
def getprettygraphnode(orig, *args, **kwargs):
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    64
    node = orig(*args, **kwargs)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    65
    if node == 'o':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    66
        return '\xE2\x97\x8B' # U+25CB ○
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    67
    if node == '@':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    68
        return '\xE2\x97\x8D' # U+25CD ◍
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    69
    if node == '*':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    70
        return '\xE2\x88\x97' # U+2217 ∗
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    71
    if node == 'x':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    72
        return '\xE2\x97\x8C' # U+25CC ◌
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    73
    if node == '_':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    74
        return '\xE2\x95\xA4' # U+2564 ╤
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    75
    return node
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    76
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    77
def outputprettygraph(orig, ui, graph, *args, **kwargs):
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    78
    (edges, text) = zip(*graph)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    79
    graph = zip([convertedges(e) for e in edges], text)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    80
    return orig(ui, graph, *args, **kwargs)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    81
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    82
def extsetup(ui):
39198
362cb82385ea beautifygraph: don't warn about busted terminal if HGPLAIN is set
Augie Fackler <augie@google.com>
parents: 38340
diff changeset
    83
    if ui.plain('graph'):
362cb82385ea beautifygraph: don't warn about busted terminal if HGPLAIN is set
Augie Fackler <augie@google.com>
parents: 38340
diff changeset
    84
        return
362cb82385ea beautifygraph: don't warn about busted terminal if HGPLAIN is set
Augie Fackler <augie@google.com>
parents: 38340
diff changeset
    85
38340
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    86
    if encoding.encoding != 'UTF-8':
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    87
        ui.warn(_('beautifygraph: unsupported encoding, UTF-8 required\n'))
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    88
        return
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    89
39053
836433f3bdd6 beautifygraph: use sysstr for checking encoding._wide
Augie Fackler <augie@google.com>
parents: 38783
diff changeset
    90
    if r'A' in encoding._wide:
38340
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    91
        ui.warn(_('beautifygraph: unsupported terminal settings, '
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    92
                  'monospace narrow text required\n'))
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    93
        return
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    94
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    95
    extensions.wrapfunction(graphmod, 'outputgraph', outputprettygraph)
9abe91a503da graph: improve graph output by using Unicode characters
John Stiles <johnstiles@gmail.com>
parents:
diff changeset
    96
    extensions.wrapfunction(templatekw, 'getgraphnode', getprettygraphnode)