mercurial/namespaces.py
author Sean Farley <sean.michael.farley@gmail.com>
Sun, 14 Dec 2014 18:54:50 -0800
changeset 23608 807ee1a02bb0
parent 23607 0fd778ef0f61
child 23610 9266d1dd6a6e
permissions -rw-r--r--
namespaces: add names method to return list of names for a given node In the previous patch, we added a node-to-name map property. This patch just exposes that interface to the api.
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
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
     3
23555
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     4
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
     5
    """
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     6
    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
     7
    """
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
     8
    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
     9
        return []
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
    10
    else:
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
    11
        return [val]
f08f6a7d4d5f namespaces: add a function to turn single results into lists
Sean Farley <sean.michael.farley@gmail.com>
parents: 23554
diff changeset
    12
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    13
class namespaces(object):
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    14
    """
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    15
    provides an interface to register a generic many-to-many mapping between
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    16
    some (namespaced) names and nodes. The goal here is to control the
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    17
    pollution of jamming things into tags or bookmarks (in extension-land) and
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    18
    to simplify internal bits of mercurial: log output, tab completion, etc.
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    19
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    20
    More precisely, we define a list of names (the namespace), a mapping of
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    21
    names to nodes, and a mapping from nodes to names. Each mapping
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    22
    returns a list of nodes.
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    23
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    24
    Furthermore, each name mapping will be passed a name to lookup which might
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    25
    not be in its domain. In this case, each method should return an empty list
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    26
    and not raise an error.
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    27
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    28
    We'll have a dictionary '_names' where each key is a namespace and
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    29
    its value is a dictionary of functions:
23605
4c4c967814ef namespaces: add template name of a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23563
diff changeset
    30
      'templatename': name to use for templating (usually the singular form
4c4c967814ef namespaces: add template name of a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23563
diff changeset
    31
                      of the plural namespace name)
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    32
      'namemap': function that takes a name and returns a list of nodes
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    33
      'nodemap': function that takes a node and returns a list of names
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    34
    """
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    35
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    36
    _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
    37
23561
3c2419e07df5 namespaces: remove weakref; always pass in repo
Ryan McElroy <rmcelroy@fb.com>
parents: 23559
diff changeset
    38
    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
    39
        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
    40
23562
59e703aecaf6 namespaces: add tags
Sean Farley <sean.michael.farley@gmail.com>
parents: 23561
diff changeset
    41
        addns = self.addnamespace
59e703aecaf6 namespaces: add tags
Sean Farley <sean.michael.farley@gmail.com>
parents: 23561
diff changeset
    42
23558
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    43
        # 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
    44
        # branches) to be initialized somewhere, so that place is here
23605
4c4c967814ef namespaces: add template name of a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23563
diff changeset
    45
        addns("bookmarks", "bookmark",
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    46
              lambda repo, name: tolist(repo._bookmarks.get(name)),
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    47
              lambda repo, name: repo.nodebookmarks(name))
23562
59e703aecaf6 namespaces: add tags
Sean Farley <sean.michael.farley@gmail.com>
parents: 23561
diff changeset
    48
23605
4c4c967814ef namespaces: add template name of a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23563
diff changeset
    49
        addns("tags", "tag",
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    50
              lambda repo, name: tolist(repo._tagscache.tags.get(name)),
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    51
              lambda repo, name: repo.nodetags(name))
23558
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    52
23605
4c4c967814ef namespaces: add template name of a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23563
diff changeset
    53
        addns("branches", "branch",
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    54
              lambda repo, name: tolist(repo.branchtip(name)),
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    55
              lambda repo, node: [repo[node].branch()])
23563
114992041625 namespaces: add branches
Sean Farley <sean.michael.farley@gmail.com>
parents: 23562
diff changeset
    56
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    57
    def addnamespace(self, namespace, templatename, namemap, nodemap,
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    58
                     order=None):
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    59
        """
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    60
        register a namespace
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    61
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    62
        namespace: the name to be registered (in plural form)
23605
4c4c967814ef namespaces: add template name of a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23563
diff changeset
    63
        templatename: the name to use for templating
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    64
        namemap: function that inputs a node, output name(s)
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    65
        nodemap: function that inputs a name, output node(s)
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    66
        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
    67
               (e.g. 'branches' should be listed before 'bookmarks')
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    68
        """
23605
4c4c967814ef namespaces: add template name of a namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23563
diff changeset
    69
        val = {'templatename': templatename,
23607
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    70
               'namemap': namemap,
0fd778ef0f61 namespaces: add nodemap property
Sean Farley <sean.michael.farley@gmail.com>
parents: 23606
diff changeset
    71
               'nodemap': nodemap}
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    72
        if order is not None:
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    73
            self._names.insert(order, namespace, val)
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    74
        else:
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    75
            self._names[namespace] = val
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
    76
23561
3c2419e07df5 namespaces: remove weakref; always pass in repo
Ryan McElroy <rmcelroy@fb.com>
parents: 23559
diff changeset
    77
    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
    78
        """
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
        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
    80
        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
    81
        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
    82
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
        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
    84
        """
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
        for ns, v in self._names.iteritems():
23561
3c2419e07df5 namespaces: remove weakref; always pass in repo
Ryan McElroy <rmcelroy@fb.com>
parents: 23559
diff changeset
    86
            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
    87
            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
    88
                # 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
    89
                if len(n) > 1:
23561
3c2419e07df5 namespaces: remove weakref; always pass in repo
Ryan McElroy <rmcelroy@fb.com>
parents: 23559
diff changeset
    90
                    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
    91
                    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
    92
                    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
    93
                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
    94
        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
    95
80e3cbe227d1 namespaces: add method to get template name of namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23605
diff changeset
    96
    def templatename(self, namespace):
80e3cbe227d1 namespaces: add method to get template name of namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23605
diff changeset
    97
        """method that returns the template name of a namespace"""
80e3cbe227d1 namespaces: add method to get template name of namespace
Sean Farley <sean.michael.farley@gmail.com>
parents: 23605
diff changeset
    98
        return self._names[namespace]['templatename']
23608
807ee1a02bb0 namespaces: add names method to return list of names for a given node
Sean Farley <sean.michael.farley@gmail.com>
parents: 23607
diff changeset
    99
807ee1a02bb0 namespaces: add names method to return list of names for a given node
Sean Farley <sean.michael.farley@gmail.com>
parents: 23607
diff changeset
   100
    def names(self, repo, namespace, node):
807ee1a02bb0 namespaces: add names method to return list of names for a given node
Sean Farley <sean.michael.farley@gmail.com>
parents: 23607
diff changeset
   101
        """method that returns a (sorted) list of names in a namespace that
807ee1a02bb0 namespaces: add names method to return list of names for a given node
Sean Farley <sean.michael.farley@gmail.com>
parents: 23607
diff changeset
   102
        match a given node"""
807ee1a02bb0 namespaces: add names method to return list of names for a given node
Sean Farley <sean.michael.farley@gmail.com>
parents: 23607
diff changeset
   103
        return sorted(self._names[namespace]['nodemap'](repo, node))