namespaces.py
82 lines
| 2.8 KiB
| text/x-python
|
PythonLexer
/ mercurial / namespaces.py
Sean Farley
|
r23559 | from i18n import _ | ||
Sean Farley
|
r23553 | from mercurial import util | ||
Sean Farley
|
r23555 | def tolist(val): | ||
""" | ||||
a convenience method to return an empty list instead of None | ||||
""" | ||||
if val is None: | ||||
return [] | ||||
else: | ||||
return [val] | ||||
Sean Farley
|
r23553 | class namespaces(object): | ||
""" | ||||
provides an interface to register a generic many-to-many mapping between | ||||
some (namespaced) names and nodes. The goal here is to control the | ||||
pollution of jamming things into tags or bookmarks (in extension-land) and | ||||
to simplify internal bits of mercurial: log output, tab completion, etc. | ||||
More precisely, we define a list of names (the namespace) and a mapping of | ||||
names to nodes. This name mapping returns a list of nodes. | ||||
Furthermore, each name mapping will be passed a name to lookup which might | ||||
not be in its domain. In this case, each method should return an empty list | ||||
and not raise an error. | ||||
We'll have a dictionary '_names' where each key is a namespace and | ||||
its value is a dictionary of functions: | ||||
'namemap': function that takes a name and returns a list of nodes | ||||
""" | ||||
_names_version = 0 | ||||
Ryan McElroy
|
r23561 | def __init__(self): | ||
Sean Farley
|
r23553 | self._names = util.sortdict() | ||
Sean Farley
|
r23554 | |||
Sean Farley
|
r23562 | addns = self.addnamespace | ||
Sean Farley
|
r23558 | # we need current mercurial named objects (bookmarks, tags, and | ||
# branches) to be initialized somewhere, so that place is here | ||||
Sean Farley
|
r23562 | addns("bookmarks", | ||
lambda repo, name: tolist(repo._bookmarks.get(name))) | ||||
addns("tags", | ||||
lambda repo, name: tolist(repo._tagscache.tags.get(name))) | ||||
Sean Farley
|
r23558 | |||
Sean Farley
|
r23563 | addns("branches", | ||
lambda repo, name: tolist(repo.branchtip(name))) | ||||
Sean Farley
|
r23554 | def addnamespace(self, namespace, namemap, order=None): | ||
""" | ||||
register a namespace | ||||
namespace: the name to be registered (in plural form) | ||||
namemap: function that inputs a node, output name(s) | ||||
order: optional argument to specify the order of namespaces | ||||
(e.g. 'branches' should be listed before 'bookmarks') | ||||
""" | ||||
val = {'namemap': namemap} | ||||
if order is not None: | ||||
self._names.insert(order, namespace, val) | ||||
else: | ||||
self._names[namespace] = val | ||||
Sean Farley
|
r23559 | |||
Ryan McElroy
|
r23561 | def singlenode(self, repo, name): | ||
Sean Farley
|
r23559 | """ | ||
Return the 'best' node for the given name. Best means the first node | ||||
in the first nonempty list returned by a name-to-nodes mapping function | ||||
in the defined precedence order. | ||||
Raises a KeyError if there is no such node. | ||||
""" | ||||
for ns, v in self._names.iteritems(): | ||||
Ryan McElroy
|
r23561 | n = v['namemap'](repo, name) | ||
Sean Farley
|
r23559 | if n: | ||
# return max revision number | ||||
if len(n) > 1: | ||||
Ryan McElroy
|
r23561 | cl = repo.changelog | ||
Sean Farley
|
r23559 | maxrev = max(cl.rev(node) for node in n) | ||
return cl.node(maxrev) | ||||
return n[0] | ||||
raise KeyError(_('no such name: %s') % name) | ||||