comparison hgext/rebase.py @ 31226:cf8ad0e6c0e4

rebase: move actual rebase into a single transaction Previously, rebasing would open several transaction over the course of rebasing several commits. Opening a transaction can have notable overhead (like copying the dirstate) which can add up when rebasing many commits. This patch adds a single large transaction around the actual commit rebase operation, with a catch for intervention which serializes the current state if we need to drop back to the terminal for user intervention. Amazingly, almost all the tests seem to pass. On large repos with large working copies, this can speed up rebasing 7 commits by 25%. I'd expect the percentage to be a bit larger for rebasing even more commits. There are minor test changes because we're rolling back the entire transaction during unexpected exceptions instead of just stopping mid-rebase, so there's no more backup bundle. It also leave an unknown file in the working copy, since our clean up 'hg update' doesn't delete unknown files.
author Durham Goode <durham@fb.com>
date Tue, 07 Mar 2017 16:27:32 -0800
parents 749b057b01f3
children 98658f73588a
comparison
equal deleted inserted replaced
31225:749b057b01f3 31226:cf8ad0e6c0e4
341 self.targetancestors) 341 self.targetancestors)
342 342
343 if dest.closesbranch() and not self.keepbranchesf: 343 if dest.closesbranch() and not self.keepbranchesf:
344 self.ui.status(_('reopening closed branch head %s\n') % dest) 344 self.ui.status(_('reopening closed branch head %s\n') % dest)
345 345
346 def _performrebase(self): 346 def _performrebase(self, tr):
347 repo, ui, opts = self.repo, self.ui, self.opts 347 repo, ui, opts = self.repo, self.ui, self.opts
348 if self.keepbranchesf: 348 if self.keepbranchesf:
349 # insert _savebranch at the start of extrafns so if 349 # insert _savebranch at the start of extrafns so if
350 # there's a user-provided extrafn it can clobber branch if 350 # there's a user-provided extrafn it can clobber branch if
351 # desired 351 # desired
391 _('changesets'), total) 391 _('changesets'), total)
392 p1, p2, base = defineparents(repo, rev, self.target, 392 p1, p2, base = defineparents(repo, rev, self.target,
393 self.state, 393 self.state,
394 self.targetancestors, 394 self.targetancestors,
395 self.obsoletenotrebased) 395 self.obsoletenotrebased)
396 self.storestatus() 396 self.storestatus(tr=tr)
397 storecollapsemsg(repo, self.collapsemsg) 397 storecollapsemsg(repo, self.collapsemsg)
398 if len(repo[None].parents()) == 2: 398 if len(repo[None].parents()) == 2:
399 repo.ui.debug('resuming interrupted rebase\n') 399 repo.ui.debug('resuming interrupted rebase\n')
400 else: 400 else:
401 try: 401 try:
709 destspace=destspace) 709 destspace=destspace)
710 retcode = rbsrt._preparenewrebase(dest, rebaseset) 710 retcode = rbsrt._preparenewrebase(dest, rebaseset)
711 if retcode is not None: 711 if retcode is not None:
712 return retcode 712 return retcode
713 713
714 rbsrt._performrebase() 714 with repo.transaction('rebase') as tr:
715 try:
716 rbsrt._performrebase(tr)
717 except error.InterventionRequired:
718 tr.close()
719 raise
715 rbsrt._finishrebase() 720 rbsrt._finishrebase()
716 finally: 721 finally:
717 release(lock, wlock) 722 release(lock, wlock)
718 723
719 def _definesets(ui, repo, destf=None, srcf=None, basef=None, revf=[], 724 def _definesets(ui, repo, destf=None, srcf=None, basef=None, revf=[],