rebase: use one dirstateguard for entire rebase
Recently we switched rebases to run the entire rebase inside a single
transaction, which dramatically improved the speed of rebases in repos with
large working copies. Let's also move the dirstate into a single dirstateguard
to get the same benefits. This let's us avoid serializing the dirstate after
each commit.
In a large repo, rebasing 27 commits is sped up by about 20%.
I believe the test changes are because us touching the dirstate gave the
transaction something to actually rollback.
--- a/hgext/rebase.py Fri Mar 10 15:52:29 2017 -0800
+++ b/hgext/rebase.py Sun Mar 19 11:54:15 2017 -0700
@@ -475,12 +475,24 @@
editopt = True
editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
revtoreuse = max(self.state)
- newnode = concludenode(repo, revtoreuse, p1, self.external,
- commitmsg=commitmsg,
- extrafn=_makeextrafn(self.extrafns),
- editor=editor,
- keepbranches=self.keepbranchesf,
- date=self.date)
+ dsguard = dirstateguard.dirstateguard(repo, 'rebase')
+ try:
+ newnode = concludenode(repo, revtoreuse, p1, self.external,
+ commitmsg=commitmsg,
+ extrafn=_makeextrafn(self.extrafns),
+ editor=editor,
+ keepbranches=self.keepbranchesf,
+ date=self.date)
+ dsguard.close()
+ release(dsguard)
+ except error.InterventionRequired:
+ dsguard.close()
+ release(dsguard)
+ raise
+ except Exception:
+ release(dsguard)
+ raise
+
if newnode is None:
newrev = self.target
else:
@@ -712,11 +724,19 @@
return retcode
with repo.transaction('rebase') as tr:
+ dsguard = dirstateguard.dirstateguard(repo, 'rebase')
try:
rbsrt._performrebase(tr)
+ dsguard.close()
+ release(dsguard)
except error.InterventionRequired:
+ dsguard.close()
+ release(dsguard)
tr.close()
raise
+ except Exception:
+ release(dsguard)
+ raise
rbsrt._finishrebase()
finally:
release(lock, wlock)
@@ -840,33 +860,28 @@
'''Commit the wd changes with parents p1 and p2. Reuse commit info from rev
but also store useful information in extra.
Return node of committed revision.'''
- dsguard = dirstateguard.dirstateguard(repo, 'rebase')
- try:
- repo.setparents(repo[p1].node(), repo[p2].node())
- ctx = repo[rev]
- if commitmsg is None:
- commitmsg = ctx.description()
- keepbranch = keepbranches and repo[p1].branch() != ctx.branch()
- extra = {'rebase_source': ctx.hex()}
- if extrafn:
- extrafn(ctx, extra)
+ repo.setparents(repo[p1].node(), repo[p2].node())
+ ctx = repo[rev]
+ if commitmsg is None:
+ commitmsg = ctx.description()
+ keepbranch = keepbranches and repo[p1].branch() != ctx.branch()
+ extra = {'rebase_source': ctx.hex()}
+ if extrafn:
+ extrafn(ctx, extra)
- targetphase = max(ctx.phase(), phases.draft)
- overrides = {('phases', 'new-commit'): targetphase}
- with repo.ui.configoverride(overrides, 'rebase'):
- if keepbranch:
- repo.ui.setconfig('ui', 'allowemptycommit', True)
- # Commit might fail if unresolved files exist
- if date is None:
- date = ctx.date()
- newnode = repo.commit(text=commitmsg, user=ctx.user(),
- date=date, extra=extra, editor=editor)
+ targetphase = max(ctx.phase(), phases.draft)
+ overrides = {('phases', 'new-commit'): targetphase}
+ with repo.ui.configoverride(overrides, 'rebase'):
+ if keepbranch:
+ repo.ui.setconfig('ui', 'allowemptycommit', True)
+ # Commit might fail if unresolved files exist
+ if date is None:
+ date = ctx.date()
+ newnode = repo.commit(text=commitmsg, user=ctx.user(),
+ date=date, extra=extra, editor=editor)
- repo.dirstate.setbranch(repo[newnode].branch())
- dsguard.close()
- return newnode
- finally:
- release(dsguard)
+ repo.dirstate.setbranch(repo[newnode].branch())
+ return newnode
def rebasenode(repo, rev, p1, base, state, collapse, target):
'Rebase a single revision rev on top of p1 using base as merge ancestor'
--- a/tests/test-rebase-collapse.t Fri Mar 10 15:52:29 2017 -0800
+++ b/tests/test-rebase-collapse.t Sun Mar 19 11:54:15 2017 -0700
@@ -572,6 +572,8 @@
o 0: 'A'
$ hg rebase --keepbranches --collapse -s 1 -d 3
+ transaction abort!
+ rollback completed
abort: cannot collapse multiple named branches
[255]
--- a/tests/test-rebase-scenario-global.t Fri Mar 10 15:52:29 2017 -0800
+++ b/tests/test-rebase-scenario-global.t Sun Mar 19 11:54:15 2017 -0700
@@ -270,6 +270,8 @@
$ hg rebase -s 6 -d 1
rebasing 6:eea13746799a "G"
+ transaction abort!
+ rollback completed
abort: cannot use revision 6 as base, result would have 3 parents
[255]
$ hg rebase --abort