comparison mercurial/namespaces.py @ 23561:3c2419e07df5

namespaces: remove weakref; always pass in repo It turns out that maintaining a reference of any sort (even weak!) to the repo when constructed doesn't work because we may at some point pass in a repoview filtered by something other than what the initial repo was.
author Ryan McElroy <rmcelroy@fb.com>
date Sun, 14 Dec 2014 19:11:44 -0800
parents 3b3a962e3677
children 59e703aecaf6
comparison
equal deleted inserted replaced
23560:aead63705504 23561:3c2419e07df5
1 from i18n import _ 1 from i18n import _
2 from mercurial import util 2 from mercurial import util
3 import weakref
4 3
5 def tolist(val): 4 def tolist(val):
6 """ 5 """
7 a convenience method to return an empty list instead of None 6 a convenience method to return an empty list instead of None
8 """ 7 """
30 'namemap': function that takes a name and returns a list of nodes 29 'namemap': function that takes a name and returns a list of nodes
31 """ 30 """
32 31
33 _names_version = 0 32 _names_version = 0
34 33
35 def __init__(self, repo): 34 def __init__(self):
36 self._names = util.sortdict() 35 self._names = util.sortdict()
37 self._repo = weakref.ref(repo)
38 36
39 # we need current mercurial named objects (bookmarks, tags, and 37 # we need current mercurial named objects (bookmarks, tags, and
40 # branches) to be initialized somewhere, so that place is here 38 # branches) to be initialized somewhere, so that place is here
41 self.addnamespace("bookmarks", 39 self.addnamespace("bookmarks",
42 lambda repo, name: tolist(repo._bookmarks.get(name))) 40 lambda repo, name: tolist(repo._bookmarks.get(name)))
43
44 @property
45 def repo(self):
46 return self._repo()
47 41
48 def addnamespace(self, namespace, namemap, order=None): 42 def addnamespace(self, namespace, namemap, order=None):
49 """ 43 """
50 register a namespace 44 register a namespace
51 45
58 if order is not None: 52 if order is not None:
59 self._names.insert(order, namespace, val) 53 self._names.insert(order, namespace, val)
60 else: 54 else:
61 self._names[namespace] = val 55 self._names[namespace] = val
62 56
63 def singlenode(self, name): 57 def singlenode(self, repo, name):
64 """ 58 """
65 Return the 'best' node for the given name. Best means the first node 59 Return the 'best' node for the given name. Best means the first node
66 in the first nonempty list returned by a name-to-nodes mapping function 60 in the first nonempty list returned by a name-to-nodes mapping function
67 in the defined precedence order. 61 in the defined precedence order.
68 62
69 Raises a KeyError if there is no such node. 63 Raises a KeyError if there is no such node.
70 """ 64 """
71 for ns, v in self._names.iteritems(): 65 for ns, v in self._names.iteritems():
72 n = v['namemap'](self.repo, name) 66 n = v['namemap'](repo, name)
73 if n: 67 if n:
74 # return max revision number 68 # return max revision number
75 if len(n) > 1: 69 if len(n) > 1:
76 cl = self.repo.changelog 70 cl = repo.changelog
77 maxrev = max(cl.rev(node) for node in n) 71 maxrev = max(cl.rev(node) for node in n)
78 return cl.node(maxrev) 72 return cl.node(maxrev)
79 return n[0] 73 return n[0]
80 raise KeyError(_('no such name: %s') % name) 74 raise KeyError(_('no such name: %s') % name)