134 desc += ' (%s)' % ' '.join(names) |
134 desc += ' (%s)' % ' '.join(names) |
135 return desc |
135 return desc |
136 |
136 |
137 class rebaseruntime(object): |
137 class rebaseruntime(object): |
138 """This class is a container for rebase runtime state""" |
138 """This class is a container for rebase runtime state""" |
139 def __init__(self, repo, ui, opts=None): |
139 def __init__(self, repo, ui, inmemory=False, opts=None): |
140 if opts is None: |
140 if opts is None: |
141 opts = {} |
141 opts = {} |
142 |
142 |
143 # prepared: whether we have rebasestate prepared or not. Currently it |
143 # prepared: whether we have rebasestate prepared or not. Currently it |
144 # decides whether "self.repo" is unfiltered or not. |
144 # decides whether "self.repo" is unfiltered or not. |
177 # keepopen is not meant for use on the command line, but by |
177 # keepopen is not meant for use on the command line, but by |
178 # other extensions |
178 # other extensions |
179 self.keepopen = opts.get('keepopen', False) |
179 self.keepopen = opts.get('keepopen', False) |
180 self.obsoletenotrebased = {} |
180 self.obsoletenotrebased = {} |
181 self.obsoletewithoutsuccessorindestination = set() |
181 self.obsoletewithoutsuccessorindestination = set() |
182 self.inmemory = opts.get('inmemory', False) |
182 self.inmemory = inmemory |
183 |
183 |
184 @property |
184 @property |
185 def repo(self): |
185 def repo(self): |
186 if self.prepared: |
186 if self.prepared: |
187 return self._repo.unfiltered() |
187 return self._repo.unfiltered() |
643 ('', 'keepbranches', False, _('keep original branch names')), |
643 ('', 'keepbranches', False, _('keep original branch names')), |
644 ('D', 'detach', False, _('(DEPRECATED)')), |
644 ('D', 'detach', False, _('(DEPRECATED)')), |
645 ('i', 'interactive', False, _('(DEPRECATED)')), |
645 ('i', 'interactive', False, _('(DEPRECATED)')), |
646 ('t', 'tool', '', _('specify merge tool')), |
646 ('t', 'tool', '', _('specify merge tool')), |
647 ('c', 'continue', False, _('continue an interrupted rebase')), |
647 ('c', 'continue', False, _('continue an interrupted rebase')), |
648 ('', 'inmemory', False, _('run rebase in-memory (EXPERIMENTAL)')), |
|
649 ('a', 'abort', False, _('abort an interrupted rebase'))] + |
648 ('a', 'abort', False, _('abort an interrupted rebase'))] + |
650 cmdutil.formatteropts, |
649 cmdutil.formatteropts, |
651 _('[-s REV | -b REV] [-d REV] [OPTION]')) |
650 _('[-s REV | -b REV] [-d REV] [OPTION]')) |
652 def rebase(ui, repo, **opts): |
651 def rebase(ui, repo, **opts): |
653 """move changeset (and descendants) to a different branch |
652 """move changeset (and descendants) to a different branch |
755 unexpectedly:: |
754 unexpectedly:: |
756 |
755 |
757 [rebase] |
756 [rebase] |
758 singletransaction = True |
757 singletransaction = True |
759 |
758 |
|
759 By default, rebase writes to the working copy, but you can configure it to |
|
760 run in-memory for for better performance, and to allow it to run if the |
|
761 working copy is dirty:: |
|
762 |
|
763 [rebase] |
|
764 experimental.inmemory = True |
|
765 |
760 Return Values: |
766 Return Values: |
761 |
767 |
762 Returns 0 on success, 1 if nothing to rebase or there are |
768 Returns 0 on success, 1 if nothing to rebase or there are |
763 unresolved conflicts. |
769 unresolved conflicts. |
764 |
770 |
765 """ |
771 """ |
|
772 inmemory = ui.configbool('rebase', 'experimental.inmemory') |
766 if opts.get('continue') or opts.get('abort'): |
773 if opts.get('continue') or opts.get('abort'): |
767 # in-memory rebase is not compatible with resuming rebases. |
774 # in-memory rebase is not compatible with resuming rebases. |
768 opts['inmemory'] = False |
775 inmemory = False |
769 |
776 |
770 if opts.get('inmemory', False): |
777 if inmemory: |
771 try: |
778 try: |
772 # in-memory merge doesn't support conflicts, so if we hit any, abort |
779 # in-memory merge doesn't support conflicts, so if we hit any, abort |
773 # and re-run as an on-disk merge. |
780 # and re-run as an on-disk merge. |
774 return _origrebase(ui, repo, **opts) |
781 return _origrebase(ui, repo, inmemory=inmemory, **opts) |
775 except error.InMemoryMergeConflictsError: |
782 except error.InMemoryMergeConflictsError: |
776 ui.warn(_('hit merge conflicts; re-running rebase without in-memory' |
783 ui.warn(_('hit merge conflicts; re-running rebase without in-memory' |
777 ' merge\n')) |
784 ' merge\n')) |
778 _origrebase(ui, repo, **{'abort': True}) |
785 _origrebase(ui, repo, **{'abort': True}) |
779 opts['inmemory'] = False |
786 return _origrebase(ui, repo, inmemory=False, **opts) |
780 return _origrebase(ui, repo, **opts) |
|
781 else: |
787 else: |
782 return _origrebase(ui, repo, **opts) |
788 return _origrebase(ui, repo, **opts) |
783 |
789 |
784 def _origrebase(ui, repo, **opts): |
790 def _origrebase(ui, repo, inmemory=False, **opts): |
785 opts = pycompat.byteskwargs(opts) |
791 opts = pycompat.byteskwargs(opts) |
786 if 'inmemory' not in opts: |
792 rbsrt = rebaseruntime(repo, ui, inmemory, opts) |
787 opts['inmemory'] = False |
|
788 rbsrt = rebaseruntime(repo, ui, opts) |
|
789 |
793 |
790 with repo.wlock(), repo.lock(): |
794 with repo.wlock(), repo.lock(): |
791 # Validate input and define rebasing points |
795 # Validate input and define rebasing points |
792 destf = opts.get('dest', None) |
796 destf = opts.get('dest', None) |
793 srcf = opts.get('source', None) |
797 srcf = opts.get('source', None) |
830 |
834 |
831 retcode = rbsrt._prepareabortorcontinue(abortf) |
835 retcode = rbsrt._prepareabortorcontinue(abortf) |
832 if retcode is not None: |
836 if retcode is not None: |
833 return retcode |
837 return retcode |
834 else: |
838 else: |
835 destmap = _definedestmap(ui, repo, destf, srcf, basef, revf, |
839 destmap = _definedestmap(ui, repo, rbsrt, destf, srcf, basef, revf, |
836 destspace=destspace, |
840 destspace=destspace) |
837 opts=opts) |
|
838 rbsrt.inmemory = opts['inmemory'] |
|
839 retcode = rbsrt._preparenewrebase(destmap) |
841 retcode = rbsrt._preparenewrebase(destmap) |
840 if retcode is not None: |
842 if retcode is not None: |
841 return retcode |
843 return retcode |
842 |
844 |
843 tr = None |
845 tr = None |
852 with util.acceptintervention(dsguard): |
854 with util.acceptintervention(dsguard): |
853 rbsrt._performrebase(tr) |
855 rbsrt._performrebase(tr) |
854 |
856 |
855 rbsrt._finishrebase() |
857 rbsrt._finishrebase() |
856 |
858 |
857 def _definedestmap(ui, repo, destf=None, srcf=None, basef=None, revf=None, |
859 def _definedestmap(ui, repo, rbsrt, destf=None, srcf=None, basef=None, |
858 destspace=None, opts=None): |
860 revf=None, destspace=None): |
859 """use revisions argument to define destmap {srcrev: destrev}""" |
861 """use revisions argument to define destmap {srcrev: destrev}""" |
860 if revf is None: |
862 if revf is None: |
861 revf = [] |
863 revf = [] |
862 |
864 |
863 # destspace is here to work around issues with `hg pull --rebase` see |
865 # destspace is here to work around issues with `hg pull --rebase` see |
867 if revf and basef: |
869 if revf and basef: |
868 raise error.Abort(_('cannot specify both a revision and a base')) |
870 raise error.Abort(_('cannot specify both a revision and a base')) |
869 if revf and srcf: |
871 if revf and srcf: |
870 raise error.Abort(_('cannot specify both a revision and a source')) |
872 raise error.Abort(_('cannot specify both a revision and a source')) |
871 |
873 |
872 if not opts['inmemory']: |
874 if not rbsrt.inmemory: |
873 cmdutil.checkunfinished(repo) |
875 cmdutil.checkunfinished(repo) |
874 cmdutil.bailifchanged(repo) |
876 cmdutil.bailifchanged(repo) |
875 |
877 |
876 if ui.configbool('commands', 'rebase.requiredest') and not destf: |
878 if ui.configbool('commands', 'rebase.requiredest') and not destf: |
877 raise error.Abort(_('you must specify a destination'), |
879 raise error.Abort(_('you must specify a destination'), |
953 # |
955 # |
954 # Note that there are cases where this isn't true -- e.g., rebasing large |
956 # Note that there are cases where this isn't true -- e.g., rebasing large |
955 # stacks that include the WCP. However, I'm not yet sure where the cutoff |
957 # stacks that include the WCP. However, I'm not yet sure where the cutoff |
956 # is. |
958 # is. |
957 rebasingwcp = repo['.'].rev() in rebaseset |
959 rebasingwcp = repo['.'].rev() in rebaseset |
958 if opts['inmemory'] and rebasingwcp: |
960 if rbsrt.inmemory and rebasingwcp: |
959 opts['inmemory'] = False |
961 rbsrt.inmemory = False |
960 # Check these since we did not before. |
962 # Check these since we did not before. |
961 cmdutil.checkunfinished(repo) |
963 cmdutil.checkunfinished(repo) |
962 cmdutil.bailifchanged(repo) |
964 cmdutil.bailifchanged(repo) |
963 |
965 |
964 if not destf: |
966 if not destf: |