# HG changeset patch # User Matt Mackall # Date 1290451411 21600 # Node ID e41e2b79883dc7638809f3c841e1fcbb56417f4b # Parent 3da456d0c8852d448064c4cbb1fdb234e1b406b9 dirstate: warn on invalid parents rather than aborting This allows more graceful recovery from some mangled dirstates diff -r 3da456d0c885 -r e41e2b79883d hgext/bookmarks.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 diff -r 3da456d0c885 -r e41e2b79883d mercurial/dirstate.py --- 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 diff -r 3da456d0c885 -r e41e2b79883d mercurial/localrepo.py --- 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: