dirstate: warn on invalid parents rather than aborting
authorMatt Mackall <mpm@selenic.com>
Mon, 22 Nov 2010 12:43:31 -0600
changeset 13032 e41e2b79883d
parent 13031 3da456d0c885
child 13033 026053f691a4
dirstate: warn on invalid parents rather than aborting This allows more graceful recovery from some mangled dirstates
hgext/bookmarks.py
mercurial/dirstate.py
mercurial/localrepo.py
--- a/hgext/bookmarks.py	Mon Nov 22 18:15:58 2010 +0100
+++ b/hgext/bookmarks.py	Mon Nov 22 12:43:31 2010 -0600
@@ -348,14 +348,12 @@
             return result
 
         def addchangegroup(self, *args, **kwargs):
-            parents = self.dirstate.parents()
-
             result = super(bookmark_repo, self).addchangegroup(*args, **kwargs)
             if result > 1:
                 # We have more heads than before
                 return result
             node = self.changelog.tip()
-
+            parents = self.dirstate.parents()
             self._bookmarksupdate(parents, node)
             return result
 
--- a/mercurial/dirstate.py	Mon Nov 22 18:15:58 2010 +0100
+++ b/mercurial/dirstate.py	Mon Nov 22 12:43:31 2010 -0600
@@ -36,7 +36,7 @@
 
 class dirstate(object):
 
-    def __init__(self, opener, ui, root):
+    def __init__(self, opener, ui, root, validate):
         '''Create a new dirstate object.
 
         opener is an open()-like callable that can be used to open the
@@ -44,6 +44,7 @@
         the dirstate.
         '''
         self._opener = opener
+        self._validate = validate
         self._root = root
         self._rootdir = os.path.join(root, '')
         self._dirty = False
@@ -197,7 +198,7 @@
             yield x
 
     def parents(self):
-        return self._pl
+        return [self._validate(p) for p in self._pl]
 
     def branch(self):
         return self._branch
--- a/mercurial/localrepo.py	Mon Nov 22 18:15:58 2010 +0100
+++ b/mercurial/localrepo.py	Mon Nov 22 12:43:31 2010 -0600
@@ -178,7 +178,19 @@
 
     @propertycache
     def dirstate(self):
-        return dirstate.dirstate(self.opener, self.ui, self.root)
+        warned = [0]
+        def validate(node):
+            try:
+                r = self.changelog.rev(node)
+                return node
+            except error.LookupError:
+                if not warned[0]:
+                    warned[0] = True
+                    self.ui.warn(_("warning: ignoring unknown"
+                                   " working parent %s!\n" % short(node)))
+                return nullid
+
+        return dirstate.dirstate(self.opener, self.ui, self.root, validate)
 
     def __getitem__(self, changeid):
         if changeid is None: