##// END OF EJS Templates
context: catch FilteredRepoLookupError instead of RepoLookupError...
context: catch FilteredRepoLookupError instead of RepoLookupError Now that we have a more specialised exception, lets use it when we meant to catch the more specialised case.

File last commit:

r23610:9266d1dd default
r23687:8f32dcfb default
Show More
namespaces.py
111 lines | 4.1 KiB | text/x-python | PythonLexer
Sean Farley
namespaces: add a method to the first matching node for a given name
r23559 from i18n import _
Sean Farley
namespaces: introduce a generic way to map between names and nodes...
r23553 from mercurial import util
Sean Farley
namespaces: generate template keyword when registering a namespace...
r23610 import templatekw
Sean Farley
namespaces: introduce a generic way to map between names and nodes...
r23553
Sean Farley
namespaces: add a function to turn single results into lists
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
namespaces: introduce a generic way to map between names and nodes...
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.
Sean Farley
namespaces: add nodemap property...
r23607 More precisely, we define a list of names (the namespace), a mapping of
names to nodes, and a mapping from nodes to names. Each mapping
returns a list of nodes.
Sean Farley
namespaces: introduce a generic way to map between names and nodes...
r23553
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:
Sean Farley
namespaces: add template name of a namespace...
r23605 'templatename': name to use for templating (usually the singular form
of the plural namespace name)
Sean Farley
namespaces: introduce a generic way to map between names and nodes...
r23553 'namemap': function that takes a name and returns a list of nodes
Sean Farley
namespaces: add nodemap property...
r23607 'nodemap': function that takes a node and returns a list of names
Sean Farley
namespaces: introduce a generic way to map between names and nodes...
r23553 """
_names_version = 0
Ryan McElroy
namespaces: remove weakref; always pass in repo...
r23561 def __init__(self):
Sean Farley
namespaces: introduce a generic way to map between names and nodes...
r23553 self._names = util.sortdict()
Sean Farley
namespaces: add a method to register new namespaces
r23554
Sean Farley
namespaces: add tags
r23562 addns = self.addnamespace
Sean Farley
namespaces: add bookmarks to the names data structure...
r23558 # we need current mercurial named objects (bookmarks, tags, and
# branches) to be initialized somewhere, so that place is here
Sean Farley
namespaces: add template name of a namespace...
r23605 addns("bookmarks", "bookmark",
Sean Farley
namespaces: add nodemap property...
r23607 lambda repo, name: tolist(repo._bookmarks.get(name)),
lambda repo, name: repo.nodebookmarks(name))
Sean Farley
namespaces: add tags
r23562
Sean Farley
namespaces: add template name of a namespace...
r23605 addns("tags", "tag",
Sean Farley
namespaces: add nodemap property...
r23607 lambda repo, name: tolist(repo._tagscache.tags.get(name)),
lambda repo, name: repo.nodetags(name))
Sean Farley
namespaces: add bookmarks to the names data structure...
r23558
Sean Farley
namespaces: add template name of a namespace...
r23605 addns("branches", "branch",
Sean Farley
namespaces: add nodemap property...
r23607 lambda repo, name: tolist(repo.branchtip(name)),
lambda repo, node: [repo[node].branch()])
Sean Farley
namespaces: add branches...
r23563
Sean Farley
namespaces: add nodemap property...
r23607 def addnamespace(self, namespace, templatename, namemap, nodemap,
order=None):
Sean Farley
namespaces: add a method to register new namespaces
r23554 """
register a namespace
namespace: the name to be registered (in plural form)
Sean Farley
namespaces: add template name of a namespace...
r23605 templatename: the name to use for templating
Sean Farley
namespaces: add a method to register new namespaces
r23554 namemap: function that inputs a node, output name(s)
Sean Farley
namespaces: add nodemap property...
r23607 nodemap: function that inputs a name, output node(s)
Sean Farley
namespaces: add a method to register new namespaces
r23554 order: optional argument to specify the order of namespaces
(e.g. 'branches' should be listed before 'bookmarks')
"""
Sean Farley
namespaces: add template name of a namespace...
r23605 val = {'templatename': templatename,
Sean Farley
namespaces: add nodemap property...
r23607 'namemap': namemap,
'nodemap': nodemap}
Sean Farley
namespaces: add a method to register new namespaces
r23554 if order is not None:
self._names.insert(order, namespace, val)
else:
self._names[namespace] = val
Sean Farley
namespaces: add a method to the first matching node for a given name
r23559
Sean Farley
namespaces: generate template keyword when registering a namespace...
r23610 # we only generate a template keyword if one does not already exist
if namespace not in templatekw.keywords:
def generatekw(**args):
return templatekw.shownames(namespace, **args)
templatekw.keywords[namespace] = generatekw
Ryan McElroy
namespaces: remove weakref; always pass in repo...
r23561 def singlenode(self, repo, name):
Sean Farley
namespaces: add a method to the first matching node for a given name
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
namespaces: remove weakref; always pass in repo...
r23561 n = v['namemap'](repo, name)
Sean Farley
namespaces: add a method to the first matching node for a given name
r23559 if n:
# return max revision number
if len(n) > 1:
Ryan McElroy
namespaces: remove weakref; always pass in repo...
r23561 cl = repo.changelog
Sean Farley
namespaces: add a method to the first matching node for a given name
r23559 maxrev = max(cl.rev(node) for node in n)
return cl.node(maxrev)
return n[0]
raise KeyError(_('no such name: %s') % name)
Sean Farley
namespaces: add method to get template name of namespace...
r23606
def templatename(self, namespace):
"""method that returns the template name of a namespace"""
return self._names[namespace]['templatename']
Sean Farley
namespaces: add names method to return list of names for a given node...
r23608
def names(self, repo, namespace, node):
"""method that returns a (sorted) list of names in a namespace that
match a given node"""
return sorted(self._names[namespace]['nodemap'](repo, node))