##// END OF EJS Templates
cleanup: replace contiguous spaces in regex patterns with an explicit count...
cleanup: replace contiguous spaces in regex patterns with an explicit count Flagged by PyCharm, this form should be more readable. Differential Revision: https://phab.mercurial-scm.org/D7765

File last commit:

r44430:bd88407e default
r44472:ac3cb5e0 default
Show More
rebase.py
2284 lines | 81.0 KiB | text/x-python | PythonLexer
Stefano Tortarolo
Add rebase extension
r6906 # rebase.py - rebasing feature for mercurial
#
# Copyright 2008 Stefano Tortarolo <stefano.tortarolo at gmail dot com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Stefano Tortarolo
Add rebase extension
r6906
Dirkjan Ochtman
extensions: change descriptions for extensions providing a few commands
r8934 '''command to move sets of revisions to a different ancestor
Stefano Tortarolo
Add rebase extension
r6906
Martin Geisler
rebase: word-wrap help texts at 70 characters
r7999 This extension lets you rebase changesets in an existing Mercurial
repository.
Stefano Tortarolo
Add rebase extension
r6906
For more information:
Matt Mackall
urls: bulk-change primary website URLs
r26421 https://mercurial-scm.org/wiki/RebaseExtension
Stefano Tortarolo
Add rebase extension
r6906 '''
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 from __future__ import absolute_import
import errno
import os
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205
from mercurial.i18n import _
from mercurial.node import (
nullrev,
short,
)
Gregory Szorc
py3: manually import pycompat.open into files that need it...
r43355 from mercurial.pycompat import open
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 from mercurial import (
bookmarks,
cmdutil,
commands,
copies,
destutil,
Augie Fackler
rebase: refer to dirstateguard by its new name
r30490 dirstateguard,
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 error,
extensions,
hg,
timeless
rebase: rename merge to mergemod
r30271 merge as mergemod,
Augie Fackler
rebase: refer to checkunresolved by its new name
r30495 mergeutil,
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 obsolete,
obsutil: move 'allsuccessors' to the new modules...
r33146 obsutil,
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 patch,
phases,
Pulkit Goyal
py3: handle keyword arguments in hgext/rebase.py...
r35003 pycompat,
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 registrar,
repair,
revset,
Jun Wu
rebase: initial support for multiple destinations...
r34007 revsetlang,
Martin von Zweigbergk
rebase: use rewriteutil.precheck() instead of reimplementing it...
r44386 rewriteutil,
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 scmutil,
Yuya Nishihara
revset: import set classes directly from smartset module...
r31023 smartset,
Pulkit Goyal
rebase: add a stateobj variable to rebaseruntime class...
r38535 state as statemod,
Pulkit Goyal
py3: make hgext/rebase.py use absolute_import
r29128 util,
)
Christian Delahousse
rebase: added comments...
r26669 # The following constants are used throughout the rebase module. The ordering of
# their values must be maintained.
# Indicates that a revision needs to be rebased
Pierre-Yves David
rebase: add a 'revtodo' constant...
r23490 revtodo = -1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revtodostr = b'-1'
Jun Wu
rebase: remove revprecursor and revpruned states (BC)...
r33842
# legacy revstates no longer needed in current code
Jun Wu
rebase: remove revignored and nullmerge states...
r33844 # -2: nullmerge, -3: revignored, -4: revprecursor, -5: revpruned
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 legacystates = {b'-2', b'-3', b'-4', b'-5'}
Stefano Tortarolo
rebase: add --detach option to detach intermediate revisions (issue1950)...
r10352
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 cmdtable = {}
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 command = registrar.command(cmdtable)
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 testedwith = b'ships-with-hg-core'
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306
Augie Fackler
formatting: blacken the codebase...
r43346
Ryan McElroy
rebase: factor out nothing to rebase return code...
r26671 def _nothingtorebase():
return 1
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
rebase: backout changeset d755a9531fce...
r27976 def _savegraft(ctx, extra):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 s = ctx.extra().get(b'source', None)
Siddharth Agarwal
rebase: backout changeset d755a9531fce...
r27976 if s is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extra[b'source'] = s
s = ctx.extra().get(b'intermediate-source', None)
Siddharth Agarwal
rebase: backout changeset d755a9531fce...
r27976 if s is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extra[b'intermediate-source'] = s
Siddharth Agarwal
rebase: backout changeset d755a9531fce...
r27976
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
rebase: backout changeset d755a9531fce...
r27976 def _savebranch(ctx, extra):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extra[b'branch'] = ctx.branch()
Siddharth Agarwal
rebase: backout changeset d755a9531fce...
r27976
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 def _destrebase(repo, sourceset, destspace=None):
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 """small wrapper around destmerge to pass the right extra args
Please wrap destutil.destmerge instead."""
Augie Fackler
formatting: blacken the codebase...
r43346 return destutil.destmerge(
repo,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 action=b'rebase',
Augie Fackler
formatting: blacken the codebase...
r43346 sourceset=sourceset,
onheadcheck=False,
destspace=destspace,
)
Pierre-Yves David
rebase: extra default destination in its own function...
r26717
FUJIWARA Katsunori
revset: replace extpredicate by revsetpredicate of registrar...
r28394 revsetpredicate = registrar.revsetpredicate()
FUJIWARA Katsunori
revset: use delayregistrar to register predicate in extension easily...
r27586
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @revsetpredicate(b'_destrebase')
Pierre-Yves David
rebase: rename and test '_destrebase'...
r26719 def _revsetdestrebase(repo, subset, x):
Pierre-Yves David
rebase: move destination computation in a revset...
r26301 # ``_rebasedefaultdest()``
# default destination for rebase.
# # XXX: Currently private because I expect the signature to change.
# # XXX: - bailing out in case of ambiguity vs returning all data.
# i18n: "_rebasedefaultdest" is a keyword
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 sourceset = None
if x is not None:
Yuya Nishihara
revset: import set classes directly from smartset module...
r31023 sourceset = revset.getset(repo, smartset.fullreposet(repo), x)
return subset & smartset.baseset([_destrebase(repo, sourceset)])
Pierre-Yves David
rebase: move destination computation in a revset...
r26301
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @revsetpredicate(b'_destautoorphanrebase')
Augie Fackler
rebase: introduce support for automatically rebasing orphan changes...
r37805 def _revsetdestautoorphanrebase(repo, subset, x):
timeless
rebase: hide help for revisions.Predicates._destautoorphanrebase
r42485 # ``_destautoorphanrebase()``
# automatic rebase destination for a single orphan revision.
Augie Fackler
rebase: introduce support for automatically rebasing orphan changes...
r37805 unfi = repo.unfiltered()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 obsoleted = unfi.revs(b'obsolete()')
Augie Fackler
rebase: introduce support for automatically rebasing orphan changes...
r37805
src = revset.getset(repo, subset, x).first()
# Empty src or already obsoleted - Do not return a destination
if not src or src in obsoleted:
return smartset.baseset()
dests = destutil.orphanpossibledestination(repo, src)
if len(dests) > 1:
raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"ambiguous automatic rebase: %r could end up on any of %r")
Augie Fackler
formatting: blacken the codebase...
r43346 % (src, dests)
)
Augie Fackler
rebase: introduce support for automatically rebasing orphan changes...
r37805 # We have zero or one destination, so we can just return here.
return smartset.baseset(dests)
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: extract ctx description logic to a function...
r33840 def _ctxdesc(ctx):
"""short description for a context"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 desc = b'%d:%s "%s"' % (
ctx.rev(),
ctx,
ctx.description().split(b'\n', 1)[0],
)
Jun Wu
rebase: extract ctx description logic to a function...
r33840 repo = ctx.repo()
Martin von Zweigbergk
rebase: also include other namespaces in changeset description...
r34291 names = []
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 for nsname, ns in pycompat.iteritems(repo.names):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if nsname == b'branches':
Martin von Zweigbergk
rebase: also include other namespaces in changeset description...
r34291 continue
names.extend(ns.names(repo, ctx.node()))
Jun Wu
rebase: extract ctx description logic to a function...
r33840 if names:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 desc += b' (%s)' % b' '.join(names)
Jun Wu
rebase: extract ctx description logic to a function...
r33840 return desc
Augie Fackler
formatting: blacken the codebase...
r43346
Kostia Balytskyi
rebase: introduce a rebaseruntime (RR) class...
r29358 class rebaseruntime(object):
"""This class is a container for rebase runtime state"""
Augie Fackler
formatting: blacken the codebase...
r43346
Phil Cohen
rebase: replace --inmemory flag with rebase.experimental.inmemory config...
r35389 def __init__(self, repo, ui, inmemory=False, opts=None):
Kostia Balytskyi
rebase: pass repo, ui and opts objects to the RR class constructor
r29399 if opts is None:
opts = {}
Jun Wu
rebase: remove complex unhiding code...
r34096 # prepared: whether we have rebasestate prepared or not. Currently it
# decides whether "self.repo" is unfiltered or not.
# The rebasestate has explicit hash to hash instructions not depending
# on visibility. If rebasestate exists (in-memory or on-disk), use
# unfiltered repo to avoid visibility issues.
# Before knowing rebasestate (i.e. when starting a new rebase (not
# --continue or --abort)), the original repo should be used so
# visibility-dependent revsets are correct.
self.prepared = False
self._repo = repo
Kostia Balytskyi
rebase: pass repo, ui and opts objects to the RR class constructor
r29399 self.ui = ui
self.opts = opts
Kostia Balytskyi
rebase: introduce a rebaseruntime (RR) class...
r29358 self.originalwd = None
self.external = nullrev
# Mapping between the old revision id and either what is the new rebased
# revision or what needs to be done with the old revision. The state
# dict will be what contains most of the rebase progress state.
self.state = {}
self.activebookmark = None
Jun Wu
rebase: change internal format to support destination map...
r34006 self.destmap = {}
Kostia Balytskyi
rebase: move local variable 'skipped' to the RR class
r29360 self.skipped = set()
Kostia Balytskyi
rebase: introduce a rebaseruntime (RR) class...
r29358
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.collapsef = opts.get(b'collapse', False)
Kostia Balytskyi
rebase: move collapse-related local variables to the RR class...
r29400 self.collapsemsg = cmdutil.logmessage(ui, opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.date = opts.get(b'date', None)
Kostia Balytskyi
rebase: move local variables 'date' and 'extrafns' to the RR class...
r29401
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 e = opts.get(b'extrafn') # internal, used by e.g. hgsubversion
Kostia Balytskyi
rebase: move local variables 'date' and 'extrafns' to the RR class...
r29401 self.extrafns = [_savegraft]
if e:
self.extrafns = [e]
Kostia Balytskyi
rebase: move collapse-related local variables to the RR class...
r29400
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.backupf = ui.configbool(b'rewrite', b'backup-bundle')
self.keepf = opts.get(b'keep', False)
self.keepbranchesf = opts.get(b'keepbranches', False)
Kostia Balytskyi
rebase: move local variable 'obsoletenotrebased' to the RR class
r29404 self.obsoletenotrebased = {}
Denis Laxalde
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
r35049 self.obsoletewithoutsuccessorindestination = set()
Phil Cohen
rebase: replace --inmemory flag with rebase.experimental.inmemory config...
r35389 self.inmemory = inmemory
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.stateobj = statemod.cmdstate(repo, b'rebasestate')
Kostia Balytskyi
rebase: move local variables related to keeping things unchanged to the RR...
r29402
Jun Wu
rebase: remove complex unhiding code...
r34096 @property
def repo(self):
if self.prepared:
return self._repo.unfiltered()
else:
return self._repo
Durham Goode
rebase: add storestatus support for transactions...
r31224 def storestatus(self, tr=None):
Durham Goode
rebase: move storestatus onto rebaseruntime...
r31223 """Store the current status to allow recovery"""
Durham Goode
rebase: add storestatus support for transactions...
r31224 if tr:
Augie Fackler
formatting: blacken the codebase...
r43346 tr.addfilegenerator(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'rebasestate',
(b'rebasestate',),
Augie Fackler
formatting: blacken the codebase...
r43346 self._writestatus,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 location=b'plain',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Durham Goode
rebase: add storestatus support for transactions...
r31224 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with self.repo.vfs(b"rebasestate", b"w") as f:
Durham Goode
rebase: add storestatus support for transactions...
r31224 self._writestatus(f)
def _writestatus(self, f):
Jun Wu
rebase: remove unnecessary '.unfiltered()' calls...
r34097 repo = self.repo
assert repo.filtername is None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(repo[self.originalwd].hex() + b'\n')
Jun Wu
rebase: change internal format to support destination map...
r34006 # was "dest". we now write dest per src root below.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(b'\n')
f.write(repo[self.external].hex() + b'\n')
f.write(b'%d\n' % int(self.collapsef))
f.write(b'%d\n' % int(self.keepf))
f.write(b'%d\n' % int(self.keepbranchesf))
f.write(b'%s\n' % (self.activebookmark or b''))
Jun Wu
rebase: change internal format to support destination map...
r34006 destmap = self.destmap
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 for d, v in pycompat.iteritems(self.state):
Durham Goode
rebase: move storestatus onto rebaseruntime...
r31223 oldrev = repo[d].hex()
if v >= 0:
newrev = repo[v].hex()
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 newrev = b"%d" % v
Jun Wu
rebase: change internal format to support destination map...
r34006 destnode = repo[destmap[d]].hex()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(b"%s:%s:%s\n" % (oldrev, newrev, destnode))
repo.ui.debug(b'rebase status stored\n')
Durham Goode
rebase: move storestatus onto rebaseruntime...
r31223
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 def restorestatus(self):
"""Restore a previously stored status"""
Pulkit Goyal
rebase: check whether the rebasestate exists or not a bit early...
r38537 if not self.stateobj.exists():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmdutil.wrongtooltocontinue(self.repo, _(b'rebase'))
Pulkit Goyal
rebase: check whether the rebasestate exists or not a bit early...
r38537
Pulkit Goyal
rebase: refactor logic to read rebasestate in a separate function...
r38534 data = self._read()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.repo.ui.debug(b'rebase status resumed\n')
Pulkit Goyal
rebase: refactor logic to read rebasestate in a separate function...
r38534
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.originalwd = data[b'originalwd']
self.destmap = data[b'destmap']
self.state = data[b'state']
self.skipped = data[b'skipped']
self.collapsef = data[b'collapse']
self.keepf = data[b'keep']
self.keepbranchesf = data[b'keepbranches']
self.external = data[b'external']
self.activebookmark = data[b'activebookmark']
Pulkit Goyal
rebase: refactor logic to read rebasestate in a separate function...
r38534
def _read(self):
Jun Wu
rebase: remove complex unhiding code...
r34096 self.prepared = True
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 repo = self.repo
Jun Wu
rebase: remove unnecessary '.unfiltered()' calls...
r34097 assert repo.filtername is None
Augie Fackler
formatting: blacken the codebase...
r43346 data = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'keepbranches': None,
b'collapse': None,
b'activebookmark': None,
b'external': nullrev,
b'keep': None,
b'originalwd': None,
Augie Fackler
formatting: blacken the codebase...
r43346 }
Jun Wu
rebase: change internal format to support destination map...
r34006 legacydest = None
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 state = {}
Jun Wu
rebase: change internal format to support destination map...
r34006 destmap = {}
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403
Pulkit Goyal
rebase: check whether the rebasestate exists or not a bit early...
r38537 if True:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = repo.vfs(b"rebasestate")
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 for i, l in enumerate(f.read().splitlines()):
if i == 0:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'originalwd'] = repo[l].rev()
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 elif i == 1:
Jun Wu
rebase: change internal format to support destination map...
r34006 # this line should be empty in newer version. but legacy
# clients may still use it
if l:
legacydest = repo[l].rev()
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 elif i == 2:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'external'] = repo[l].rev()
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 elif i == 3:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'collapse'] = bool(int(l))
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 elif i == 4:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'keep'] = bool(int(l))
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 elif i == 5:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'keepbranches'] = bool(int(l))
elif i == 6 and not (len(l) == 81 and b':' in l):
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 # line 6 is a recent addition, so for backwards
# compatibility check that the line doesn't look like the
# oldrev:newrev lines
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'activebookmark'] = l
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args = l.split(b':')
Martin von Zweigbergk
rebase: convert "oldrev" to revnum earlier...
r37395 oldrev = repo[args[0]].rev()
Jun Wu
rebase: change internal format to support destination map...
r34006 newrev = args[1]
Jun Wu
rebase: remove revprecursor and revpruned states (BC)...
r33842 if newrev in legacystates:
continue
Jun Wu
rebase: change internal format to support destination map...
r34006 if len(args) > 2:
Martin von Zweigbergk
rebase: make "destnode" consistently a revnum and rename it to "destrev"...
r37394 destrev = repo[args[2]].rev()
Jun Wu
rebase: change internal format to support destination map...
r34006 else:
Martin von Zweigbergk
rebase: make "destnode" consistently a revnum and rename it to "destrev"...
r37394 destrev = legacydest
Martin von Zweigbergk
rebase: convert "oldrev" to revnum earlier...
r37395 destmap[oldrev] = destrev
Martin von Zweigbergk
rebase: remove unnecessary and incorrect handling of nullid...
r37396 if newrev == revtodostr:
Martin von Zweigbergk
rebase: convert "oldrev" to revnum earlier...
r37395 state[oldrev] = revtodo
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 # Legacy compat special case
else:
Martin von Zweigbergk
rebase: convert "oldrev" to revnum earlier...
r37395 state[oldrev] = repo[newrev].rev()
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if data[b'keepbranches'] is None:
raise error.Abort(_(b'.hg/rebasestate is incomplete'))
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'destmap'] = destmap
data[b'state'] = state
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 skipped = set()
# recompute the set of skipped revs
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not data[b'collapse']:
Jun Wu
rebase: change internal format to support destination map...
r34006 seen = set(destmap.values())
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 for old, new in sorted(state.items()):
if new != revtodo and new in seen:
skipped.add(old)
seen.add(new)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 data[b'skipped'] = skipped
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'computed skipped revs: %s\n'
% (b' '.join(b'%d' % r for r in sorted(skipped)) or b'')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403
Pulkit Goyal
rebase: refactor logic to read rebasestate in a separate function...
r38534 return data
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403
Jun Wu
rebase: change internal format to support destination map...
r34006 def _handleskippingobsolete(self, obsoleterevs, destmap):
Kostia Balytskyi
rebase: move handling of obsolete commits to be a separate RR class method
r29479 """Compute structures necessary for skipping obsolete revisions
obsoleterevs: iterable of all obsolete revisions in rebaseset
Jun Wu
rebase: change internal format to support destination map...
r34006 destmap: {srcrev: destrev} destination revisions
Kostia Balytskyi
rebase: move handling of obsolete commits to be a separate RR class method
r29479 """
self.obsoletenotrebased = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not self.ui.configbool(b'experimental', b'rebaseskipobsolete'):
Kostia Balytskyi
rebase: move handling of obsolete commits to be a separate RR class method
r29479 return
obsoleteset = set(obsoleterevs)
Augie Fackler
formatting: blacken the codebase...
r43346 (
self.obsoletenotrebased,
self.obsoletewithoutsuccessorindestination,
obsoleteextinctsuccessors,
) = _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
Kostia Balytskyi
rebase: move handling of obsolete commits to be a separate RR class method
r29479 skippedset = set(self.obsoletenotrebased)
Denis Laxalde
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
r35049 skippedset.update(self.obsoletewithoutsuccessorindestination)
Denis Laxalde
rebase: do not consider extincts for divergence detection (issue5782)...
r36013 skippedset.update(obsoleteextinctsuccessors)
Jun Wu
rebase: remove rebaseset from _checkobsrebase...
r33845 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
Kostia Balytskyi
rebase: move handling of obsolete commits to be a separate RR class method
r29479
Sushil khanchi
rebase: suppress warning thrown when aborting rebase in case of dryrun...
r38518 def _prepareabortorcontinue(self, isabort, backup=True, suppwarns=False):
Kostia Balytskyi
rebase: move abort/continue prep to be a method of the RR class...
r29472 try:
self.restorestatus()
Durham Goode
rebase: allow aborting if last-message.txt is missing...
r31225 self.collapsemsg = restorecollapsemsg(self.repo, isabort)
Kostia Balytskyi
rebase: move abort/continue prep to be a method of the RR class...
r29472 except error.RepoLookupError:
if isabort:
clearstatus(self.repo)
clearcollapsemsg(self.repo)
Augie Fackler
formatting: blacken the codebase...
r43346 self.repo.ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'rebase aborted (no revision is removed,'
b' only broken state is cleared)\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Kostia Balytskyi
rebase: move abort/continue prep to be a method of the RR class...
r29472 return 0
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b'cannot continue inconsistent rebase')
hint = _(b'use "hg rebase --abort" to clear broken state')
Kostia Balytskyi
rebase: move abort/continue prep to be a method of the RR class...
r29472 raise error.Abort(msg, hint=hint)
Sushil khanchi
rebase: move "backup" flag to rebaseruntime...
r38852
Kostia Balytskyi
rebase: move abort/continue prep to be a method of the RR class...
r29472 if isabort:
Sushil khanchi
rebase: move "backup" flag to rebaseruntime...
r38852 backup = backup and self.backupf
Martin von Zweigbergk
rebase: remove now-unnecessary arguments to _abort()...
r40892 return self._abort(backup=backup, suppwarns=suppwarns)
Kostia Balytskyi
rebase: move abort/continue prep to be a method of the RR class...
r29472
Jun Wu
rebase: change internal format to support destination map...
r34006 def _preparenewrebase(self, destmap):
if not destmap:
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473 return _nothingtorebase()
Jun Wu
rebase: change internal format to support destination map...
r34006 rebaseset = destmap.keys()
Martin von Zweigbergk
rebase: use rewriteutil.precheck() instead of reimplementing it...
r44386 if not self.keepf:
try:
rewriteutil.precheck(self.repo, rebaseset, action=b'rebase')
except error.Abort as e:
if e.hint is None:
Martin von Zweigbergk
rebase: restore i18n of a hint message...
r44393 e.hint = _(b'use --keep to keep original changesets')
Martin von Zweigbergk
rebase: use rewriteutil.precheck() instead of reimplementing it...
r44386 raise e
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473
Jun Wu
rebase: move working parent and bookmark for obsoleted revs (BC)...
r34010 result = buildstate(self.repo, destmap, self.collapsef)
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473
if not result:
# Empty state built, nothing to rebase
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.status(_(b'nothing to rebase\n'))
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473 return _nothingtorebase()
Jun Wu
rebase: change internal format to support destination map...
r34006 (self.originalwd, self.destmap, self.state) = result
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473 if self.collapsef:
Jun Wu
rebase: change internal format to support destination map...
r34006 dests = set(self.destmap.values())
if len(dests) != 1:
raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'--collapse does not work with multiple destinations')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jun Wu
rebase: change internal format to support destination map...
r34006 destrev = next(iter(dests))
Augie Fackler
formatting: blacken the codebase...
r43346 destancestors = self.repo.changelog.ancestors(
[destrev], inclusive=True
)
Jun Wu
rebase: remove self.destancestors...
r33846 self.external = externalparent(self.repo, self.state, destancestors)
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473
Jun Wu
rebase: change internal format to support destination map...
r34006 for destrev in sorted(set(destmap.values())):
dest = self.repo[destrev]
if dest.closesbranch() and not self.keepbranchesf:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.status(_(b'reopening closed branch head %s\n') % dest)
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473
Jun Wu
rebase: remove complex unhiding code...
r34096 self.prepared = True
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473
Phil Cohen
rebase: extract _assignworkingcopy...
r35334 def _assignworkingcopy(self):
Phil Cohen
rebase: add the --inmemory option flag; assign a wctx object for the rebase...
r35291 if self.inmemory:
from mercurial.context import overlayworkingctx
Augie Fackler
formatting: blacken the codebase...
r43346
Phil Cohen
rebase: add the --inmemory option flag; assign a wctx object for the rebase...
r35291 self.wctx = overlayworkingctx(self.repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.repo.ui.debug(b"rebasing in-memory\n")
Phil Cohen
rebase: add the --inmemory option flag; assign a wctx object for the rebase...
r35291 else:
self.wctx = self.repo[None]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.repo.ui.debug(b"rebasing on disk\n")
Augie Fackler
formatting: blacken the codebase...
r43346 self.repo.ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"rebase",
b"using in-memory rebase: %r\n",
Augie Fackler
formatting: blacken the codebase...
r43346 self.inmemory,
rebase_imm_used=self.inmemory,
)
Phil Cohen
rebase: extract _assignworkingcopy...
r35334
def _performrebase(self, tr):
self._assignworkingcopy()
repo, ui = self.repo, self.ui
Kostia Balytskyi
rebase: move core rebase logic to be a method of the RR class
r29477 if self.keepbranchesf:
# insert _savebranch at the start of extrafns so if
# there's a user-provided extrafn it can clobber branch if
# desired
self.extrafns.insert(0, _savebranch)
if self.collapsef:
branches = set()
for rev in self.state:
branches.add(repo[rev].branch())
if len(branches) > 1:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'cannot collapse multiple named branches')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Kostia Balytskyi
rebase: move core rebase logic to be a method of the RR class
r29477
Jun Wu
rebase: move working parent and bookmark for obsoleted revs (BC)...
r34010 # Calculate self.obsoletenotrebased
obsrevs = _filterobsoleterevs(self.repo, self.state)
self._handleskippingobsolete(obsrevs, self.destmap)
Kostia Balytskyi
rebase: move core rebase logic to be a method of the RR class
r29477
Jun Wu
rebase: use scmutil.cleanupnodes (issue5606) (BC)...
r33332 # Keep track of the active bookmarks in order to reset them later
Kostia Balytskyi
rebase: move core rebase logic to be a method of the RR class
r29477 self.activebookmark = self.activebookmark or repo._activebookmark
if self.activebookmark:
bookmarks.deactivate(repo)
Durham Goode
rebase: allow aborting if last-message.txt is missing...
r31225 # Store the state before we begin so users can run 'hg rebase --abort'
# if we fail before the transaction closes.
self.storestatus()
Martin von Zweigbergk
rebase: register status file generator only once when using single transaction...
r37049 if tr:
# When using single transaction, store state when transaction
# commits.
self.storestatus(tr)
Durham Goode
rebase: allow aborting if last-message.txt is missing...
r31225
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 cands = [k for k, v in pycompat.iteritems(self.state) if v == revtodo]
Augie Fackler
formatting: blacken the codebase...
r43346 p = repo.ui.makeprogress(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"rebasing"), unit=_(b'changesets'), total=len(cands)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
rebase: move constant expressions out of inner loop in _performrebase()...
r36951 def progress(ctx):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 p.increment(item=(b"%d:%s" % (ctx.rev(), ctx)))
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
rebase: move constant expressions out of inner loop in _performrebase()...
r36951 allowdivergence = self.ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'experimental', b'evolution.allowdivergence'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jun Wu
rebase: sort destmap topologically...
r34008 for subset in sortsource(self.destmap):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
Martin von Zweigbergk
rebase: inline _performrebasesubset()...
r36950 if not allowdivergence:
sortedrevs -= self.repo.revs(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'descendants(%ld) and not %ld',
Martin von Zweigbergk
rebase: inline _performrebasesubset()...
r36950 self.obsoletewithoutsuccessorindestination,
self.obsoletewithoutsuccessorindestination,
)
for rev in sortedrevs:
self._rebasenode(tr, rev, allowdivergence, progress)
Martin von Zweigbergk
rebase: use progress helper...
r38396 p.complete()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b'rebase merging completed\n'))
Jun Wu
rebase: sort destmap topologically...
r34008
Martin von Zweigbergk
rebase: extract common _concludenode()...
r37051 def _concludenode(self, rev, p1, p2, editor, commitmsg=None):
'''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.'''
repo = self.repo
Martin von Zweigbergk
rebase: pass in ctx, not rev, to conclude[memory]node()...
r37052 ctx = repo[rev]
Martin von Zweigbergk
rebase: look up commit message to reuse outside of conclude[memory]node()...
r37053 if commitmsg is None:
commitmsg = ctx.description()
Martin von Zweigbergk
rebase: look up default date outside of conclude[memory]node()...
r37059 date = self.date
if date is None:
date = ctx.date()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extra = {b'rebase_source': ctx.hex()}
Martin von Zweigbergk
rebase: inline _makextrafn() now that we have only one caller...
r37055 for c in self.extrafns:
c(ctx, extra)
Martin von Zweigbergk
rebase: pass in "keepbranch" to conclude[memory]node()...
r37056 keepbranch = self.keepbranchesf and repo[p1].branch() != ctx.branch()
Martin von Zweigbergk
rebase: pass in entire "overrides" dict to conclude[memory]node()...
r37057 destphase = max(ctx.phase(), phases.draft)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'phases', b'new-commit'): destphase}
Martin von Zweigbergk
rebase: pass in entire "overrides" dict to conclude[memory]node()...
r37057 if keepbranch:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides[(b'ui', b'allowemptycommit')] = True
with repo.ui.configoverride(overrides, b'rebase'):
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 if self.inmemory:
Augie Fackler
formatting: blacken the codebase...
r43346 newnode = commitmemorynode(
repo,
p1,
p2,
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 wctx=self.wctx,
extra=extra,
commitmsg=commitmsg,
editor=editor,
Martin von Zweigbergk
rebase: pass in "user" instead of "ctx" to conclude[memory]node()...
r37060 user=ctx.user(),
Augie Fackler
formatting: blacken the codebase...
r43346 date=date,
)
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 mergemod.mergestate.clean(repo)
else:
Augie Fackler
formatting: blacken the codebase...
r43346 newnode = commitnode(
repo,
p1,
p2,
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 extra=extra,
commitmsg=commitmsg,
editor=editor,
Martin von Zweigbergk
rebase: pass in "user" instead of "ctx" to conclude[memory]node()...
r37060 user=ctx.user(),
Augie Fackler
formatting: blacken the codebase...
r43346 date=date,
)
Martin von Zweigbergk
rebase: extract common _concludenode()...
r37051
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 if newnode is None:
# If it ended up being a no-op commit, then the normal
# merge state clean-up path doesn't happen, so do it
# here. Fix issue5494
mergemod.mergestate.clean(repo)
return newnode
Martin von Zweigbergk
rebase: extract common _concludenode()...
r37051
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 def _rebasenode(self, tr, rev, allowdivergence, progressfn):
Jun Wu
rebase: sort destmap topologically...
r34008 repo, ui, opts = self.repo, self.ui, self.opts
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 dest = self.destmap[rev]
ctx = repo[rev]
desc = _ctxdesc(ctx)
if self.state[rev] == rev:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'already rebased %s\n') % desc)
Augie Fackler
formatting: blacken the codebase...
r43346 elif (
not allowdivergence
and rev in self.obsoletewithoutsuccessorindestination
):
msg = (
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'note: not rebasing %s and its descendants as '
b'this would cause divergence\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% desc
)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 repo.ui.status(msg)
self.skipped.add(rev)
elif rev in self.obsoletenotrebased:
succ = self.obsoletenotrebased[rev]
if succ is None:
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 msg = _(b'note: not rebasing %s, it has no successor\n') % desc
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 else:
succdesc = _ctxdesc(repo[succ])
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b'note: not rebasing %s, already in destination as %s\n'
Augie Fackler
formatting: blacken the codebase...
r43346 ) % (desc, succdesc)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 repo.ui.status(msg)
# Make clearrebased aware state[rev] is not a true successor
self.skipped.add(rev)
# Record rev as moved to its desired destination in self.state.
# This helps bookmark and working parent movement.
Augie Fackler
formatting: blacken the codebase...
r43346 dest = max(
adjustdest(repo, rev, self.destmap, self.state, self.skipped)
)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 self.state[rev] = dest
elif self.state[rev] == revtodo:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'rebasing %s\n') % desc)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 progressfn(ctx)
Augie Fackler
formatting: blacken the codebase...
r43346 p1, p2, base = defineparents(
repo,
rev,
self.destmap,
self.state,
self.skipped,
self.obsoletenotrebased,
)
Martin von Zweigbergk
rebase: abort in-mem rebase if there's a dirty merge state...
r40836 if not self.inmemory and len(repo[None].parents()) == 2:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b'resuming interrupted rebase\n')
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
with ui.configoverride(overrides, b'rebase'):
Augie Fackler
formatting: blacken the codebase...
r43346 stats = rebasenode(
repo,
rev,
p1,
base,
self.collapsef,
dest,
wctx=self.wctx,
)
Gregory Szorc
merge: deprecate accessing update results by index...
r37143 if stats.unresolvedcount > 0:
Martin von Zweigbergk
rebase: get "inmemory" state directly from rebase runtime...
r37045 if self.inmemory:
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 raise error.InMemoryMergeConflictsError()
else:
raise error.InterventionRequired(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unresolved conflicts (see hg '
b'resolve, then hg rebase --continue)'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 if not self.collapsef:
merging = p2 != nullrev
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 editform = cmdutil.mergeeditform(merging, b'rebase')
Augie Fackler
formatting: blacken the codebase...
r43346 editor = cmdutil.getcommiteditor(
editform=editform, **pycompat.strkwargs(opts)
)
Martin von Zweigbergk
rebase: extract common _concludenode()...
r37051 newnode = self._concludenode(rev, p1, p2, editor)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 else:
# Skip commit if we are collapsing
Martin von Zweigbergk
rebase: get "inmemory" state directly from rebase runtime...
r37045 if self.inmemory:
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 self.wctx.setbase(repo[p1])
else:
repo.setparents(repo[p1].node())
newnode = None
# Update the state
if newnode is not None:
self.state[rev] = repo[newnode].rev()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.debug(b'rebased as %s\n' % short(newnode))
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 else:
Kostia Balytskyi
rebase: move core rebase logic to be a method of the RR class
r29477 if not self.collapsef:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'note: not rebasing %s, its destination already '
b'has all its changes\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% desc
)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 self.skipped.add(rev)
self.state[rev] = p1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.debug(b'next revision set to %d\n' % p1)
Martin von Zweigbergk
rebase: extract function for rebasing a single node...
r36949 else:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'already rebased %s as %s\n') % (desc, repo[self.state[rev]])
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
rebase: store rebase state after each commit...
r37050 if not tr:
# When not using single transaction, store state after each
# commit is completely done. On InterventionRequired, we thus
# won't store the status. Instead, we'll hit the "len(parents) == 2"
# case and realize that the commit was in progress.
self.storestatus()
Kostia Balytskyi
rebase: move core rebase logic to be a method of the RR class
r29477
Sushil khanchi
rebase: move "backup" flag to rebaseruntime...
r38852 def _finishrebase(self):
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478 repo, ui, opts = self.repo, self.ui, self.opts
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fm = ui.formatter(b'rebase', opts)
Pulkit Goyal
rebase: add support to output nodechanges...
r34884 fm.startitem()
Martin von Zweigbergk
rebase: delete obsolete internal "keepopen" option...
r36789 if self.collapsef:
Augie Fackler
formatting: blacken the codebase...
r43346 p1, p2, _base = defineparents(
repo,
min(self.state),
self.destmap,
self.state,
self.skipped,
self.obsoletenotrebased,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 editopt = opts.get(b'edit')
editform = b'rebase.collapse'
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478 if self.collapsemsg:
commitmsg = self.collapsemsg
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 commitmsg = b'Collapsed revision'
Yuya Nishihara
rebase: sort collapsed revisions in commit message (issue5643)...
r33624 for rebased in sorted(self.state):
Jun Wu
rebase: remove "state >= revtodo" condition...
r33847 if rebased not in self.skipped:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 commitmsg += b'\n* %s' % repo[rebased].description()
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478 editopt = True
editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
Kostia Balytskyi
rebase: remove sortedstate-related confusion...
r29552 revtoreuse = max(self.state)
Durham Goode
rebase: use one dirstateguard for when using rebase.singletransaction...
r33621
Augie Fackler
formatting: blacken the codebase...
r43346 newnode = self._concludenode(
revtoreuse, p1, self.external, editor, commitmsg=commitmsg
)
Martin von Zweigbergk
rebase: fix issue 5494 also with --collapse...
r36946
Jun Wu
rebase: only change self.state when collapsing in _finishrebase...
r33864 if newnode is not None:
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478 newrev = repo[newnode].rev()
Augie Fackler
py3: use default dict iterator instead of iterkeys...
r36313 for oldrev in self.state:
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478 self.state[oldrev] = newrev
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'qtip' in repo.tags():
Augie Fackler
formatting: blacken the codebase...
r43346 updatemq(repo, self.state, self.skipped, **pycompat.strkwargs(opts))
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478
# restore original working directory
# (we do this before stripping)
newwd = self.state.get(self.originalwd, self.originalwd)
Jun Wu
rebase: remove revprecursor and revpruned states (BC)...
r33842 if newwd < 0:
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478 # original directory is a parent of rebase set root or ignored
newwd = self.originalwd
Martin von Zweigbergk
rebase: allow in-memory merge of the working copy parent...
r36993 if newwd not in [c.rev() for c in repo[None].parents()]:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b"update back to initial working directory parent\n"))
Yuya Nishihara
cleanup: pass in overwrite flag to hg.updaterepo() as named argument...
r38527 hg.updaterepo(repo, newwd, overwrite=False)
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478
Jun Wu
rebase: move bookmarks with --keep (issue5682)...
r34364 collapsedas = None
Martin von Zweigbergk
rebase: collapse two nested if-conditions...
r36792 if self.collapsef and not self.keepf:
collapsedas = newnode
Augie Fackler
formatting: blacken the codebase...
r43346 clearrebased(
ui,
repo,
self.destmap,
self.state,
self.skipped,
collapsedas,
self.keepf,
fm=fm,
backup=self.backupf,
)
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478
clearstatus(repo)
clearcollapsemsg(repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b"rebase completed\n"))
util.unlinkpath(repo.sjoin(b'undo'), ignoremissing=True)
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478 if self.skipped:
skippedlen = len(self.skipped)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b"%d revisions have been skipped\n") % skippedlen)
Pulkit Goyal
rebase: add support to output nodechanges...
r34884 fm.end()
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478
Augie Fackler
formatting: blacken the codebase...
r43346 if (
self.activebookmark
and self.activebookmark in repo._bookmarks
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 and repo[b'.'].node() == repo._bookmarks[self.activebookmark]
Augie Fackler
formatting: blacken the codebase...
r43346 ):
bookmarks.activate(repo, self.activebookmark)
Kostia Balytskyi
rebase: move rebase finish logic to be a method of the RR class...
r29478
Martin von Zweigbergk
rebase: remove now-unnecessary arguments to _abort()...
r40892 def _abort(self, backup=True, suppwarns=False):
'''Restore the repository to its original state.'''
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891
Martin von Zweigbergk
rebase: remove now-unnecessary arguments to _abort()...
r40892 repo = self.repo
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891 try:
# If the first commits in the rebased set get skipped during the
# rebase, their values within the state mapping will be the dest
# rev id. The rebased list must must not contain the dest rev
# (issue4896)
Augie Fackler
formatting: blacken the codebase...
r43346 rebased = [
s
for r, s in self.state.items()
if s >= 0 and s != r and s != self.destmap[r]
]
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891 immutable = [d for d in rebased if not repo[d].mutable()]
cleanup = True
if immutable:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"warning: can't clean up public changesets %s\n")
% b', '.join(bytes(repo[r]) for r in immutable),
hint=_(b"see 'hg help phases' for details"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891 cleanup = False
descendants = set()
if rebased:
descendants = set(repo.changelog.descendants(rebased))
if descendants - set(rebased):
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"warning: new changesets detected on "
b"destination branch, can't strip\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891 cleanup = False
if cleanup:
if rebased:
strippoints = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 c.node() for c in repo.set(b'roots(%ld)', rebased)
Augie Fackler
formatting: blacken the codebase...
r43346 ]
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891
updateifonnodes = set(rebased)
Martin von Zweigbergk
rebase: remove now-unnecessary arguments to _abort()...
r40892 updateifonnodes.update(self.destmap.values())
updateifonnodes.add(self.originalwd)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shouldupdate = repo[b'.'].rev() in updateifonnodes
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891
# Update away from the rebase if necessary
Martin von Zweigbergk
rebase: remove now-unnecessary arguments to _abort()...
r40892 if shouldupdate or needupdate(repo, self.state):
Augie Fackler
formatting: blacken the codebase...
r43346 mergemod.update(
repo, self.originalwd, branchmerge=False, force=True
)
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891
# Strip from the first rebased revision
if rebased:
repair.strip(repo.ui, repo, strippoints, backup=backup)
Martin von Zweigbergk
rebase: remove now-unnecessary arguments to _abort()...
r40892 if self.activebookmark and self.activebookmark in repo._bookmarks:
bookmarks.activate(repo, self.activebookmark)
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891
finally:
clearstatus(repo)
clearcollapsemsg(repo)
if not suppwarns:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.warn(_(b'rebase aborted\n'))
Martin von Zweigbergk
rebase: move abort() onto rebaseruntime...
r40891 return 0
Augie Fackler
formatting: blacken the codebase...
r43346
@command(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'rebase',
Augie Fackler
formatting: blacken the codebase...
r43346 [
(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b's',
b'source',
b'',
_(b'rebase the specified changeset and descendants'),
_(b'REV'),
Augie Fackler
formatting: blacken the codebase...
r43346 ),
(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'b',
b'base',
b'',
_(b'rebase everything from branching point of specified changeset'),
_(b'REV'),
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'r', b'rev', [], _(b'rebase these revisions'), _(b'REV')),
Augie Fackler
formatting: blacken the codebase...
r43346 (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'd',
b'dest',
b'',
_(b'rebase onto the specified changeset'),
_(b'REV'),
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'', b'collapse', False, _(b'collapse the rebased changesets')),
Augie Fackler
formatting: blacken the codebase...
r43346 (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'm',
b'message',
b'',
_(b'use text as collapse commit message'),
_(b'TEXT'),
),
(b'e', b'edit', False, _(b'invoke editor on commit messages')),
(
b'l',
b'logfile',
b'',
_(b'read collapse commit message from file'),
_(b'FILE'),
Augie Fackler
formatting: blacken the codebase...
r43346 ),
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'k', b'keep', False, _(b'keep original changesets')),
(b'', b'keepbranches', False, _(b'keep original branch names')),
(b'D', b'detach', False, _(b'(DEPRECATED)')),
(b'i', b'interactive', False, _(b'(DEPRECATED)')),
(b't', b'tool', b'', _(b'specify merge tool')),
(b'', b'stop', False, _(b'stop interrupted rebase')),
(b'c', b'continue', False, _(b'continue an interrupted rebase')),
(b'a', b'abort', False, _(b'abort an interrupted rebase')),
Augie Fackler
formatting: blacken the codebase...
r43346 (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'',
b'auto-orphans',
b'',
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'automatically rebase orphan revisions '
b'in the specified revset (EXPERIMENTAL)'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
),
]
+ cmdutil.dryrunopts
+ cmdutil.formatteropts
+ cmdutil.confirmopts,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'[-s REV | -b REV] [-d REV] [OPTION]'),
Augie Fackler
formatting: blacken the codebase...
r43346 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
)
Stefano Tortarolo
Add rebase extension
r6906 def rebase(ui, repo, **opts):
"""move changeset (and descendants) to a different branch
Martin Geisler
rebase: word-wrap help texts at 70 characters
r7999 Rebase uses repeated merging to graft changesets from one part of
Greg Ward
rebase: improve help text...
r10646 history (the source) onto another (the destination). This can be
Martin Geisler
rebase: stress that only local changesets should be rebased
r11188 useful for linearizing *local* changes relative to a master
Greg Ward
rebase: improve help text...
r10646 development tree.
timeless
rebase: simplify documentation about public commits...
r27454 Published commits cannot be rebased (see :hg:`help phases`).
To copy commits, see :hg:`help graft`.
Kevin Bullock
rebase: mention phases in the help...
r18516
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 If you don't specify a destination changeset (``-d/--dest``), rebase
will use the same logic as :hg:`merge` to pick a destination. if
the current branch contains exactly one other head, the other head
is merged with by default. Otherwise, an explicit revision with
which to merge with must be provided. (destination changeset is not
modified by rebasing, but new changesets are added as its
descendants.)
Greg Ward
rebase: improve help text...
r10646
FUJIWARA Katsunori
doc: prevent non-literal text block from being treated as literal one...
r27956 Here are the ways to select changesets:
timeless
rebase: simplify documentation about selecting commits to rebase
r27455
1. Explicitly select them using ``--rev``.
Greg Ward
rebase: improve help text...
r10646
timeless
rebase: simplify documentation about selecting commits to rebase
r27455 2. Use ``--source`` to select a root changeset and include all of its
FUJIWARA Katsunori
doc: use correct indentation for enumeration...
r27959 descendants.
timeless
rebase: simplify documentation about selecting commits to rebase
r27455
3. Use ``--base`` to select a changeset; rebase will find ancestors
FUJIWARA Katsunori
doc: use correct indentation for enumeration...
r27959 and their descendants which are not also ancestors of the destination.
Pierre-Yves David
rebase: mention --rev in the help...
r18518
Manuel Jacob
rebase: add missing dashes in help text
r41972 4. If you do not specify any of ``--rev``, ``--source``, or ``--base``,
FUJIWARA Katsunori
doc: use correct indentation for enumeration...
r27959 rebase will use ``--base .`` as above.
timeless
rebase: restore help for rebase w/o args (issue5059)...
r27932
Jun Wu
rebase: enable multidest by default...
r35288 If ``--source`` or ``--rev`` is used, special names ``SRC`` and ``ALLSRC``
can be used in ``--dest``. Destination would be calculated per source
revision with ``SRC`` substituted by that single source revision and
``ALLSRC`` substituted by all source revisions.
timeless
rebase: simplify documentation about --keep...
r27456 Rebase will destroy original changesets unless you use ``--keep``.
It will also move your bookmarks (even if you do).
Some changesets may be dropped if they do not contribute changes
(e.g. merges from the destination branch).
Greg Ward
rebase: improve help text...
r10646
timeless
rebase: simplify documentation about heads
r27457 Unlike ``merge``, rebase will do nothing if you are at the branch tip of
a named branch with two heads. You will need to explicitly specify source
and/or destination.
Stefano Tortarolo
Add rebase extension
r6906
timeless
rebase: mention help merge-tools in help
r28001 If you need to use a tool to automate merge/conflict decisions, you
can specify one with ``--tool``, see :hg:`help merge-tools`.
timeless
rebase: document that tool does not apply to deleted files
r28002 As a caveat: the tool will not be used to mediate when a file was
deleted, there is no hook presently available for this.
timeless
rebase: mention help merge-tools in help
r28001
timeless
rebase: mention conflict in documentation instead of merge
r27458 If a rebase is interrupted to manually resolve a conflict, it can be
Sushil khanchi
rebase: include --stop option in documentation...
r39130 continued with --continue/-c, aborted with --abort/-a, or stopped with
--stop.
Matt Mackall
rebase: add error codes...
r11205
Matt Mackall
rebase: add help examples
r22790 .. container:: verbose
Examples:
- move "local changes" (current commit back to branching point)
to the current branch tip after a pull::
hg rebase
- move a single changeset to the stable branch::
hg rebase -r 5f493448 -d stable
- splice a commit and all its descendants onto another part of history::
hg rebase --source c0c3 --dest 4cf9
- rebase everything on a branch marked by a bookmark onto the
default branch::
hg rebase --base myfeature --dest default
- collapse a sequence of changes into a single commit::
hg rebase --collapse -r 1520:1525 -d .
- move a named branch while preserving its name::
hg rebase -r "branch(featureX)" -d 1.3 --keepbranches
Jun Wu
rebase: enable multidest by default...
r35288 - stabilize orphaned changesets so history looks linear::
hg rebase -r 'orphan()-obsolete()'\
-d 'first(max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::) +\
max(::((roots(ALLSRC) & ::SRC)^)-obsolete()))'
Ryan McElroy
rebase: add flag to require destination...
r31558 Configuration Options:
You can make rebase require a destination if you set the following config
FUJIWARA Katsunori
help: apply bulk fixes for indentation and literal blocking issues...
r32085 option::
Ryan McElroy
rebase: add flag to require destination...
r31558
[commands]
FUJIWARA Katsunori
rebase: fix incorrect configuration example...
r32084 rebase.requiredest = True
Ryan McElroy
rebase: add flag to require destination...
r31558
Durham Goode
rebase: add config to move rebase into a single transaction...
r33569 By default, rebase will close the transaction after each commit. For
performance purposes, you can configure rebase to use a single transaction
across the entire rebase. WARNING: This setting introduces a significant
risk of losing the work you've done in a rebase if the rebase aborts
unexpectedly::
[rebase]
singletransaction = True
Phil Cohen
rebase: replace --inmemory flag with rebase.experimental.inmemory config...
r35389 By default, rebase writes to the working copy, but you can configure it to
Kyle Lippincott
rebase: tweak description of inmemory working even w/ dirty working dir...
r42640 run in-memory for better performance. When the rebase is not moving the
parent(s) of the working copy (AKA the "currently checked out changesets"),
this may also allow it to run even if the working copy is dirty::
Phil Cohen
rebase: replace --inmemory flag with rebase.experimental.inmemory config...
r35389
[rebase]
experimental.inmemory = True
Ryan McElroy
rebase: add flag to require destination...
r31558 Return Values:
FUJIWARA Katsunori
rebase: add description about exit code when there are unresolved conflicts
r19971 Returns 0 on success, 1 if nothing to rebase or there are
unresolved conflicts.
Matt Mackall
rebase: add help examples
r22790
Stefano Tortarolo
Add rebase extension
r6906 """
Yuya Nishihara
rebase: convert opts dict to bytes at once
r38520 opts = pycompat.byteskwargs(opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 inmemory = ui.configbool(b'rebase', b'experimental.inmemory')
Martin von Zweigbergk
rebase: use cmdutil.check_at_most_one_arg() for action...
r44351 action = cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
Martin von Zweigbergk
rebase: use cmdutil.check_incompatible_arguments() for action+confirm/dryrun...
r44379 if action:
cmdutil.check_incompatible_arguments(
opts, action, b'confirm', b'dry_run'
)
Martin von Zweigbergk
rebase: use cmdutil.check_at_most_one_arg() for action+revision...
r44383 cmdutil.check_incompatible_arguments(
opts, action, b'rev', b'source', b'base', b'dest'
)
Martin von Zweigbergk
rebase: use cmdutil.check_at_most_one_arg() for --confirm/--dry-run...
r44378 cmdutil.check_at_most_one_arg(opts, b'confirm', b'dry_run')
Martin von Zweigbergk
rebase: use cmdutil.check_at_most_one_arg() for -b/-s/-r...
r44381 cmdutil.check_at_most_one_arg(opts, b'rev', b'source', b'base')
Sushil khanchi
rebase: add dry-run functionality...
r38391
Yuya Nishihara
rebase: turn off inmemory flag on --stop...
r39137 if action or repo.currenttransaction() is not None:
Phil Cohen
rebase: rerun a rebase on-disk if IMM merge conflicts arise...
r35321 # in-memory rebase is not compatible with resuming rebases.
Phil Cohen
rebase: don't run IMM if running rebase in a transaction...
r35719 # (Or if it is run within a transaction, since the restart logic can
# fail the entire transaction.)
Phil Cohen
rebase: replace --inmemory flag with rebase.experimental.inmemory config...
r35389 inmemory = False
Phil Cohen
rebase: rerun a rebase on-disk if IMM merge conflicts arise...
r35321
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'auto_orphans'):
Martin von Zweigbergk
rebase: use cmdutil.check_incompatible_arguments() for --auto-orphans...
r44382 disallowed_opts = set(opts) - {b'auto_orphans'}
cmdutil.check_incompatible_arguments(
opts, b'auto_orphans', *disallowed_opts
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 userrevs = list(repo.revs(opts.get(b'auto_orphans')))
opts[b'rev'] = [revsetlang.formatspec(b'%ld and orphan()', userrevs)]
opts[b'dest'] = b'_destautoorphanrebase(SRC)'
Augie Fackler
rebase: introduce support for automatically rebasing orphan changes...
r37805
Martin von Zweigbergk
rebase: inline single-use `dryrun` and `confirm` variables...
r44380 if opts.get(b'dry_run') or opts.get(b'confirm'):
Yuya Nishihara
rebase: use action variable to select things to do
r39136 return _dryrunrebase(ui, repo, action, opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif action == b'stop':
Sushil khanchi
rebase: add --stop option to stop rebase at any point (issue5206)...
r39128 rbsrt = rebaseruntime(repo, ui)
with repo.wlock(), repo.lock():
Sushil khanchi
rebase: cover restorestatus() by lock to prevent it from being updated...
r39152 rbsrt.restorestatus()
if rbsrt.collapsef:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"cannot stop in --collapse session"))
Sushil khanchi
rebase: cover restorestatus() by lock to prevent it from being updated...
r39152 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
if not (rbsrt.keepf or allowunstable):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"cannot remove original changesets with"
b" unrebased descendants"
Augie Fackler
formatting: blacken the codebase...
r43346 ),
hint=_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'either enable obsmarkers to allow unstable '
b'revisions or use --keep to keep original '
b'changesets'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
)
Sushil khanchi
rebase: add --stop option to stop rebase at any point (issue5206)...
r39128 if needupdate(repo, rbsrt.state):
# update to the current working revision
# to clear interrupted merge
hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
rbsrt._finishrebase()
return 0
Sushil khanchi
rebase: add dry-run functionality...
r38391 elif inmemory:
Phil Cohen
rebase: rerun a rebase on-disk if IMM merge conflicts arise...
r35321 try:
# in-memory merge doesn't support conflicts, so if we hit any, abort
# and re-run as an on-disk merge.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'rebase', b'singletransaction'): True}
with ui.configoverride(overrides, b'rebase'):
Yuya Nishihara
rebase: use action variable to select things to do
r39136 return _dorebase(ui, repo, action, opts, inmemory=inmemory)
Phil Cohen
rebase: rerun a rebase on-disk if IMM merge conflicts arise...
r35321 except error.InMemoryMergeConflictsError:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'hit merge conflicts; re-running rebase without in-memory'
b' merge\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Martin von Zweigbergk
rebase: preserve working copy when redoing in-mem rebase on disk...
r40835 # TODO: Make in-memory merge not use the on-disk merge state, so
# we don't have to clean it here
mergemod.mergestate.clean(repo)
clearstatus(repo)
clearcollapsemsg(repo)
Yuya Nishihara
rebase: use action variable to select things to do
r39136 return _dorebase(ui, repo, action, opts, inmemory=False)
Phil Cohen
rebase: rerun a rebase on-disk if IMM merge conflicts arise...
r35321 else:
Yuya Nishihara
rebase: use action variable to select things to do
r39136 return _dorebase(ui, repo, action, opts)
Phil Cohen
rebase: rerun a rebase on-disk if IMM merge conflicts arise...
r35321
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
rebase: use action variable to select things to do
r39136 def _dryrunrebase(ui, repo, action, opts):
Yuya Nishihara
rebase: convert opts dict to bytes at once
r38520 rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 confirm = opts.get(b'confirm')
Sushil khanchi
rebase: add --confirm option...
r38689 if confirm:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'starting in-memory rebase\n'))
Sushil khanchi
rebase: add --confirm option...
r38689 else:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'starting dry-run rebase; repository will not be changed\n')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Sushil khanchi
rebase: extract dryrun as a function...
r38515 with repo.wlock(), repo.lock():
Sushil khanchi
rebase: add --confirm option...
r38689 needsabort = True
Sushil khanchi
rebase: extract dryrun as a function...
r38515 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 overrides = {(b'rebase', b'singletransaction'): True}
with ui.configoverride(overrides, b'rebase'):
Augie Fackler
formatting: blacken the codebase...
r43346 _origrebase(
ui,
repo,
action,
opts,
rbsrt,
inmemory=True,
leaveunfinished=True,
)
Sushil khanchi
rebase: extract dryrun as a function...
r38515 except error.InMemoryMergeConflictsError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'hit a merge conflict\n'))
Sushil khanchi
rebase: extract dryrun as a function...
r38515 return 1
Augie Fackler
rebase: fix bug that prevented dry-run rebases from printing failures...
r42277 except error.Abort:
needsabort = False
raise
Sushil khanchi
rebase: extract dryrun as a function...
r38515 else:
Sushil khanchi
rebase: add --confirm option...
r38689 if confirm:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'rebase completed successfully\n'))
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 if not ui.promptchoice(_(b'apply changes (yn)?$$ &Yes $$ &No')):
Sushil khanchi
rebase: add --confirm option...
r38689 # finish unfinished rebase
Sushil khanchi
rebase: move "backup" flag to rebaseruntime...
r38852 rbsrt._finishrebase()
Sushil khanchi
rebase: add --confirm option...
r38689 else:
Augie Fackler
formatting: blacken the codebase...
r43346 rbsrt._prepareabortorcontinue(
isabort=True, backup=False, suppwarns=True
)
Sushil khanchi
rebase: add --confirm option...
r38689 needsabort = False
else:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'dry-run rebase completed successfully; run without'
b' -n/--dry-run to perform this rebase\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Sushil khanchi
rebase: extract dryrun as a function...
r38515 return 0
finally:
Sushil khanchi
rebase: add --confirm option...
r38689 if needsabort:
# no need to store backup in case of dryrun
Augie Fackler
formatting: blacken the codebase...
r43346 rbsrt._prepareabortorcontinue(
isabort=True, backup=False, suppwarns=True
)
Sushil khanchi
rebase: extract dryrun as a function...
r38515
Yuya Nishihara
rebase: use action variable to select things to do
r39136 def _dorebase(ui, repo, action, opts, inmemory=False):
Yuya Nishihara
rebase: convert opts dict to bytes at once
r38520 rbsrt = rebaseruntime(repo, ui, inmemory, opts)
Yuya Nishihara
rebase: use action variable to select things to do
r39136 return _origrebase(ui, repo, action, opts, rbsrt, inmemory=inmemory)
Sushil khanchi
rebase: split _origrebase() for conveniece in dryrun...
r38516
Augie Fackler
formatting: blacken the codebase...
r43346
def _origrebase(
ui, repo, action, opts, rbsrt, inmemory=False, leaveunfinished=False
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 assert action != b'stop'
Martin von Zweigbergk
rebase: use context manager for locking in rebase()
r32917 with repo.wlock(), repo.lock():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'interactive'):
timeless@mozdev.org
rebase: enable histedit for useful help with it
r26496 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if extensions.find(b'histedit'):
enablehistedit = b''
timeless@mozdev.org
rebase: enable histedit for useful help with it
r26496 except KeyError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 enablehistedit = b" --config extensions.histedit="
help = b"hg%s help -e histedit" % enablehistedit
Augie Fackler
formatting: blacken the codebase...
r43346 msg = (
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"interactive history editing is supported by the "
b"'histedit' extension (see \"%s\")"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% help
)
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg)
David Soria Parra
rebase: add a deprecated -i/--interactive flag...
r22382
Kostia Balytskyi
rebase: move collapse-related local variables to the RR class...
r29400 if rbsrt.collapsemsg and not rbsrt.collapsef:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'message can only be specified with collapse'))
Radomir Dopieralski
rebase: add -m/--message to rebase --collapse (issue2389)...
r13661
Yuya Nishihara
rebase: use action variable to select things to do
r39136 if action:
Kostia Balytskyi
rebase: move collapse-related local variables to the RR class...
r29400 if rbsrt.collapsef:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'cannot use collapse with continue or abort')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if action == b'abort' and opts.get(b'tool', False):
ui.warn(_(b'tool option will be ignored\n'))
if action == b'continue':
timeless
rebase: check for conflicts before continuing...
r30273 ms = mergemod.mergestate.read(repo)
Augie Fackler
rebase: refer to checkunresolved by its new name
r30495 mergeutil.checkunresolved(ms)
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 retcode = rbsrt._prepareabortorcontinue(
isabort=(action == b'abort')
)
Kostia Balytskyi
rebase: move abort/continue prep to be a method of the RR class...
r29472 if retcode is not None:
return retcode
Stefano Tortarolo
Add rebase extension
r6906 else:
Martin von Zweigbergk
rebase: inline single-use variables passed to _definedestmap()...
r44384 # search default destination in this space
# used in the 'hg pull --rebase' case, see issue 5214.
destspace = opts.get(b'_destspace')
Augie Fackler
formatting: blacken the codebase...
r43346 destmap = _definedestmap(
ui,
repo,
inmemory,
Martin von Zweigbergk
rebase: inline single-use variables passed to _definedestmap()...
r44384 opts.get(b'dest', None),
opts.get(b'source', None),
opts.get(b'base', None),
opts.get(b'rev', []),
Augie Fackler
formatting: blacken the codebase...
r43346 destspace=destspace,
)
Jun Wu
rebase: change internal format to support destination map...
r34006 retcode = rbsrt._preparenewrebase(destmap)
Kostia Balytskyi
rebase: move new rebase preparation to be a method of the RR class...
r29473 if retcode is not None:
return retcode
Martin von Zweigbergk
rebase: only store collapse message once...
r36793 storecollapsemsg(repo, rbsrt.collapsemsg)
Mads Kiilerich
rebase: tell when reopening a closed branch head...
r21027
Durham Goode
rebase: add config to move rebase into a single transaction...
r33569 tr = None
Durham Goode
rebase: use one dirstateguard for when using rebase.singletransaction...
r33621
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 singletr = ui.configbool(b'rebase', b'singletransaction')
Durham Goode
rebase: use one dirstateguard for when using rebase.singletransaction...
r33621 if singletr:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr = repo.transaction(b'rebase')
Phil Cohen
rebase: don't take out a dirstate guard for in-memory rebase...
r35496
# If `rebase.singletransaction` is enabled, wrap the entire operation in
# one transaction here. Otherwise, transactions are obtained when
# committing each node, which is slower but allows partial success.
Durham Goode
rebase: add config to move rebase into a single transaction...
r33569 with util.acceptintervention(tr):
Phil Cohen
rebase: don't take out a dirstate guard for in-memory rebase...
r35496 # Same logic for the dirstate guard, except we don't create one when
# rebasing in-memory (it's not needed).
Martin von Zweigbergk
rebase: reduce scope of "dsguard" variables a bit...
r36791 dsguard = None
Phil Cohen
rebase: don't take out a dirstate guard for in-memory rebase...
r35496 if singletr and not inmemory:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
Durham Goode
rebase: use one dirstateguard for when using rebase.singletransaction...
r33621 with util.acceptintervention(dsguard):
rbsrt._performrebase(tr)
Sushil khanchi
rebase: add dry-run functionality...
r38391 if not leaveunfinished:
Sushil khanchi
rebase: move "backup" flag to rebaseruntime...
r38852 rbsrt._finishrebase()
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: blacken the codebase...
r43346
def _definedestmap(
ui,
repo,
inmemory,
destf=None,
srcf=None,
basef=None,
revf=None,
destspace=None,
):
Jun Wu
rebase: change internal format to support destination map...
r34006 """use revisions argument to define destmap {srcrev: destrev}"""
Pierre-Yves David
rebase: explicitly tests for None...
r31431 if revf is None:
revf = []
Gregory Szorc
rebase: don't use mutable default argument value
r31395
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 # destspace is here to work around issues with `hg pull --rebase` see
# issue5214 for details
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136
Kyle Lippincott
rebase: check for unfinished ops even when inmemory (issue6214)...
r43988 cmdutil.checkunfinished(repo)
Martin von Zweigbergk
rebase: pass "inmemory" directly to _definedestmap()...
r37043 if not inmemory:
Phil Cohen
rebase: do not bail on uncomitted changes if rebasing in-memory...
r35292 cmdutil.bailifchanged(repo)
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if ui.configbool(b'commands', b'rebase.requiredest') and not destf:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'you must specify a destination'),
hint=_(b'use: hg rebase -d REV'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Ryan McElroy
rebase: allow destination-free continue and abort (issue5513)
r31731
Jun Wu
rebase: initial support for multiple destinations...
r34007 dest = None
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136
if revf:
rebaseset = scmutil.revrange(repo, revf)
if not rebaseset:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'empty "rev" revision set - nothing to rebase\n'))
Jun Wu
rebase: change internal format to support destination map...
r34006 return None
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136 elif srcf:
src = scmutil.revrange(repo, [srcf])
if not src:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'empty "source" revision set - nothing to rebase\n'))
Jun Wu
rebase: change internal format to support destination map...
r34006 return None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rebaseset = repo.revs(b'(%ld)::', src)
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136 assert rebaseset
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 base = scmutil.revrange(repo, [basef or b'.'])
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136 if not base:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'empty "base" revision set - ' b"can't compute rebase set\n")
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jun Wu
rebase: change internal format to support destination map...
r34006 return None
Jun Wu
rebase: initial support for multiple destinations...
r34007 if destf:
# --base does not support multiple destinations
dest = scmutil.revsingle(repo, destf)
else:
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 dest = repo[_destrebase(repo, base, destspace=destspace)]
Pulkit Goyal
py3: replace str() calls with their preferred bytes equivalent...
r36493 destf = bytes(dest)
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189
Augie Fackler
formatting: blacken the codebase...
r43346 roots = [] # selected children of branching points
bpbase = {} # {branchingpoint: [origbase]}
for b in base: # group bases by branching points
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bp = repo.revs(b'ancestor(%d, %d)', b, dest.rev()).first()
Jun Wu
rebase: calculate ancestors for --base separately (issue5420)...
r30580 bpbase[bp] = bpbase.get(bp, []) + [b]
if None in bpbase:
# emulate the old behavior, showing "nothing to rebase" (a better
# behavior may be abort with "cannot find branching point" error)
bpbase.clear()
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 for bp, bs in pycompat.iteritems(bpbase): # calculate roots
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 roots += list(repo.revs(b'children(%d) & ancestors(%ld)', bp, bs))
Jun Wu
rebase: calculate ancestors for --base separately (issue5420)...
r30580
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rebaseset = repo.revs(b'%ld::', roots)
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136
if not rebaseset:
# transform to list because smartsets are not comparable to
# lists. This should be improved to honor laziness of
# smartset.
if list(base) == [dest.rev()]:
if basef:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'nothing to rebase - %s is both "base"'
b' and destination\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% dest
)
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136 else:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'nothing to rebase - working directory '
b'parent is also destination\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif not repo.revs(b'%ld - ::%d', base, dest.rev()):
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136 if basef:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'nothing to rebase - "base" %s is '
b'already an ancestor of destination '
b'%s\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 % (b'+'.join(bytes(repo[r]) for r in base), dest)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136 else:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.status(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'nothing to rebase - working '
b'directory parent is already an '
b'ancestor of destination %s\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% dest
)
else: # can it happen?
ui.status(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'nothing to rebase from %s to %s\n')
% (b'+'.join(bytes(repo[r]) for r in base), dest)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jun Wu
rebase: change internal format to support destination map...
r34006 return None
Martin von Zweigbergk
rebase: allow in-memory merge of the working copy parent...
r36993
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rebasingwcp = repo[b'.'].rev() in rebaseset
Augie Fackler
formatting: blacken the codebase...
r43346 ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"rebase",
b"rebasing working copy parent: %r\n",
Augie Fackler
formatting: blacken the codebase...
r43346 rebasingwcp,
rebase_rebasing_wcp=rebasingwcp,
)
Martin von Zweigbergk
rebase: pass "inmemory" directly to _definedestmap()...
r37043 if inmemory and rebasingwcp:
Phil Cohen
rebase: disable `inmemory` if the rebaseset contains the working copy...
r35333 # Check these since we did not before.
cmdutil.checkunfinished(repo)
cmdutil.bailifchanged(repo)
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189
if not destf:
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 dest = repo[_destrebase(repo, rebaseset, destspace=destspace)]
Pulkit Goyal
py3: replace str() calls with their preferred bytes equivalent...
r36493 destf = bytes(dest)
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 allsrc = revsetlang.formatspec(b'%ld', rebaseset)
alias = {b'ALLSRC': allsrc}
Jun Wu
rebase: initial support for multiple destinations...
r34007
if dest is None:
try:
# fast path: try to resolve dest without SRC alias
dest = scmutil.revsingle(repo, destf, localalias=alias)
except error.RepoLookupError:
# multi-dest path: resolve dest for each SRC separately
destmap = {}
for r in rebaseset:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 alias[b'SRC'] = revsetlang.formatspec(b'%d', r)
Jun Wu
rebase: initial support for multiple destinations...
r34007 # use repo.anyrevs instead of scmutil.revsingle because we
# don't want to abort if destset is empty.
destset = repo.anyrevs([destf], user=True, localalias=alias)
size = len(destset)
if size == 1:
destmap[r] = destset.first()
elif size == 0:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.note(_(b'skipping %s - empty destination\n') % repo[r])
Jun Wu
rebase: initial support for multiple destinations...
r34007 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'rebase destination for %s is not unique') % repo[r]
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jun Wu
rebase: initial support for multiple destinations...
r34007
if dest is not None:
# single-dest case: assign dest to each rev in rebaseset
destrev = dest.rev()
Augie Fackler
formatting: blacken the codebase...
r43346 destmap = {r: destrev for r in rebaseset} # {srcrev: destrev}
Jun Wu
rebase: initial support for multiple destinations...
r34007
if not destmap:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'nothing to rebase - empty destination\n'))
Jun Wu
rebase: initial support for multiple destinations...
r34007 return None
Jun Wu
rebase: change internal format to support destination map...
r34006
return destmap
Pierre-Yves David
rebase: extract rebaseset and destination computation in a function...
r28136
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
rebase: rename "target" to "dest" in variable names...
r32248 def externalparent(repo, state, destancestors):
Mads Kiilerich
rebase: refactor and rename checkexternal - it is a getter more than a setter
r19955 """Return the revision that should be used as the second parent
Martin von Zweigbergk
rebase: rename "target" to "dest" in variable names...
r32248 when the revisions in state is collapsed on top of destancestors.
Mads Kiilerich
rebase: refactor and rename checkexternal - it is a getter more than a setter
r19955 Abort if there is more than one parent.
Stefano Tortarolo
rebase: refactoring...
r10351 """
Mads Kiilerich
rebase: refactor and rename checkexternal - it is a getter more than a setter
r19955 parents = set()
Stefano Tortarolo
rebase: refactoring...
r10351 source = min(state)
for rev in state:
if rev == source:
continue
for p in repo[rev].parents():
Augie Fackler
formatting: blacken the codebase...
r43346 if p.rev() not in state and p.rev() not in destancestors:
Mads Kiilerich
rebase: refactor and rename checkexternal - it is a getter more than a setter
r19955 parents.add(p.rev())
if not parents:
return nullrev
if len(parents) == 1:
return parents.pop()
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'unable to collapse on top of %d, there is more '
b'than one external parent: %s'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 % (max(destancestors), b', '.join(b"%d" % p for p in sorted(parents)))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Stefano Tortarolo
rebase: refactoring...
r10351
Martin von Zweigbergk
rebase: rename conclude[memory]node() to commit[memory]node()...
r37061 def commitmemorynode(repo, p1, p2, wctx, editor, extra, user, date, commitmsg):
Martin von Zweigbergk
rebase: pass in "user" instead of "ctx" to conclude[memory]node()...
r37060 '''Commit the memory changes with parents p1 and p2.
Phil Cohen
rebase: add concludememorynode(), and call it when rebasing in-memory...
r35320 Return node of committed revision.'''
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 # Replicates the empty check in ``repo.commit``.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if wctx.isempty() and not repo.ui.configbool(b'ui', b'allowemptycommit'):
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 return None
Phil Cohen
rebase: add concludememorynode(), and call it when rebasing in-memory...
r35320
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 # By convention, ``extra['branch']`` (set by extrafn) clobbers
# ``branch`` (used when passing ``--keepbranches``).
branch = repo[p1].branch()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'branch' in extra:
branch = extra[b'branch']
Phil Cohen
rebase: add concludememorynode(), and call it when rebasing in-memory...
r35320
Augie Fackler
formatting: blacken the codebase...
r43346 memctx = wctx.tomemctx(
commitmsg,
parents=(p1, p2),
date=date,
extra=extra,
user=user,
branch=branch,
editor=editor,
)
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 commitres = repo.commitctx(memctx)
Augie Fackler
formatting: blacken the codebase...
r43346 wctx.clean() # Might be reused
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 return commitres
Phil Cohen
rebase: add concludememorynode(), and call it when rebasing in-memory...
r35320
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
rebase: rename conclude[memory]node() to commit[memory]node()...
r37061 def commitnode(repo, p1, p2, editor, extra, user, date, commitmsg):
Martin von Zweigbergk
rebase: pass in "user" instead of "ctx" to conclude[memory]node()...
r37060 '''Commit the wd changes with parents p1 and p2.
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 Return node of committed revision.'''
Durham Goode
rebase: use one dirstateguard for when using rebase.singletransaction...
r33621 dsguard = util.nullcontextmanager()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not repo.ui.configbool(b'rebase', b'singletransaction'):
dsguard = dirstateguard.dirstateguard(repo, b'rebase')
Durham Goode
rebase: use one dirstateguard for when using rebase.singletransaction...
r33621 with dsguard:
rebase: backed out changeset 2519994d25ca...
r33135 repo.setparents(repo[p1].node(), repo[p2].node())
Pierre-Yves David
rebase: do not retract phase boundary by hand...
r22038
Martin von Zweigbergk
rebase: move config override out of conclude[memory]node()...
r37058 # Commit might fail if unresolved files exist
Augie Fackler
formatting: blacken the codebase...
r43346 newnode = repo.commit(
text=commitmsg, user=user, date=date, extra=extra, editor=editor
)
Pierre-Yves David
rebase: do not retract phase boundary by hand...
r22038
rebase: backed out changeset 2519994d25ca...
r33135 repo.dirstate.setbranch(repo[newnode].branch())
return newnode
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
rebase: remove unused argument "state" from rebasenode()...
r36790 def rebasenode(repo, rev, p1, base, collapse, dest, wctx):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Rebase a single revision rev on top of p1 using base as merge ancestor"""
Stefano Tortarolo
Add rebase extension
r6906 # Merge phase
Martin von Zweigbergk
rebase: rename "target" to "dest" in variable names...
r32248 # Update to destination and merge it with local
Phil Cohen
rebase: do not update if IMM; instead, set the overlaywctx's parents...
r35318 if wctx.isinmemory():
wctx.setbase(repo[p1])
Stefano Tortarolo
Add rebase extension
r6906 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if repo[b'.'].rev() != p1:
repo.ui.debug(b" update to %d:%s\n" % (p1, repo[p1]))
Martin von Zweigbergk
update: clarify update() call sites by specifying argument names...
r40402 mergemod.update(repo, p1, branchmerge=False, force=True)
Phil Cohen
rebase: do not update if IMM; instead, set the overlaywctx's parents...
r35318 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" already in destination\n")
Phil Cohen
rebase: fix for hgsubversion...
r35411 # This is, alas, necessary to invalidate workingctx's manifest cache,
# as well as other data we litter on it in other places.
wctx = repo[None]
Phil Cohen
rebase: do not update if IMM; instead, set the overlaywctx's parents...
r35318 repo.dirstate.write(repo.currenttransaction())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" merge against %d:%s\n" % (rev, repo[rev]))
Pierre-Yves David
rebase: fix selection of base used when rebasing merge (issue4041)...
r19969 if base is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" detach base %d:%s\n" % (base, repo[base]))
Patrick Mezard
rebase: allow collapsing branches in place (issue3111)...
r16696 # When collapsing in-place, the parent is the common ancestor, we
# have to allow merging with it.
Augie Fackler
formatting: blacken the codebase...
r43346 stats = mergemod.update(
repo,
rev,
branchmerge=True,
force=True,
ancestor=base,
mergeancestor=collapse,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 labels=[b'dest', b'source'],
Augie Fackler
formatting: blacken the codebase...
r43346 wc=wctx,
)
Matt Mackall
rebase: move duplicatecopies next to merge...
r22905 if collapse:
Phil Cohen
context: add workingfilectx.markcopied...
r34788 copies.duplicatecopies(repo, wctx, rev, dest)
Matt Mackall
rebase: move duplicatecopies next to merge...
r22905 else:
# If we're not using --collapse, we need to
# duplicate copies between the revision we're
# rebasing and its first parent, but *not*
# duplicate any copies that have already been
# performed in the destination.
p1rev = repo[rev].p1().rev()
Phil Cohen
context: add workingfilectx.markcopied...
r34788 copies.duplicatecopies(repo, wctx, rev, p1rev, skiprev=dest)
Matt Mackall
rebase: move duplicatecopies next to merge...
r22905 return stats
Dirkjan Ochtman
strip trailing whitespace, replace tabs by spaces
r6923
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: move working parent and bookmark for obsoleted revs (BC)...
r34010 def adjustdest(repo, rev, destmap, state, skipped):
Gregory Szorc
global: make some docstrings raw strings...
r41674 r"""adjust rebase destination given the current rebase state
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591
rev is what is being rebased. Return a list of two revs, which are the
adjusted destinations for rev's p1 and p2, respectively. If a parent is
nullrev, return dest without adjustment for it.
Jun Wu
rebase: initial support for multiple destinations...
r34007 For example, when doing rebasing B+E to F, C to G, rebase will first move B
to B1, and E's destination will be adjusted from F to B1.
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591
B1 <- written during rebasing B
|
F <- original destination of B, E
|
| E <- rev, which is being rebased
| |
| D <- prev, one parent of rev being checked
| |
| x <- skipped, ex. no successor or successor in (::dest)
| |
Jun Wu
rebase: initial support for multiple destinations...
r34007 | C <- rebased as C', different destination
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591 | |
Jun Wu
rebase: initial support for multiple destinations...
r34007 | B <- rebased as B1 C'
|/ |
A G <- destination of C, different
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591
Another example about merge changeset, rebase -r C+G+H -d K, rebase will
first move C to C1, G to G1, and when it's checking H, the adjusted
destinations will be [C1, G1].
H C1 G1
/| | /
F G |/
K | | -> K
| C D |
| |/ |
| B | ...
|/ |/
A A
Jun Wu
rebase: sort destmap topologically...
r34008
Besides, adjust dest according to existing rebase information. For example,
B C D B needs to be rebased on top of C, C needs to be rebased on top
\|/ of D. We will rebase C first.
A
C' After rebasing C, when considering B's destination, use C'
| instead of the original C.
B D
\ /
A
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591 """
Jun Wu
rebase: change internal format to support destination map...
r34006 # pick already rebased revs with same dest from state as interesting source
dest = destmap[rev]
Augie Fackler
formatting: blacken the codebase...
r43346 source = [
s
for s, d in state.items()
if d > 0 and destmap[s] == dest and s not in skipped
]
Jun Wu
rebase: optimize "source" calculation in adjustdest...
r33848
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591 result = []
for prev in repo.changelog.parentrevs(rev):
adjusted = dest
if prev != nullrev:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 candidate = repo.revs(b'max(%ld and (::%d))', source, prev).first()
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591 if candidate is not None:
adjusted = state[candidate]
Jun Wu
rebase: sort destmap topologically...
r34008 if adjusted == dest and dest in state:
adjusted = state[dest]
if adjusted == revtodo:
# sortsource should produce an order that makes this impossible
raise error.ProgrammingError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'rev %d should be rebased already at this time' % dest
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jun Wu
rebase: move bookmark to destination for commits becoming empty (issue5627)...
r33591 result.append(adjusted)
return result
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: remove rebaseset from _checkobsrebase...
r33845 def _checkobsrebase(repo, ui, rebaseobsrevs, rebaseobsskipped):
Laurent Charignon
rebase: refactor of error handling code path for rebaseskipobsolete...
r28685 """
Abort if rebase will create divergence or rebase is noop because of markers
`rebaseobsrevs`: set of obsolete revision in source
`rebaseobsskipped`: set of revisions from source skipped because they have
Denis Laxalde
rebase: do not consider extincts for divergence detection (issue5782)...
r36013 successors in destination or no non-obsolete successor.
Laurent Charignon
rebase: refactor of error handling code path for rebaseskipobsolete...
r28685 """
# Obsolete node with successors not in dest leads to divergence
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 divergenceok = ui.configbool(b'experimental', b'evolution.allowdivergence')
Laurent Charignon
rebase: refactor of error handling code path for rebaseskipobsolete...
r28685 divergencebasecandidates = rebaseobsrevs - rebaseobsskipped
if divergencebasecandidates and not divergenceok:
Augie Fackler
formatting: blacken the codebase...
r43346 divhashes = (bytes(repo[r]) for r in divergencebasecandidates)
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 msg = _(b"this rebase will cause divergences from: %s")
Augie Fackler
formatting: blacken the codebase...
r43346 h = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"to force the rebase please set "
b"experimental.evolution.allowdivergence=True"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(msg % (b",".join(divhashes),), hint=h)
Laurent Charignon
rebase: refactor of error handling code path for rebaseskipobsolete...
r28685
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: remove unnecessary '.unfiltered()' calls...
r34097 def successorrevs(unfi, rev):
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 """yield revision numbers for successors of rev"""
Jun Wu
rebase: remove unnecessary '.unfiltered()' calls...
r34097 assert unfi.filtername is None
index: use `index.get_rev` in `rebase.successorrevs`...
r43966 get_rev = unfi.changelog.index.get_rev
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]):
index: use `index.get_rev` in `rebase.successorrevs`...
r43966 r = get_rev(s)
if r is not None:
yield r
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: move working parent and bookmark for obsoleted revs (BC)...
r34010 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 """Return new parents and optionally a merge base for rev being rebased
The destination specified by "dest" cannot always be used directly because
previously rebase result could affect destination. For example,
Stefano Tortarolo
Add rebase extension
r6906
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 D E rebase -r C+D+E -d B
|/ C will be rebased to C'
B C D's new destination will be C' instead of B
|/ E's new destination will be C' instead of B
A
Stefano Tortarolo
Add rebase extension
r6906
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 The new parents of a merge is slightly more complicated. See the comment
block below.
"""
Jun Wu
rebase: do not crash rebasing merge with a parent having hidden successor...
r34094 # use unfiltered changelog since successorrevs may return filtered nodes
Jun Wu
rebase: remove unnecessary '.unfiltered()' calls...
r34097 assert repo.filtername is None
cl = repo.changelog
Martin von Zweigbergk
revlog: introduce a isancestorrev() and use it in rebase...
r38688 isancestor = cl.isancestorrev
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783
Jun Wu
rebase: change internal format to support destination map...
r34006 dest = destmap[rev]
Augie Fackler
formatting: blacken the codebase...
r43346 oldps = repo.changelog.parentrevs(rev) # old parents
newps = [nullrev, nullrev] # new parents
Jun Wu
rebase: move working parent and bookmark for obsoleted revs (BC)...
r34010 dests = adjustdest(repo, rev, destmap, state, skipped)
Augie Fackler
formatting: blacken the codebase...
r43346 bases = list(oldps) # merge base candidates, initially just old parents
Stefano Tortarolo
Add rebase extension
r6906
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 if all(r == nullrev for r in oldps[1:]):
# For non-merge changeset, just move p to adjusted dest as requested.
newps[0] = dests[0]
else:
# For merge changeset, if we move p to dests[i] unconditionally, both
# parents may change and the end result looks like "the merge loses a
# parent", which is a surprise. This is a limit because "--dest" only
# accepts one dest per src.
#
# Therefore, only move p with reasonable conditions (in this order):
# 1. use dest, if dest is a descendent of (p or one of p's successors)
# 2. use p's rebased result, if p is rebased (state[p] > 0)
#
# Comparing with adjustdest, the logic here does some additional work:
# 1. decide which parents will not be moved towards dest
# 2. if the above decision is "no", should a parent still be moved
# because it was rebased?
#
# For example:
#
# C # "rebase -r C -d D" is an error since none of the parents
# /| # can be moved. "rebase -r B+C -d D" will move C's parent
# A B D # B (using rule "2."), since B will be rebased.
#
# The loop tries to be not rely on the fact that a Mercurial node has
# at most 2 parents.
for i, p in enumerate(oldps):
Augie Fackler
formatting: blacken the codebase...
r43346 np = p # new parent
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)):
np = dests[i]
elif p in state and state[p] > 0:
np = state[p]
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 # "bases" only record "special" merge bases that cannot be
# calculated from changelog DAG (i.e. isancestor(p, np) is False).
# For example:
#
# B' # rebase -s B -d D, when B was rebased to B'. dest for C
# | C # is B', but merge base for C is B, instead of
# D | # changelog.ancestor(C, B') == A. If changelog DAG and
# | B # "state" edges are merged (so there will be an edge from
# |/ # B to B'), the merge base is still ancestor(C, B') in
# A # the merged graph.
#
# Also see https://bz.mercurial-scm.org/show_bug.cgi?id=1950#c8
# which uses "virtual null merge" to explain this situation.
if isancestor(p, np):
bases[i] = nullrev
# If one parent becomes an ancestor of the other, drop the ancestor
for j, x in enumerate(newps[:i]):
if x == nullrev:
continue
Augie Fackler
formatting: blacken the codebase...
r43346 if isancestor(np, x): # CASE-1
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 np = nullrev
Augie Fackler
formatting: blacken the codebase...
r43346 elif isancestor(x, np): # CASE-2
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 newps[j] = np
np = nullrev
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863 # New parents forming an ancestor relationship does not
# mean the old parents have a similar relationship. Do not
# set bases[x] to nullrev.
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 bases[j], bases[i] = bases[i], bases[j]
newps[i] = np
# "rebasenode" updates to new p1, and the old p1 will be used as merge
# base. If only p2 changes, merging using unchanged p1 as merge base is
# suboptimal. Therefore swap parents to make the merge sane.
if newps[1] != nullrev and oldps[0] == newps[0]:
assert len(newps) == 2 and len(oldps) == 2
newps.reverse()
bases.reverse()
# No parent change might be an error because we fail to make rev a
# descendent of requested dest. This can happen, for example:
#
# C # rebase -r C -d D
# /| # None of A and B will be changed to D and rebase fails.
# A B D
if set(newps) == set(oldps) and dest not in newps:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cannot rebase %d:%s without '
b'moving at least one of its parents'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% (rev, repo[rev])
)
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783
Jun Wu
rebase: sort destmap topologically...
r34008 # Source should not be ancestor of dest. The check here guarantees it's
# impossible. With multi-dest, the initial check does not cover complex
# cases since we don't have abstractions to dry-run rebase cheaply.
if any(p != nullrev and isancestor(rev, p) for p in newps):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'source is ancestor of destination'))
Jun Wu
rebase: sort destmap topologically...
r34008
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783 # "rebasenode" updates to new p1, use the corresponding merge base.
if bases[0] != nullrev:
base = bases[0]
else:
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 base = None
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783
# Check if the merge will contain unwanted changes. That may happen if
# there are multiple special (non-changelog ancestor) merge bases, which
# cannot be handled well by the 3-way merge algorithm. For example:
#
# F
# /|
# D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen
# | | # as merge base, the difference between D and F will include
# B C # C, so the rebased F will contain C surprisingly. If "E" was
# |/ # chosen, the rebased F will contain B.
# A Z
#
# But our merge base candidates (D and E in above case) could still be
# better than the default (ancestor(F, Z) == null). Therefore still
# pick one (so choose p1 above).
Kyle Lippincott
rebase: make rebase not crash if p1 == p2 != nullid...
r44326 if sum(1 for b in set(bases) if b != nullrev) > 1:
Augie Fackler
formatting: blacken the codebase...
r43346 unwanted = [None, None] # unwanted[i]: unwanted revs if choose bases[i]
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863 for i, base in enumerate(bases):
if base == nullrev:
continue
# Revisions in the side (not chosen as merge base) branch that
# might contain "surprising" contents
Augie Fackler
formatting: blacken the codebase...
r43346 siderevs = list(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.revs(b'((%ld-%d) %% (%d+%d))', bases, base, base, dest)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863 # If those revisions are covered by rebaseset, the result is good.
# A merge in rebaseset would be considered to cover its ancestors.
if siderevs:
Augie Fackler
formatting: blacken the codebase...
r43346 rebaseset = [
r for r, d in state.items() if d > 0 and r not in obsskipped
]
merges = [
r for r in rebaseset if cl.parentrevs(r)[1] != nullrev
]
unwanted[i] = list(
repo.revs(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'%ld - (::%ld) - %ld', siderevs, merges, rebaseset
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863 # Choose a merge base that has a minimal number of unwanted revs.
Augie Fackler
formatting: blacken the codebase...
r43346 l, i = min(
(len(revs), i)
for i, revs in enumerate(unwanted)
if revs is not None
)
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863 base = bases[i]
# newps[0] should match merge base if possible. Currently, if newps[i]
# is nullrev, the only case is newps[i] and newps[j] (j < i), one is
# the other's ancestor. In that case, it's fine to not swap newps here.
# (see CASE-1 and CASE-2 above)
if i != 0 and newps[i] != nullrev:
newps[0], newps[i] = newps[i], newps[0]
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863 # The merge will include unwanted revisions. Abort now. Revisit this if
# we have a more advanced merge algorithm that handles multiple bases.
if l > 0:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 unwanteddesc = _(b' or ').join(
Augie Fackler
formatting: blacken the codebase...
r43346 (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b', '.join(b'%d:%s' % (r, repo[r]) for r in revs)
Augie Fackler
formatting: blacken the codebase...
r43346 for revs in unwanted
if revs is not None
)
)
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'rebasing %d:%s will include unwanted changes from %s')
Augie Fackler
formatting: blacken the codebase...
r43346 % (rev, repo[rev], unwanteddesc)
)
Jun Wu
rebase: choose merge base without unwanted revisions...
r33863
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b" future parents are %d and %d\n" % tuple(newps))
Jun Wu
rebase: rewrite core algorithm (issue5578) (issue5630)...
r33783
return newps[0], newps[1], base
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: blacken the codebase...
r43346
Stefano Tortarolo
rebase: keep original mq patch format (Issue1574)...
r7955 def isagitpatch(repo, patchname):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Return true if the given patch is in git format"""
Stefano Tortarolo
rebase: keep original mq patch format (Issue1574)...
r7955 mqpatch = os.path.join(repo.mq.path, patchname)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for line in patch.linereader(open(mqpatch, b'rb')):
if line.startswith(b'diff --git'):
Stefano Tortarolo
rebase: keep original mq patch format (Issue1574)...
r7955 return True
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Stefano Tortarolo
Add rebase extension
r6906 def updatemq(repo, state, skipped, **opts):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Update rebased mq patches - finalize and then import them"""
Stefano Tortarolo
Add rebase extension
r6906 mqrebase = {}
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 mq = repo.mq
Adrian Buehlmann
mq: rename full_series to fullseries
r14572 original_series = mq.fullseries[:]
Patrick Mezard
rebase: preserve mq series order, guarded patches (issue2849)...
r16531 skippedpatches = set()
Stefano Tortarolo
rebase: restore mq guards after rebasing (issue2107)...
r14497
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 for p in mq.applied:
rev = repo[p.node].rev()
if rev in state:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'revision %d is an mq patch (%s), finalize it.\n'
Augie Fackler
formatting: blacken the codebase...
r43346 % (rev, p.name)
)
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
Patrick Mezard
rebase: preserve mq series order, guarded patches (issue2849)...
r16531 else:
# Applied but not rebased, not sure this should happen
skippedpatches.add(p.name)
Stefano Tortarolo
Add rebase extension
r6906
if mqrebase:
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 mq.finish(repo, mqrebase.keys())
Stefano Tortarolo
Add rebase extension
r6906
# We must start import from the newest revision
Matt Mackall
replace various uses of list.reverse()
r8210 for rev in sorted(mqrebase, reverse=True):
Stefano Tortarolo
Add rebase extension
r6906 if rev not in skipped:
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 name, isgit = mqrebase[rev]
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.note(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'updating mq patch %s to %d:%s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % (name, state[rev], repo[state[rev]])
)
mq.qimport(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo,
(),
patchname=name,
git=isgit,
rev=[b"%d" % state[rev]],
Augie Fackler
formatting: blacken the codebase...
r43346 )
Patrick Mezard
rebase: preserve mq series order, guarded patches (issue2849)...
r16531 else:
# Rebased and skipped
skippedpatches.add(mqrebase[rev][0])
Stefano Tortarolo
rebase: restore mq guards after rebasing (issue2107)...
r14497
Patrick Mezard
rebase: preserve mq series order, guarded patches (issue2849)...
r16531 # Patches were either applied and rebased and imported in
# order, applied and removed or unapplied. Discard the removed
# ones while preserving the original series order and guards.
Augie Fackler
formatting: blacken the codebase...
r43346 newseries = [
s
for s in original_series
if mq.guard_re.split(s, 1)[0] not in skippedpatches
]
Patrick Mezard
rebase: preserve mq series order, guarded patches (issue2849)...
r16531 mq.fullseries[:] = newseries
mq.seriesdirty = True
Adrian Buehlmann
mq: rename save_dirty to savedirty
r14580 mq.savedirty()
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: blacken the codebase...
r43346
liscju
rebase: adds storing collapse message (issue4792)...
r28185 def storecollapsemsg(repo, collapsemsg):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Store the collapse message to allow recovery"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 collapsemsg = collapsemsg or b''
f = repo.vfs(b"last-message.txt", b"w")
f.write(b"%s\n" % collapsemsg)
liscju
rebase: adds storing collapse message (issue4792)...
r28185 f.close()
Augie Fackler
formatting: blacken the codebase...
r43346
liscju
rebase: adds storing collapse message (issue4792)...
r28185 def clearcollapsemsg(repo):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Remove collapse message file"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.vfs.unlinkpath(b"last-message.txt", ignoremissing=True)
liscju
rebase: adds storing collapse message (issue4792)...
r28185
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
rebase: allow aborting if last-message.txt is missing...
r31225 def restorecollapsemsg(repo, isabort):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Restore previously stored collapse message"""
liscju
rebase: adds storing collapse message (issue4792)...
r28185 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = repo.vfs(b"last-message.txt")
liscju
rebase: adds storing collapse message (issue4792)...
r28185 collapsemsg = f.readline().strip()
f.close()
except IOError as err:
if err.errno != errno.ENOENT:
raise
Durham Goode
rebase: allow aborting if last-message.txt is missing...
r31225 if isabort:
# Oh well, just abort like normal
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 collapsemsg = b''
Durham Goode
rebase: allow aborting if last-message.txt is missing...
r31225 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'missing .hg/last-message.txt for rebase'))
liscju
rebase: adds storing collapse message (issue4792)...
r28185 return collapsemsg
Augie Fackler
formatting: blacken the codebase...
r43346
Stefano Tortarolo
Add rebase extension
r6906 def clearstatus(repo):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Remove the status files"""
Jun Wu
rebase: clean up rebasestate from active transaction...
r33056 # Make sure the active transaction won't write the state file
tr = repo.currenttransaction()
if tr:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.removefilegenerator(b'rebasestate')
repo.vfs.unlinkpath(b"rebasestate", ignoremissing=True)
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: blacken the codebase...
r43346
Jordi Gutiérrez Hermoso
rebase: clear merge when aborting before any rebasing (issue4661)...
r25070 def needupdate(repo, state):
'''check whether we should `update --clean` away from a merge, or if
somehow the working dir got forcibly updated, e.g. by older hg'''
Augie Fackler
commands: inline definition of localrepo.parents() and drop the method (API)...
r27167 parents = [p.rev() for p in repo[None].parents()]
Jordi Gutiérrez Hermoso
rebase: clear merge when aborting before any rebasing (issue4661)...
r25070
# Are we in a merge state at all?
if len(parents) < 2:
return False
# We should be standing on the first as-of-yet unrebased commit.
Augie Fackler
formatting: blacken the codebase...
r43346 firstunrebased = min(
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 [old for old, new in pycompat.iteritems(state) if new == nullrev]
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jordi Gutiérrez Hermoso
rebase: clear merge when aborting before any rebasing (issue4661)...
r25070 if firstunrebased in parents:
Matt Mackall
rebase: don't clobber wd on --abort when we've updated away (issue4009)
r19516 return True
return False
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: sort destmap topologically...
r34008 def sortsource(destmap):
"""yield source revisions in an order that we only rebase things once
If source and destination overlaps, we should filter out revisions
depending on other revisions which hasn't been rebased yet.
Yield a sorted list of revisions each time.
For example, when rebasing A to B, B to C. This function yields [B], then
[A], indicating B needs to be rebased first.
Raise if there is a cycle so the rebase is impossible.
"""
srcset = set(destmap)
while srcset:
srclist = sorted(srcset)
result = []
for r in srclist:
if destmap[r] not in srcset:
result.append(r)
if not result:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'source and destination form a cycle'))
Jun Wu
rebase: sort destmap topologically...
r34008 srcset -= set(result)
yield result
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: move working parent and bookmark for obsoleted revs (BC)...
r34010 def buildstate(repo, destmap, collapse):
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267 '''Define which revisions are going to be rebased and where
Stefano Tortarolo
Add rebase extension
r6906
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267 repo: repo
Jun Wu
rebase: change internal format to support destination map...
r34006 destmap: {srcrev: destrev}
Pierre-Yves David
rebase: do not add second parent to rebased changeset (drop detach option) (BC)...
r17005 '''
Jun Wu
rebase: change internal format to support destination map...
r34006 rebaseset = destmap.keys()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 originalwd = repo[b'.'].rev()
Stefano Tortarolo
Add rebase extension
r6906
Greg Ward
rebase: always check if rebasing onto an applied mq patch....
r10672 # This check isn't strictly necessary, since mq detects commits over an
# applied patch. But it prevents messing up the working directory when
# a partially completed rebase is blocked by mq.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'qtip' in repo.tags():
Jun Wu
rebase: change internal format to support destination map...
r34006 mqapplied = set(repo[s.node].rev() for s in repo.mq.applied)
if set(destmap.values()) & mqapplied:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'cannot rebase onto an applied mq patch'))
Greg Ward
rebase: always check if rebasing onto an applied mq patch....
r10672
Jun Wu
rebase: sort destmap topologically...
r34008 # Get "cycle" error early by exhausting the generator.
Augie Fackler
formatting: blacken the codebase...
r43346 sortedsrc = list(sortsource(destmap)) # a list of sorted revs
Jun Wu
rebase: sort destmap topologically...
r34008 if not sortedsrc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'no matching revisions'))
Jun Wu
rebase: sort destmap topologically...
r34008
# Only check the first batch of revisions to rebase not depending on other
# rebaseset. This means "source is ancestor of destination" for the second
# (and following) batches of revisions are not checked here. We rely on
# "defineparents" to do that check.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 roots = list(repo.set(b'roots(%ld)', sortedsrc[0]))
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267 if not roots:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'no matching revisions'))
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
rebase: sort roots by revision...
r36285 def revof(r):
return r.rev()
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
rebase: sort roots by revision...
r36285 roots = sorted(roots, key=revof)
Martin von Zweigbergk
rebase: don't update state dict same way for each root...
r32175 state = dict.fromkeys(rebaseset, revtodo)
Augie Fackler
formatting: blacken the codebase...
r43346 emptyrebase = len(sortedsrc) == 1
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 for root in roots:
Jun Wu
rebase: change internal format to support destination map...
r34006 dest = repo[destmap[root.rev()]]
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 commonbase = root.ancestor(dest)
if commonbase == root:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'source is ancestor of destination'))
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 if commonbase == dest:
Mads Kiilerich
rebase: allow rebasing children of wd to wd if a new branch has been set (BC)...
r31380 wctx = repo[None]
if dest == wctx.p1():
# when rebasing to '.', it will use the current wd branch name
samebranch = root.branch() == wctx.branch()
else:
samebranch = root.branch() == dest.branch()
Martin von Zweigbergk
rebase: rewrite "x in y.children()" as "y in x.parents()"...
r32900 if not collapse and samebranch and dest in root.parents():
Martin von Zweigbergk
rebase: allow rebase even if some revisions need no rebase (BC) (issue5422)...
r32272 # mark the revision as done by setting its new revision
# equal to its old (current) revisions
state[root.rev()] = root.rev()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b'source is a child of destination\n')
Martin von Zweigbergk
rebase: allow rebase even if some revisions need no rebase (BC) (issue5422)...
r32272 continue
Stefano Tortarolo
Add rebase extension
r6906
Martin von Zweigbergk
rebase: allow rebase even if some revisions need no rebase (BC) (issue5422)...
r32272 emptyrebase = False
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b'rebase onto %s starting from %s\n' % (dest, root))
Martin von Zweigbergk
rebase: allow rebase even if some revisions need no rebase (BC) (issue5422)...
r32272 if emptyrebase:
return None
for rev in sorted(state):
parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
# if all parents of this revision are done, then so is this revision
if parents and all((state.get(p) == p for p in parents)):
state[rev] = rev
Jun Wu
rebase: change internal format to support destination map...
r34006 return originalwd, destmap, state
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: blacken the codebase...
r43346
def clearrebased(
ui,
repo,
destmap,
state,
skipped,
collapsedas=None,
keepf=False,
fm=None,
backup=True,
):
Pierre-Yves David
rebase: properly handle --collapse when creating obsolescence marker...
r17613 """dispose of rebased revision at the end of the rebase
If `collapsedas` is not None, the rebase was a collapse whose result if the
Jun Wu
rebase: move bookmarks with --keep (issue5682)...
r34364 `collapsedas` node.
If `keepf` is not True, the rebase has --keep set and no nodes should be
removed (but bookmarks still need to be moved).
Sushil khanchi
rebase: support "history-editing-backup" config option...
r38835
If `backup` is False, no backup will be stored when stripping rebased
revisions.
Jun Wu
rebase: move bookmarks with --keep (issue5682)...
r34364 """
Jun Wu
rebase: use scmutil.cleanupnodes (issue5606) (BC)...
r33332 tonode = repo.changelog.node
Jun Wu
rebase: move bookmarks with --keep (issue5682)...
r34364 replacements = {}
moves = {}
Boris Feld
rebase: don't try to prune obsolete changeset already in the destination...
r39951 stripcleanup = not obsolete.isenabled(repo, obsolete.createmarkersopt)
Boris Feld
rebase: explicitly track collapses as fold...
r39955
collapsednodes = []
Jun Wu
rebase: remove "if True"...
r33333 for rev, newrev in sorted(state.items()):
if newrev >= 0 and newrev != rev:
Jun Wu
rebase: move bookmarks with --keep (issue5682)...
r34364 oldnode = tonode(rev)
newnode = collapsedas or tonode(newrev)
moves[oldnode] = newnode
Paul Gossman
rebase: track new nodes when --keep is set...
r43245 succs = None
if rev in skipped:
if stripcleanup or not repo[rev].obsolete():
succs = ()
elif collapsedas:
collapsednodes.append(oldnode)
else:
succs = (newnode,)
if succs is not None:
replacements[(oldnode,)] = succs
Boris Feld
rebase: explicitly track collapses as fold...
r39955 if collapsednodes:
replacements[tuple(collapsednodes)] = (collapsedas,)
Pulkit Goyal
rebase: add support to output nodechanges...
r34884 if fm:
Pulkit Goyal
rebase: use fm.formatlist() and fm.formatdict() to support user template...
r35123 hf = fm.hexfunc
fl = fm.formatlist
fd = fm.formatdict
Boris Feld
rebase: expand a long "one-liner"...
r39953 changes = {}
Gregory Szorc
py3: define and use pycompat.iteritems() for hgext/...
r43375 for oldns, newn in pycompat.iteritems(replacements):
Boris Feld
rebase: use tuple as `replacement` keys...
r39954 for oldn in oldns:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 changes[hf(oldn)] = fl([hf(n) for n in newn], name=b'node')
nodechanges = fd(changes, key=b"oldnode", value=b"newnodes")
Pulkit Goyal
rebase: add support to output nodechanges...
r34884 fm.data(nodechanges=nodechanges)
Paul Gossman
rebase: track new nodes when --keep is set...
r43245 if keepf:
replacements = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 scmutil.cleanupnodes(repo, replacements, b'rebase', moves, backup=backup)
Pierre-Yves David
rebase: extract final changesets cleanup logic in a dedicated function...
r17611
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
extensions: use new wrapper functions
r7216 def pullrebase(orig, ui, repo, *args, **opts):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """Call rebase after pull if the latter has been invoked with --rebase"""
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if opts.get('rebase'):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if ui.configbool(b'commands', b'rebase.requiredest'):
msg = _(b'rebase destination required by configuration')
hint = _(b'use hg pull followed by hg rebase -d DEST')
Ryan McElroy
rebase: abort hg pull --rebase if rebase.requiredest is set (issue5514)...
r31733 raise error.Abort(msg, hint=hint)
Martin von Zweigbergk
rebase: use context manager for locking in pullrebase()
r32918 with repo.wlock(), repo.lock():
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if opts.get('update'):
del opts['update']
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'--update and --rebase are not compatible, ignoring '
b'the update flag\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Stefano Tortarolo
Add rebase extension
r6906
Taapas Agrawal
statecheck: added support for STATES...
r42732 cmdutil.checkunfinished(repo, skipmerge=True)
Augie Fackler
formatting: blacken the codebase...
r43346 cmdutil.bailifchanged(
repo,
hint=_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cannot pull with rebase: '
b'please commit or shelve your changes first'
Augie Fackler
formatting: blacken the codebase...
r43346 ),
)
Valters Vingolds
rebase: fail-fast the pull if working dir is not clean (BC)...
r30725
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 revsprepull = len(repo)
origpostincoming = commands.postincoming
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 def _dummy(*args, **kwargs):
pass
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 commands.postincoming = _dummy
try:
liscju
rebase: add returning value from pullrebase function...
r26960 ret = orig(ui, repo, *args, **opts)
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 finally:
commands.postincoming = origpostincoming
revspostpull = len(repo)
if revspostpull > revsprepull:
# --rev option from pull conflict with rebase own --rev
# dropping it
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if 'rev' in opts:
del opts['rev']
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 # positional argument from pull conflicts with rebase's own
# --source.
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if 'source' in opts:
del opts['source']
Pierre-Yves David
rebase: restrict rebase destination to the pulled set (issue5214)...
r29044 # revsprepull is the len of the repo, not revnum of tip.
destspace = list(repo.changelog.revs(start=revsprepull))
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 opts['_destspace'] = destspace
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 try:
rebase(ui, repo, **opts)
except error.NoMergeDestAbort:
# we can maybe update instead
Pierre-Yves David
rebase: perform update through the 'update' command...
r28118 rev, _a, _b = destutil.destupdate(repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if rev == repo[b'.'].rev():
ui.status(_(b'nothing to rebase\n'))
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.status(_(b'nothing to rebase - updating instead\n'))
Pierre-Yves David
rebase: perform update through the 'update' command...
r28118 # not passing argument to get the bare update behavior
# with warning and trumpets
commands.update(ui, repo)
Stefano Tortarolo
Add rebase extension
r6906 else:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if opts.get('tool'):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'--tool can only be used with --rebase'))
liscju
rebase: add returning value from pullrebase function...
r26960 ret = orig(ui, repo, *args, **opts)
return ret
Stefano Tortarolo
Add rebase extension
r6906
Augie Fackler
formatting: blacken the codebase...
r43346
Laurent Charignon
rebase: small refactoring to allow better extensibility from extensions...
r27790 def _filterobsoleterevs(repo, revs):
"""returns a set of the obsolete revisions in revs"""
return set(r for r in revs if repo[r].obsolete())
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
rebase: change internal format to support destination map...
r34006 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
Denis Laxalde
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
r35049 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
`obsoletenotrebased` is a mapping mapping obsolete => successor for all
obsolete nodes to be rebased given in `rebaseobsrevs`.
Laurent Charignon
rebase: don't rebase obsolete commits with no successor...
r27012
Denis Laxalde
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
r35049 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
without a successor in destination.
Denis Laxalde
rebase: do not consider extincts for divergence detection (issue5782)...
r36013
`obsoleteextinctsuccessors` is a set of obsolete revisions with only
obsolete successors.
Denis Laxalde
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
r35049 """
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 obsoletenotrebased = {}
Martin von Zweigbergk
cleanup: use set literals where possible...
r42224 obsoletewithoutsuccessorindestination = set()
obsoleteextinctsuccessors = set()
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349
Jun Wu
rebase: remove unnecessary '.unfiltered()' calls...
r34097 assert repo.filtername is None
Pierre-Yves David
rebase: use a direct reference to repo.changelog...
r26674 cl = repo.changelog
index: use `index.get_rev` in `rebase._computeobsoletenotrebased`...
r43967 get_rev = cl.index.get_rev
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extinctrevs = set(repo.revs(b'extinct()'))
Jun Wu
rebase: rewrite _computeobsoletenotrebased...
r34005 for srcrev in rebaseobsrevs:
srcnode = cl.node(srcrev)
# XXX: more advanced APIs are required to handle split correctly
Denis Laxalde
rebase: make "successors" a set in _computeobsoletenotrebased()...
r36015 successors = set(obsutil.allsuccessors(repo.obsstore, [srcnode]))
Denis Laxalde
rebase: eliminate node from successors early in _computeobsoletenotrebased()
r36012 # obsutil.allsuccessors includes node itself
successors.remove(srcnode)
index: use `index.get_rev` in `rebase._computeobsoletenotrebased`...
r43967 succrevs = {get_rev(s) for s in successors}
succrevs.discard(None)
Martin von Zweigbergk
rebase: use revnums (not nodes) for set of extinct revisions...
r38695 if succrevs.issubset(extinctrevs):
Denis Laxalde
rebase: do not consider extincts for divergence detection (issue5782)...
r36013 # all successors are extinct
obsoleteextinctsuccessors.add(srcrev)
Denis Laxalde
rebase: eliminate node from successors early in _computeobsoletenotrebased()
r36012 if not successors:
# no successor
Jun Wu
rebase: rewrite _computeobsoletenotrebased...
r34005 obsoletenotrebased[srcrev] = None
else:
Martin von Zweigbergk
rebase: avoid converting from nodes to revnums twice...
r38694 dstrev = destmap[srcrev]
for succrev in succrevs:
if cl.isancestorrev(succrev, dstrev):
obsoletenotrebased[srcrev] = succrev
Jun Wu
rebase: rewrite _computeobsoletenotrebased...
r34005 break
Denis Laxalde
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
r35049 else:
# If 'srcrev' has a successor in rebase set but none in
# destination (which would be catched above), we shall skip it
# and its descendants to avoid divergence.
Martin von Zweigbergk
rebase: skip extinct revisions even if it has no successor in rebase set...
r39364 if srcrev in extinctrevs or any(s in destmap for s in succrevs):
Denis Laxalde
rebase: exclude descendants of obsoletes w/o a successor in dest (issue5300)...
r35049 obsoletewithoutsuccessorindestination.add(srcrev)
Laurent Charignon
rebase: don't rebase obsolete commits with no successor...
r27012
Denis Laxalde
rebase: do not consider extincts for divergence detection (issue5782)...
r36013 return (
obsoletenotrebased,
obsoletewithoutsuccessorindestination,
obsoleteextinctsuccessors,
)
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349
Augie Fackler
formatting: blacken the codebase...
r43346
Taapas Agrawal
abort: added support for rebase...
r42786 def abortrebase(ui, repo):
with repo.wlock(), repo.lock():
rbsrt = rebaseruntime(repo, ui)
rbsrt._prepareabortorcontinue(isabort=True)
Augie Fackler
formatting: blacken the codebase...
r43346
Taapas Agrawal
continue: added support for rebase...
r42832 def continuerebase(ui, repo):
with repo.wlock(), repo.lock():
rbsrt = rebaseruntime(repo, ui)
ms = mergemod.mergestate.read(repo)
mergeutil.checkunresolved(ms)
retcode = rbsrt._prepareabortorcontinue(isabort=False)
if retcode is not None:
return retcode
rbsrt._performrebase(None)
rbsrt._finishrebase()
Augie Fackler
formatting: blacken the codebase...
r43346
Bryan O'Sullivan
summary: indicate if a rebase is underway
r19214 def summaryhook(ui, repo):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not repo.vfs.exists(b'rebasestate'):
Bryan O'Sullivan
summary: indicate if a rebase is underway
r19214 return
FUJIWARA Katsunori
rebase: catch RepoLookupError at restoring rebase state for summary...
r19849 try:
Kostia Balytskyi
rebase: move restorestestatus function to be a method of the RR class
r29403 rbsrt = rebaseruntime(repo, ui, {})
rbsrt.restorestatus()
state = rbsrt.state
FUJIWARA Katsunori
rebase: catch RepoLookupError at restoring rebase state for summary...
r19849 except error.RepoLookupError:
# i18n: column positioning for "hg summary"
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b'rebase: (use "hg rebase --abort" to clear broken state)\n')
FUJIWARA Katsunori
rebase: catch RepoLookupError at restoring rebase state for summary...
r19849 ui.write(msg)
return
Gregory Szorc
py3: define and use pycompat.itervalues()...
r43374 numrebased = len([i for i in pycompat.itervalues(state) if i >= 0])
Bryan O'Sullivan
summary: indicate if a rebase is underway
r19214 # i18n: column positioning for "hg summary"
Augie Fackler
formatting: blacken the codebase...
r43346 ui.write(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'rebase: %s, %s (rebase --continue)\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.label(_(b'%d rebased'), b'rebase.rebased') % numrebased,
ui.label(_(b'%d remaining'), b'rebase.remaining')
Augie Fackler
formatting: blacken the codebase...
r43346 % (len(state) - numrebased),
)
)
Bryan O'Sullivan
summary: indicate if a rebase is underway
r19214
Stefano Tortarolo
Add rebase extension
r6906 def uisetup(ui):
Augie Fackler
formatting: blacken the codebase...
r43346 # Replace pull with a decorator to provide --rebase option
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 entry = extensions.wrapcommand(commands.table, b'pull', pullrebase)
Augie Fackler
formatting: blacken the codebase...
r43346 entry[1].append(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (b'', b'rebase', None, _(b"rebase working directory to branch head"))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 entry[1].append((b't', b'tool', b'', _(b"specify merge tool for rebase")))
cmdutil.summaryhooks.add(b'rebase', summaryhook)
Augie Fackler
formatting: blacken the codebase...
r43346 statemod.addunfinished(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'rebase',
fname=b'rebasestate',
Augie Fackler
formatting: blacken the codebase...
r43346 stopflag=True,
continueflag=True,
abortfunc=abortrebase,
continuefunc=continuerebase,
)