Mercurial > hg
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) |