# HG changeset patch # User Durham Goode # Date 1409942180 25200 # Node ID 6f63c47cbb861169d700830ad70cf7297fdb46fb # Parent 12bc7f06fc4151cd9951aad5ce77bb310b04f0a2 dirstate: wrap setparent calls with begin/endparentchange (issue4353) This wraps all the locations of dirstate.setparent with the appropriate begin/endparentchange calls. This will prevent exceptions during those calls from causing incoherent dirstates (issue4353). diff -r 12bc7f06fc41 -r 6f63c47cbb86 hgext/histedit.py --- a/hgext/histedit.py Fri Sep 05 11:34:29 2014 -0700 +++ b/hgext/histedit.py Fri Sep 05 11:36:20 2014 -0700 @@ -221,6 +221,7 @@ cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True) stats = None else: + repo.dirstate.beginparentchange() try: # ui.forcemerge is an internal variable, do not document repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), @@ -230,6 +231,7 @@ finally: repo.ui.setconfig('ui', 'forcemerge', '', 'histedit') repo.setparents(wcpar, node.nullid) + repo.dirstate.endparentchange() repo.dirstate.write() # fix up dirstate for copies and renames cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev()) diff -r 12bc7f06fc41 -r 6f63c47cbb86 hgext/mq.py --- a/hgext/mq.py Fri Sep 05 11:34:29 2014 -0700 +++ b/hgext/mq.py Fri Sep 05 11:36:20 2014 -0700 @@ -816,12 +816,14 @@ merged.append(f) else: removed.append(f) + repo.dirstate.beginparentchange() for f in removed: repo.dirstate.remove(f) for f in merged: repo.dirstate.merge(f) p1, p2 = repo.dirstate.parents() repo.setparents(p1, merge) + repo.dirstate.endparentchange() if all_files and '.hgsubstate' in all_files: wctx = repo[None] @@ -1451,7 +1453,7 @@ if keepchanges and tobackup: raise util.Abort(_("local changes found, refresh first")) self.backup(repo, tobackup) - + repo.dirstate.beginparentchange() for f in a: util.unlinkpath(repo.wjoin(f), ignoremissing=True) repo.dirstate.drop(f) @@ -1460,6 +1462,7 @@ repo.wwrite(f, fctx.data(), fctx.flags()) repo.dirstate.normal(f) repo.setparents(qp, nullid) + repo.dirstate.endparentchange() for patch in reversed(self.applied[start:end]): self.ui.status(_("popping %s\n") % patch.name) del self.applied[start:end] @@ -1599,6 +1602,7 @@ bmlist = repo[top].bookmarks() try: + repo.dirstate.beginparentchange() if diffopts.git or diffopts.upgrade: copies = {} for dst in a: @@ -1651,6 +1655,7 @@ # assumes strip can roll itself back if interrupted repo.setparents(*cparents) + repo.dirstate.endparentchange() self.applied.pop() self.applieddirty = True strip(self.ui, repo, [top], update=False, backup=False) diff -r 12bc7f06fc41 -r 6f63c47cbb86 hgext/rebase.py --- a/hgext/rebase.py Fri Sep 05 11:34:29 2014 -0700 +++ b/hgext/rebase.py Fri Sep 05 11:36:20 2014 -0700 @@ -366,7 +366,9 @@ editor=editor) else: # Skip commit if we are collapsing + repo.dirstate.beginparentchange() repo.setparents(repo[p1].node()) + repo.dirstate.endparentchange() newrev = None # Update the state if newrev is not None: @@ -472,7 +474,9 @@ def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None): 'Commit the changes and store useful information in extra' try: + repo.dirstate.beginparentchange() repo.setparents(repo[p1].node(), repo[p2].node()) + repo.dirstate.endparentchange() ctx = repo[rev] if commitmsg is None: commitmsg = ctx.description() diff -r 12bc7f06fc41 -r 6f63c47cbb86 mercurial/cmdutil.py --- a/mercurial/cmdutil.py Fri Sep 05 11:34:29 2014 -0700 +++ b/mercurial/cmdutil.py Fri Sep 05 11:36:20 2014 -0700 @@ -659,6 +659,7 @@ n = None if update: + repo.dirstate.beginparentchange() if p1 != parents[0]: updatefunc(repo, p1.node()) if p2 != parents[1]: @@ -698,6 +699,7 @@ n = repo.commit(message, opts.get('user') or user, opts.get('date') or date, match=m, editor=editor, force=partial) + repo.dirstate.endparentchange() else: if opts.get('exact') or opts.get('import_branch'): branch = branch or 'default' diff -r 12bc7f06fc41 -r 6f63c47cbb86 mercurial/commands.py --- a/mercurial/commands.py Fri Sep 05 11:34:29 2014 -0700 +++ b/mercurial/commands.py Fri Sep 05 11:36:20 2014 -0700 @@ -483,9 +483,11 @@ try: ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'backout') + repo.dirstate.beginparentchange() stats = mergemod.update(repo, parent, True, True, False, node, False) repo.setparents(op1, op2) + repo.dirstate.endparentchange() hg._showstats(repo, stats) if stats[3]: repo.ui.status(_("use 'hg resolve' to retry unresolved " @@ -2750,7 +2752,9 @@ wlock = repo.wlock() try: + repo.dirstate.beginparentchange() repo.setparents(r1, r2) + repo.dirstate.endparentchange() finally: wlock.release() @@ -3310,10 +3314,12 @@ cont = False # drop the second merge parent + repo.dirstate.beginparentchange() repo.setparents(current.node(), nullid) repo.dirstate.write() # fix up dirstate for copies and renames cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev()) + repo.dirstate.endparentchange() # commit node = repo.commit(text=message, user=user, @@ -3922,6 +3928,7 @@ try: try: wlock = repo.wlock() + repo.dirstate.beginparentchange() if not opts.get('no_commit'): lock = repo.lock() tr = repo.transaction('import') @@ -3962,6 +3969,7 @@ tr.close() if msgs: repo.savecommitmessage('\n* * *\n'.join(msgs)) + repo.dirstate.endparentchange() return ret except: # re-raises # wlock.release() indirectly calls dirstate.write(): since diff -r 12bc7f06fc41 -r 6f63c47cbb86 mercurial/context.py --- a/mercurial/context.py Fri Sep 05 11:34:29 2014 -0700 +++ b/mercurial/context.py Fri Sep 05 11:36:20 2014 -0700 @@ -1173,11 +1173,13 @@ """ + self._repo.dirstate.beginparentchange() for f in self.modified() + self.added(): self._repo.dirstate.normal(f) for f in self.removed(): self._repo.dirstate.drop(f) self._repo.dirstate.setparents(node) + self._repo.dirstate.endparentchange() def dirs(self): return self._repo.dirstate.dirs() diff -r 12bc7f06fc41 -r 6f63c47cbb86 mercurial/localrepo.py --- a/mercurial/localrepo.py Fri Sep 05 11:34:29 2014 -0700 +++ b/mercurial/localrepo.py Fri Sep 05 11:36:20 2014 -0700 @@ -758,6 +758,7 @@ return self[changeid].parents() def setparents(self, p1, p2=nullid): + self.dirstate.beginparentchange() copies = self.dirstate.setparents(p1, p2) pctx = self[p1] if copies: @@ -771,6 +772,7 @@ for f, s in sorted(self.dirstate.copies().items()): if f not in pctx and s not in pctx: self.dirstate.copy(None, f) + self.dirstate.endparentchange() def filectx(self, path, changeid=None, fileid=None): """changeid can be a changeset revision, node, or tag. diff -r 12bc7f06fc41 -r 6f63c47cbb86 mercurial/merge.py --- a/mercurial/merge.py Fri Sep 05 11:34:29 2014 -0700 +++ b/mercurial/merge.py Fri Sep 05 11:36:20 2014 -0700 @@ -1134,6 +1134,7 @@ stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels) if not partial: + repo.dirstate.beginparentchange() repo.setparents(fp1, fp2) recordupdates(repo, actions, branchmerge) # update completed, clear state @@ -1141,6 +1142,7 @@ if not branchmerge: repo.dirstate.setbranch(p2.branch()) + repo.dirstate.endparentchange() finally: wlock.release()