mercurial/namespaces.py
author Sean Farley <sean.michael.farley@gmail.com>
Sun, 21 Dec 2014 14:34:07 -0800
changeset 23739 b8b246cffdee
parent 23738 3436e45de2fb
child 23760 50229b4c33be
permissions -rw-r--r--
namespaces: remove templatename method on the namespaces object Now that there is an object for each individual namespace, we use the templatename property on that object instead of the method on the collection of namespaces.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
23559
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
     1
from i18n import _
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
     2
from mercurial import util
23610
9266d1dd6a6e namespaces: generate template keyword when registering a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23608
diff changeset
     3
import templatekw
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
     4
23555
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     5
def tolist(val):
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     6
    """
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     7
    a convenience method to return an empty list instead of None
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     8
    """
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     9
    if val is None:
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
    10
        return []
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
    11
    else:
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
    12
        return [val]
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
    13
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    14
class namespaces(object):
23718
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    15
    """provides an interface to register and operate on multiple namespaces. See
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    16
    the namespace class below for details on the namespace object.
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    17
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    18
    """
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    19
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    20
    _names_version = 0
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    21
23561
3c2419e07df5 namespaces: remove weakref; always pass in repo
Ryan McElroy <rmcelroy@fb.com>
parents: 23559
diff changeset
    22
    def __init__(self):
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    23
        self._names = util.sortdict()
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    24
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    25
        # shorten the class name for less indentation
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    26
        ns = namespace
23562
59e703aecaf6 namespaces: add tags
Sean Farley <sean.michael.farley@gmail.com>
parents: 23561
diff changeset
    27
23558
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    28
        # we need current mercurial named objects (bookmarks, tags, and
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    29
        # branches) to be initialized somewhere, so that place is here
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    30
        n = ns("bookmarks", "bookmark",
23718
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    31
               lambda repo, name: tolist(repo._bookmarks.get(name)),
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    32
               lambda repo, name: repo.nodebookmarks(name))
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    33
        self.addnamespace(n)
23562
59e703aecaf6 namespaces: add tags
Sean Farley <sean.michael.farley@gmail.com>
parents: 23561
diff changeset
    34
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    35
        n = ns("tags", "tag",
23718
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    36
               lambda repo, name: tolist(repo._tagscache.tags.get(name)),
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    37
               lambda repo, name: repo.nodetags(name))
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    38
        self.addnamespace(n)
23558
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    39
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    40
        n = ns("branches", "branch",
23718
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    41
               lambda repo, name: tolist(repo.branchtip(name)),
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    42
               lambda repo, node: [repo[node].branch()])
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    43
        self.addnamespace(n)
23563
114992041625 namespaces: add branches
Sean Farley <sean.michael.farley@gmail.com>
parents: 23562
diff changeset
    44
23736
d7324c242c3f namespaces: add __getitem__ property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23718
diff changeset
    45
    def __getitem__(self, namespace):
d7324c242c3f namespaces: add __getitem__ property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23718
diff changeset
    46
        """returns the namespace object"""
d7324c242c3f namespaces: add __getitem__ property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23718
diff changeset
    47
        return self._names[namespace]
d7324c242c3f namespaces: add __getitem__ property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23718
diff changeset
    48
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    49
    def addnamespace(self, namespace, order=None):
23718
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    50
        """register a namespace
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    51
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    52
        namespace: the name to be registered (in plural form)
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    53
        order: optional argument to specify the order of namespaces
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    54
               (e.g. 'branches' should be listed before 'bookmarks')
23718
42908c3275c6 namespaces: update documentation and code indentation
Sean Farley <sean.michael.farley@gmail.com>
parents: 23717
diff changeset
    55
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    56
        """
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    57
        if order is not None:
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    58
            self._names.insert(order, namespace.name, namespace)
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    59
        else:
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    60
            self._names[namespace.name] = namespace
23559
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    61
23610
9266d1dd6a6e namespaces: generate template keyword when registering a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23608
diff changeset
    62
        # we only generate a template keyword if one does not already exist
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    63
        if namespace.name not in templatekw.keywords:
23610
9266d1dd6a6e namespaces: generate template keyword when registering a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23608
diff changeset
    64
            def generatekw(**args):
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    65
                return templatekw.shownames(namespace.name, **args)
23610
9266d1dd6a6e namespaces: generate template keyword when registering a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23608
diff changeset
    66
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    67
            templatekw.keywords[namespace.name] = generatekw
23610
9266d1dd6a6e namespaces: generate template keyword when registering a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23608
diff changeset
    68
23561
3c2419e07df5 namespaces: remove weakref; always pass in repo
Ryan McElroy <rmcelroy@fb.com>
parents: 23559
diff changeset
    69
    def singlenode(self, repo, name):
23559
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    70
        """
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    71
        Return the 'best' node for the given name. Best means the first node
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    72
        in the first nonempty list returned by a name-to-nodes mapping function
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    73
        in the defined precedence order.
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    74
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    75
        Raises a KeyError if there is no such node.
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    76
        """
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    77
        for ns, v in self._names.iteritems():
23717
d8663e6153c1 namespaces: use namespace object instead of dictionary
Sean Farley <sean.michael.farley@gmail.com>
parents: 23716
diff changeset
    78
            n = v.namemap(repo, name)
23559
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    79
            if n:
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    80
                # return max revision number
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    81
                if len(n) > 1:
23561
3c2419e07df5 namespaces: remove weakref; always pass in repo
Ryan McElroy <rmcelroy@fb.com>
parents: 23559
diff changeset
    82
                    cl = repo.changelog
23559
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    83
                    maxrev = max(cl.rev(node) for node in n)
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    84
                    return cl.node(maxrev)
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    85
                return n[0]
3b3a962e3677 namespaces: add a method to the first matching node for a given name
Sean Farley <sean.michael.farley@gmail.com>
parents: 23558
diff changeset
    86
        raise KeyError(_('no such name: %s') % name)
23606
80e3cbe227d1 namespaces: add method to get template name of namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23605
diff changeset
    87
23715
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    88
class namespace(object):
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    89
    """provides an interface to a namespace
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    90
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    91
    Namespaces are basically generic many-to-many mapping between some
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    92
    (namespaced) names and nodes. The goal here is to control the pollution of
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    93
    jamming things into tags or bookmarks (in extension-land) and to simplify
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    94
    internal bits of mercurial: log output, tab completion, etc.
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    95
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    96
    More precisely, we define a mapping of names to nodes, and a mapping from
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    97
    nodes to names. Each mapping returns a list.
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    98
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
    99
    Furthermore, each name mapping will be passed a name to lookup which might
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   100
    not be in its domain. In this case, each method should return an empty list
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   101
    and not raise an error.
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   102
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   103
    This namespace object will define the properties we need:
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   104
      'name': the namespace (plural form)
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   105
      'templatename': name to use for templating (usually the singular form
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   106
                      of the plural namespace name)
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   107
      'namemap': function that takes a name and returns a list of nodes
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   108
      'nodemap': function that takes a node and returns a list of names
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   109
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   110
    """
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   111
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   112
    def __init__(self, name, templatename, namemap, nodemap):
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   113
        """create a namespace
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   114
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   115
        name: the namespace to be registered (in plural form)
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   116
        templatename: the name to use for templating
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   117
        namemap: function that inputs a node, output name(s)
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   118
        nodemap: function that inputs a name, output node(s)
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   119
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   120
        """
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   121
        self.name = name
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   122
        self.templatename = templatename
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   123
        self.namemap = namemap
eee55c09010a namespaces: add a namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23610
diff changeset
   124
        self.nodemap = nodemap
23716
f4828a8f6ae9 namespaces: copy implementation to new namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23715
diff changeset
   125
f4828a8f6ae9 namespaces: copy implementation to new namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23715
diff changeset
   126
    def names(self, repo, node):
f4828a8f6ae9 namespaces: copy implementation to new namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23715
diff changeset
   127
        """method that returns a (sorted) list of names in a namespace that
f4828a8f6ae9 namespaces: copy implementation to new namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23715
diff changeset
   128
        match a given node"""
f4828a8f6ae9 namespaces: copy implementation to new namespace object
Sean Farley <sean.michael.farley@gmail.com>
parents: 23715
diff changeset
   129
        return sorted(self.nodemap(repo, node))