mercurial/namespaces.py
author Sean Farley <sean.michael.farley@gmail.com>
Fri, 17 Oct 2014 15:28:40 -0700
changeset 23559 3b3a962e3677
parent 23558 3198aac7a95d
child 23561 3c2419e07df5
permissions -rw-r--r--
namespaces: add a method to the first matching node for a given name
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
23556
7e1da5d004eb namespaces: pass repo to __init__
Sean Farley <sean.michael.farley@gmail.com>
parents: 23555
diff changeset
     3
import weakref
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):
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    15
    """
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    16
    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
    17
    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
    18
    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
    19
    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
    20
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    21
    More precisely, we define a list of names (the namespace) and  a mapping of
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    22
    names to nodes. This name mapping returns a list of nodes.
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:
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    30
      'namemap': function that takes a name and returns a list of nodes
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    31
    """
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    32
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    33
    _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
    34
23556
7e1da5d004eb namespaces: pass repo to __init__
Sean Farley <sean.michael.farley@gmail.com>
parents: 23555
diff changeset
    35
    def __init__(self, repo):
23553
7cebb6a8c75f namespaces: introduce a generic way to map between names and nodes
Sean Farley <sean.michael.farley@gmail.com>
parents:
diff changeset
    36
        self._names = util.sortdict()
23556
7e1da5d004eb namespaces: pass repo to __init__
Sean Farley <sean.michael.farley@gmail.com>
parents: 23555
diff changeset
    37
        self._repo = weakref.ref(repo)
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    38
23558
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    39
        # 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
    40
        # branches) to be initialized somewhere, so that place is here
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    41
        self.addnamespace("bookmarks",
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    42
                          lambda repo, name: tolist(repo._bookmarks.get(name)))
3198aac7a95d namespaces: add bookmarks to the names data structure
Sean Farley <sean.michael.farley@gmail.com>
parents: 23557
diff changeset
    43
23557
b04b27aa6da3 namespaces: add a convenience property for the weakref _repo
Sean Farley <sean.michael.farley@gmail.com>
parents: 23556
diff changeset
    44
    @property
b04b27aa6da3 namespaces: add a convenience property for the weakref _repo
Sean Farley <sean.michael.farley@gmail.com>
parents: 23556
diff changeset
    45
    def repo(self):
b04b27aa6da3 namespaces: add a convenience property for the weakref _repo
Sean Farley <sean.michael.farley@gmail.com>
parents: 23556
diff changeset
    46
        return self._repo()
b04b27aa6da3 namespaces: add a convenience property for the weakref _repo
Sean Farley <sean.michael.farley@gmail.com>
parents: 23556
diff changeset
    47
23554
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    48
    def addnamespace(self, namespace, namemap, order=None):
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    49
        """
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    50
        register a namespace
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
        namemap: function that inputs a node, output name(s)
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    54
        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
    55
               (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
    56
        """
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    57
        val = {'namemap': namemap}
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    58
        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
    59
            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
    60
        else:
75f9643cab1b namespaces: add a method to register new namespaces
Sean Farley <sean.michael.farley@gmail.com>
parents: 23553
diff changeset
    61
            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
    62
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
    63
    def singlenode(self, name):
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
    64
        """
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
    65
        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
    66
        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
    67
        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
    68
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
    69
        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
    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
        for ns, v in self._names.iteritems():
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
            n = v['namemap'](self.repo, name)
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
            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
    74
                # 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
    75
                if len(n) > 1:
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
                    cl = self.repo.changelog
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
                    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
    78
                    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
    79
                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
    80
        raise KeyError(_('no such name: %s') % name)