37 _names_version = 0 |
37 _names_version = 0 |
38 |
38 |
39 def __init__(self): |
39 def __init__(self): |
40 self._names = util.sortdict() |
40 self._names = util.sortdict() |
41 |
41 |
42 addns = self.addnamespace |
42 # shorten the class name for less indentation |
|
43 ns = namespace |
43 |
44 |
44 # we need current mercurial named objects (bookmarks, tags, and |
45 # we need current mercurial named objects (bookmarks, tags, and |
45 # branches) to be initialized somewhere, so that place is here |
46 # branches) to be initialized somewhere, so that place is here |
46 addns("bookmarks", "bookmark", |
47 n = ns("bookmarks", "bookmark", |
47 lambda repo, name: tolist(repo._bookmarks.get(name)), |
48 lambda repo, name: tolist(repo._bookmarks.get(name)), |
48 lambda repo, name: repo.nodebookmarks(name)) |
49 lambda repo, name: repo.nodebookmarks(name)) |
|
50 self.addnamespace(n) |
49 |
51 |
50 addns("tags", "tag", |
52 n = ns("tags", "tag", |
51 lambda repo, name: tolist(repo._tagscache.tags.get(name)), |
53 lambda repo, name: tolist(repo._tagscache.tags.get(name)), |
52 lambda repo, name: repo.nodetags(name)) |
54 lambda repo, name: repo.nodetags(name)) |
|
55 self.addnamespace(n) |
53 |
56 |
54 addns("branches", "branch", |
57 n = ns("branches", "branch", |
55 lambda repo, name: tolist(repo.branchtip(name)), |
58 lambda repo, name: tolist(repo.branchtip(name)), |
56 lambda repo, node: [repo[node].branch()]) |
59 lambda repo, node: [repo[node].branch()]) |
|
60 self.addnamespace(n) |
57 |
61 |
58 def addnamespace(self, namespace, templatename, namemap, nodemap, |
62 def addnamespace(self, namespace, order=None): |
59 order=None): |
|
60 """ |
63 """ |
61 register a namespace |
64 register a namespace |
62 |
65 |
63 namespace: the name to be registered (in plural form) |
66 namespace: the name to be registered (in plural form) |
64 templatename: the name to use for templating |
67 templatename: the name to use for templating |
65 namemap: function that inputs a node, output name(s) |
68 namemap: function that inputs a node, output name(s) |
66 nodemap: function that inputs a name, output node(s) |
69 nodemap: function that inputs a name, output node(s) |
67 order: optional argument to specify the order of namespaces |
70 order: optional argument to specify the order of namespaces |
68 (e.g. 'branches' should be listed before 'bookmarks') |
71 (e.g. 'branches' should be listed before 'bookmarks') |
69 """ |
72 """ |
70 val = {'templatename': templatename, |
|
71 'namemap': namemap, |
|
72 'nodemap': nodemap} |
|
73 if order is not None: |
73 if order is not None: |
74 self._names.insert(order, namespace, val) |
74 self._names.insert(order, namespace.name, namespace) |
75 else: |
75 else: |
76 self._names[namespace] = val |
76 self._names[namespace.name] = namespace |
77 |
77 |
78 # we only generate a template keyword if one does not already exist |
78 # we only generate a template keyword if one does not already exist |
79 if namespace not in templatekw.keywords: |
79 if namespace.name not in templatekw.keywords: |
80 def generatekw(**args): |
80 def generatekw(**args): |
81 return templatekw.shownames(namespace, **args) |
81 return templatekw.shownames(namespace.name, **args) |
82 |
82 |
83 templatekw.keywords[namespace] = generatekw |
83 templatekw.keywords[namespace.name] = generatekw |
84 |
84 |
85 def singlenode(self, repo, name): |
85 def singlenode(self, repo, name): |
86 """ |
86 """ |
87 Return the 'best' node for the given name. Best means the first node |
87 Return the 'best' node for the given name. Best means the first node |
88 in the first nonempty list returned by a name-to-nodes mapping function |
88 in the first nonempty list returned by a name-to-nodes mapping function |
89 in the defined precedence order. |
89 in the defined precedence order. |
90 |
90 |
91 Raises a KeyError if there is no such node. |
91 Raises a KeyError if there is no such node. |
92 """ |
92 """ |
93 for ns, v in self._names.iteritems(): |
93 for ns, v in self._names.iteritems(): |
94 n = v['namemap'](repo, name) |
94 n = v.namemap(repo, name) |
95 if n: |
95 if n: |
96 # return max revision number |
96 # return max revision number |
97 if len(n) > 1: |
97 if len(n) > 1: |
98 cl = repo.changelog |
98 cl = repo.changelog |
99 maxrev = max(cl.rev(node) for node in n) |
99 maxrev = max(cl.rev(node) for node in n) |
101 return n[0] |
101 return n[0] |
102 raise KeyError(_('no such name: %s') % name) |
102 raise KeyError(_('no such name: %s') % name) |
103 |
103 |
104 def templatename(self, namespace): |
104 def templatename(self, namespace): |
105 """method that returns the template name of a namespace""" |
105 """method that returns the template name of a namespace""" |
106 return self._names[namespace]['templatename'] |
106 return self._names[namespace].templatename |
107 |
107 |
108 def names(self, repo, namespace, node): |
108 def names(self, repo, namespace, node): |
109 """method that returns a (sorted) list of names in a namespace that |
109 """method that returns a (sorted) list of names in a namespace that |
110 match a given node""" |
110 match a given node""" |
111 return sorted(self._names[namespace]['nodemap'](repo, node)) |
111 return sorted(self._names[namespace].nodemap(repo, node)) |
112 |
112 |
113 class namespace(object): |
113 class namespace(object): |
114 """provides an interface to a namespace |
114 """provides an interface to a namespace |
115 |
115 |
116 Namespaces are basically generic many-to-many mapping between some |
116 Namespaces are basically generic many-to-many mapping between some |