Patchwork [1,of,3] namespaces: remove weakref; always pass in repo

login
register
mail settings
Submitter Ryan McElroy
Date Dec. 15, 2014, 3:35 a.m.
Message ID <2def00d143fbcc131a79.1418614531@devbig105.prn2.facebook.com>
Download mbox | patch
Permalink /patch/7112/
State Accepted
Headers show

Comments

Ryan McElroy - Dec. 15, 2014, 3:35 a.m.
# HG changeset patch
# User Ryan McElroy <rmcelroy@fb.com>
# Date 1418613104 28800
#      Sun Dec 14 19:11:44 2014 -0800
# Node ID 2def00d143fbcc131a79c974ad66ab5ae5f02e89
# Parent  0c7ea92bf8c36f06df015ea62ec298e79a1e1b3c
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.

Patch

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -409,7 +409,7 @@  class changectx(basectx):
 
             # lookup bookmarks through the name interface
             try:
-                self._node = repo.names.singlenode(changeid)
+                self._node = repo.names.singlenode(repo, changeid)
                 self._rev = repo.changelog.rev(self._node)
                 return
             except KeyError:
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -299,7 +299,7 @@  class localrepository(object):
         self.filteredrevcache = {}
 
         # generic mapping between names and nodes
-        self.names = namespaces.namespaces(self)
+        self.names = namespaces.namespaces()
 
     def close(self):
         pass
diff --git a/mercurial/namespaces.py b/mercurial/namespaces.py
--- a/mercurial/namespaces.py
+++ b/mercurial/namespaces.py
@@ -1,6 +1,5 @@ 
 from i18n import _
 from mercurial import util
-import weakref
 
 def tolist(val):
     """
@@ -32,19 +31,14 @@  class namespaces(object):
 
     _names_version = 0
 
-    def __init__(self, repo):
+    def __init__(self):
         self._names = util.sortdict()
-        self._repo = weakref.ref(repo)
 
         # we need current mercurial named objects (bookmarks, tags, and
         # branches) to be initialized somewhere, so that place is here
         self.addnamespace("bookmarks",
                           lambda repo, name: tolist(repo._bookmarks.get(name)))
 
-    @property
-    def repo(self):
-        return self._repo()
-
     def addnamespace(self, namespace, namemap, order=None):
         """
         register a namespace
@@ -60,7 +54,7 @@  class namespaces(object):
         else:
             self._names[namespace] = val
 
-    def singlenode(self, name):
+    def singlenode(self, repo, name):
         """
         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
@@ -69,11 +63,11 @@  class namespaces(object):
         Raises a KeyError if there is no such node.
         """
         for ns, v in self._names.iteritems():
-            n = v['namemap'](self.repo, name)
+            n = v['namemap'](repo, name)
             if n:
                 # return max revision number
                 if len(n) > 1:
-                    cl = self.repo.changelog
+                    cl = repo.changelog
                     maxrev = max(cl.rev(node) for node in n)
                     return cl.node(maxrev)
                 return n[0]
diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py
--- a/mercurial/statichttprepo.py
+++ b/mercurial/statichttprepo.py
@@ -106,7 +106,7 @@  class statichttprepository(localrepo.loc
         self.vfs = self.opener
         self._phasedefaults = []
 
-        self.names = namespaces.namespaces(self)
+        self.names = namespaces.namespaces()
 
         try:
             requirements = scmutil.readrequires(self.opener, self.supported)