##// END OF EJS Templates
scmutil: extract general delta config handling in a function...
scmutil: extract general delta config handling in a function General delta is currently controlled by a single option, we will introduce a new one in the next changeset. We extract the logic in a function while it is simple.

File last commit:

r26902:7ffebbdc default
r26906:e40af07e default
Show More
rebase.py
1238 lines | 50.3 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 '''
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884 from mercurial import hg, util, repair, merge, cmdutil, commands, bookmarks
Augie Fackler
rebase: switch from util.Abort to util.InterventionRequired where appropriate (bc)
r18933 from mercurial import extensions, patch, scmutil, phases, obsolete, error
Pierre-Yves David
rebase: move destination computation in a revset...
r26301 from mercurial import copies, repoview, revset
Stefano Tortarolo
Add rebase extension
r6906 from mercurial.commands import templateopts
Mads Kiilerich
rebase: show more useful status information while rebasing...
r23517 from mercurial.node import nullrev, nullid, hex, short
Ronny Pfannschmidt
switch lock releasing in the extensions from gc to explicit
r8112 from mercurial.lock import release
Stefano Tortarolo
Add rebase extension
r6906 from mercurial.i18n import _
import os, errno
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
Stefano Tortarolo
rebase: add --detach option to detach intermediate revisions (issue1950)...
r10352 nullmerge = -2
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 revignored = -3
Christian Delahousse
rebase: added comments...
r26669 # To do with obsolescence
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 revprecursor = -4
Stefano Tortarolo
rebase: add --detach option to detach intermediate revisions (issue1950)...
r10352
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 cmdtable = {}
command = cmdutil.command(cmdtable)
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # Note for extension authors: ONLY specify testedwith = 'internal' for
# 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
hgext: mark all first-party extensions as such
r16743 testedwith = 'internal'
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306
Ryan McElroy
rebase: factor out nothing to rebase return code...
r26671 def _nothingtorebase():
return 1
Augie Fackler
rebase: preserve metadata from grafts of changes (issue4001)
r19861 def _savegraft(ctx, extra):
s = ctx.extra().get('source', None)
if s is not None:
extra['source'] = s
Matt Harbison
rebase: preserve the 'intermediate-source' attribute of grafts...
r26902 s = ctx.extra().get('intermediate-source', None)
if s is not None:
extra['intermediate-source'] = s
Augie Fackler
rebase: preserve metadata from grafts of changes (issue4001)
r19861
Augie Fackler
rebase: rework extrafn handling to support multiple extrafns...
r19860 def _savebranch(ctx, extra):
extra['branch'] = ctx.branch()
def _makeextrafn(copiers):
"""make an extrafn out of the given copy-functions.
A copy function takes a context and an extra dict, and mutates the
extra dict as needed based on the given context.
"""
def extrafn(ctx, extra):
for c in copiers:
c(ctx, extra)
return extrafn
Pierre-Yves David
rebase: extra default destination in its own function...
r26717 def _destrebase(repo):
# Destination defaults to the latest revision in the
# current branch
branch = repo[None].branch()
return repo[branch].rev()
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: - taking rev as arguments,
# # XXX: - bailing out in case of ambiguity vs returning all data.
# # XXX: - probably merging with the merge destination.
# i18n: "_rebasedefaultdest" is a keyword
revset.getargs(x, 0, 0, _("_rebasedefaultdest takes no arguments"))
Pierre-Yves David
rebase: extra default destination in its own function...
r26717 return subset & revset.baseset([_destrebase(repo)])
Pierre-Yves David
rebase: move destination computation in a revset...
r26301
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 @command('rebase',
[('s', 'source', '',
Matt Mackall
rebase: attempt to clarify --base
r22789 _('rebase the specified changeset and descendants'), _('REV')),
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 ('b', 'base', '',
Matt Mackall
rebase: attempt to clarify --base
r22789 _('rebase everything from branching point of specified changeset'),
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 _('REV')),
Pierre-Yves David
rebase: add --rev option to rebase...
r15270 ('r', 'rev', [],
_('rebase these revisions'),
_('REV')),
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 ('d', 'dest', '',
_('rebase onto the specified changeset'), _('REV')),
('', 'collapse', False, _('collapse the rebased changesets')),
('m', 'message', '',
_('use text as collapse commit message'), _('TEXT')),
Matt Mackall
rebase: add --edit switch
r15219 ('e', 'edit', False, _('invoke editor on commit messages')),
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 ('l', 'logfile', '',
_('read collapse commit message from file'), _('FILE')),
Nat Mote
rebase: add short -k option for --keep...
r25025 ('k', 'keep', False, _('keep original changesets')),
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 ('', 'keepbranches', False, _('keep original branch names')),
Pierre-Yves David
rebase: do not add second parent to rebased changeset (drop detach option) (BC)...
r17005 ('D', 'detach', False, _('(DEPRECATED)')),
David Soria Parra
rebase: add a deprecated -i/--interactive flag...
r22382 ('i', 'interactive', False, _('(DEPRECATED)')),
Adrian Buehlmann
rebase: use cmdutil.command decorator
r14306 ('t', 'tool', '', _('specify merge tool')),
('c', 'continue', False, _('continue an interrupted rebase')),
('a', 'abort', False, _('abort an interrupted rebase'))] +
templateopts,
Patrick Mezard
rebase: remove second broken synopsis line (issue3172)...
r17325 _('[-s REV | -b REV] [-d REV] [OPTION]'))
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.
Martin Geisler
rebase: stress that only local changesets should be rebased
r11188 You should not rebase changesets that have already been shared
with others. Doing so will force everybody else to perform the
same rebase or they will end up with duplicated changesets after
pulling in your rebased changesets.
Kevin Bullock
rebase: mention phases in the help...
r18516 In its default configuration, Mercurial will prevent you from
rebasing published changes. See :hg:`help phases` for details.
Greg Ward
rebase: improve help text...
r10646 If you don't specify a destination changeset (``-d/--dest``),
Matt Mackall
rebase: simplify references to branch tips
r19398 rebase uses the current branch tip as the destination. (The
destination changeset is not modified by rebasing, but new
changesets are added as its descendants.)
Greg Ward
rebase: improve help text...
r10646
You can specify which changesets to rebase in two ways: as a
Martin Geisler
rebase: remove unnecessary \" from help string...
r10659 "source" changeset or as a "base" changeset. Both are shorthand
for a topologically related set of changesets (the "source
branch"). If you specify source (``-s/--source``), rebase will
rebase that changeset and all of its descendants onto dest. If you
specify base (``-b/--base``), rebase will select ancestors of base
back to but not including the common ancestor with dest. Thus,
``-b`` is less precise but more convenient than ``-s``: you can
specify any changeset in the source branch, and rebase will select
the whole branch. If you specify neither ``-s`` nor ``-b``, rebase
uses the parent of the working directory as the base.
Greg Ward
rebase: improve help text...
r10646
Pierre-Yves David
rebase: mention --rev in the help...
r18518 For advanced usage, a third way is available through the ``--rev``
option. It allows you to specify an arbitrary set of changesets to
rebase. Descendants of revs you specify with this option are not
automatically included in the rebase.
Greg Ward
rebase: improve help text...
r10646 By default, rebase recreates the changesets in the source branch
as descendants of dest and then destroys the originals. Use
``--keep`` to preserve the original source changesets. Some
changesets in the source branch (e.g. merges from the destination
branch) may be dropped if they no longer contribute any change.
One result of the rules for selecting the destination changeset
and source branch is that, unlike ``merge``, rebase will do
Matt Mackall
rebase: simplify references to branch tips
r19398 nothing if you are at the branch tip of a named branch
Greg Ward
rebase: improve help text...
r10646 with two heads. You need to explicitly specify source and/or
destination (or ``update`` to the other head, if it's the head of
the intended source branch).
Stefano Tortarolo
Add rebase extension
r6906
Martin Geisler
rebase: word-wrap help texts at 70 characters
r7999 If a rebase is interrupted to manually resolve a merge, it can be
Martin Geisler
help texts: write command line switches as -a/--abc
r8076 continued with --continue/-c or aborted with --abort/-a.
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
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 """
Benoit Boissinot
remove unused variables
r7280 originalwd = target = None
Durham Goode
rebase: restore active bookmark after rebase --continue...
r18755 activebookmark = None
Stefano Tortarolo
Add rebase extension
r6906 external = nullrev
Mads Kiilerich
spelling: trivial spell checking
r26781 # 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
Christian Delahousse
rebase: added comments...
r26669 # will be what contains most of the rebase progress state.
Benoit Boissinot
rebase: use set instead of dict
r8454 state = {}
skipped = set()
Stefano Tortarolo
rebase: refactoring...
r10351 targetancestors = set()
Stefano Tortarolo
Add rebase extension
r6906
Matt Mackall
rebase: add --edit switch
r15219
Stefano Tortarolo
Add rebase extension
r6906 lock = wlock = None
try:
Mads Kiilerich
rebase: take locks in the right order...
r15874 wlock = repo.wlock()
Stefano Tortarolo
Add rebase extension
r6906 lock = repo.lock()
# Validate input and define rebasing points
destf = opts.get('dest', None)
srcf = opts.get('source', None)
basef = opts.get('base', None)
Pierre-Yves David
rebase: add --rev option to rebase...
r15270 revf = opts.get('rev', [])
Stefano Tortarolo
Add rebase extension
r6906 contf = opts.get('continue')
abortf = opts.get('abort')
collapsef = opts.get('collapse', False)
Idan Kamara
cmdutil, logmessage: use ui.fin when reading from '-'
r14635 collapsemsg = cmdutil.logmessage(ui, opts)
Stanislau Hlebik
rebase: pass date parameter to concludenode
r26869 date = opts.get('date', None)
Augie Fackler
rebase: rework extrafn handling to support multiple extrafns...
r19860 e = opts.get('extrafn') # internal, used by e.g. hgsubversion
Augie Fackler
rebase: preserve metadata from grafts of changes (issue4001)
r19861 extrafns = [_savegraft]
Augie Fackler
rebase: rework extrafn handling to support multiple extrafns...
r19860 if e:
extrafns = [e]
Stefano Tortarolo
rebase: store/restore arguments correctly...
r7952 keepf = opts.get('keep', False)
keepbranchesf = opts.get('keepbranches', False)
Stefano Tortarolo
rebase: add option to not commit after a collapsing...
r10677 # keepopen is not meant for use on the command line, but by
# other extensions
keepopen = opts.get('keepopen', False)
Augie Fackler
rebase: add support to keep branch names...
r7468
David Soria Parra
rebase: add a deprecated -i/--interactive flag...
r22382 if opts.get('interactive'):
timeless@mozdev.org
rebase: enable histedit for useful help with it
r26496 try:
if extensions.find('histedit'):
enablehistedit = ''
except KeyError:
enablehistedit = " --config extensions.histedit="
help = "hg%s help -e histedit" % enablehistedit
David Soria Parra
rebase: add a deprecated -i/--interactive flag...
r22382 msg = _("interactive history editing is supported by the "
timeless@mozdev.org
rebase: factor out histedit help command
r26494 "'histedit' extension (see \"%s\")") % 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
Radomir Dopieralski
rebase: add -m/--message to rebase --collapse (issue2389)...
r13661 if collapsemsg and not collapsef:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Radomir Dopieralski
rebase: add -m/--message to rebase --collapse (issue2389)...
r13661 _('message can only be specified with collapse'))
Stefano Tortarolo
Add rebase extension
r6906 if contf or abortf:
if contf and abortf:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot use both abort and continue'))
Stefano Tortarolo
Add rebase extension
r6906 if collapsef:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Matt Mackall
rebase: use usual util.abort rather than error.ParseError
r11285 _('cannot use collapse with continue or abort'))
Martin Geisler
remove unnecessary outer parenthesis in if-statements
r8117 if srcf or basef or destf:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Stefano Tortarolo
Add rebase extension
r6906 _('abort and continue do not allow specifying revisions'))
liscju
rebase: fix warning about ignoring tool option on rebase continue (issue4698)...
r26165 if abortf and opts.get('tool', False):
Stefano Tortarolo
rebase: add --tool argument for specifying merge tool
r13856 ui.warn(_('tool option will be ignored\n'))
Stefano Tortarolo
Add rebase extension
r6906
FUJIWARA Katsunori
rebase: catch RepoLookupError at restoring rebase state for abort/continue...
r19848 try:
(originalwd, target, state, skipped, collapsef, keepf,
keepbranchesf, external, activebookmark) = restorestatus(repo)
except error.RepoLookupError:
if abortf:
clearstatus(repo)
repo.ui.warn(_('rebase aborted (no revision is removed,'
' only broken state is cleared)\n'))
return 0
else:
msg = _('cannot continue inconsistent rebase')
Simon Heimberg
hgext: fix one typo in rebase
r20313 hint = _('use "hg rebase --abort" to clear broken state')
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg, hint=hint)
Stefano Tortarolo
Add rebase extension
r6906 if abortf:
Tony Tung
rebase: restore bookmark state on abort...
r24758 return abort(repo, originalwd, target, state,
activebookmark=activebookmark)
Stefano Tortarolo
Add rebase extension
r6906 else:
if srcf and basef:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot specify both a '
Pierre-Yves David
rebase: add --rev option to rebase...
r15270 'source and a base'))
if revf and basef:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot specify both a '
Matt Mackall
rebase: use usual util.abort rather than error.ParseError
r11285 'revision and a base'))
Pierre-Yves David
rebase: add --rev option to rebase...
r15270 if revf and srcf:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot specify both a '
Pierre-Yves David
rebase: add --rev option to rebase...
r15270 'revision and a source'))
Stefano Tortarolo
rebase: add --detach option to detach intermediate revisions (issue1950)...
r10352
Matt Mackall
rebase: add checkunfinished support (issue3955)
r19478 cmdutil.checkunfinished(repo)
Matt Mackall
cmdutil: bail_if_changed to bailifchanged
r14289 cmdutil.bailifchanged(repo)
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267
Pierre-Yves David
rebase: directly use '_destrebase'...
r26718 if destf:
dest = scmutil.revsingle(repo, destf)
else:
dest = repo[_destrebase(repo)]
destf = str(dest)
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267
Matt Mackall
rebase: simplify set generation
r15271 if revf:
Bryan O'Sullivan
rebase: handle bookmarks matching revset function names (issue3950)...
r19641 rebaseset = scmutil.revrange(repo, revf)
Mads Kiilerich
rebase: improve error message for empty --rev set...
r20247 if not rebaseset:
Julien Cristau
rebase: don't abort if we're asked to rebase an empty revset...
r21197 ui.status(_('empty "rev" revision set - '
'nothing to rebase\n'))
Ryan McElroy
rebase: factor out nothing to rebase return code...
r26671 return _nothingtorebase()
Matt Mackall
rebase: simplify set generation
r15271 elif srcf:
Steven Brown
rebase: reinstate old-style rev spec support for the source and base (issue3181)...
r15800 src = scmutil.revrange(repo, [srcf])
Mads Kiilerich
rebase: improve error message for empty --source set...
r20248 if not src:
Mads Kiilerich
rebase: empty revset should be a gentle no-op with exit code 1, not an error
r21210 ui.status(_('empty "source" revision set - '
'nothing to rebase\n'))
Ryan McElroy
rebase: factor out nothing to rebase return code...
r26671 return _nothingtorebase()
Matt Mackall
merge with stable
r15801 rebaseset = repo.revs('(%ld)::', src)
Mads Kiilerich
rebase: improve error message for empty --source set...
r20248 assert rebaseset
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267 else:
Steven Brown
rebase: reinstate old-style rev spec support for the source and base (issue3181)...
r15800 base = scmutil.revrange(repo, [basef or '.'])
Mads Kiilerich
rebase: improve error message for --base being empty or causing emptiness...
r20249 if not base:
Mads Kiilerich
rebase: empty revset should be a gentle no-op with exit code 1, not an error
r21210 ui.status(_('empty "base" revision set - '
"can't compute rebase set\n"))
Ryan McElroy
rebase: factor out nothing to rebase return code...
r26671 return _nothingtorebase()
Durham Goode
rebase: improve base revset performance...
r23072 commonanc = repo.revs('ancestor(%ld, %d)', base, dest).first()
Durham Goode
rebase: fix rebase with no common ancestors (issue4446)...
r23246 if commonanc is not None:
rebaseset = repo.revs('(%d::(%ld) - %d)::',
commonanc, base, commonanc)
else:
rebaseset = []
Mads Kiilerich
rebase: improve error message for --base being empty or causing emptiness...
r20249 if not rebaseset:
Pierre-Yves David
rebase: transform the smartset to a list before comparing with a list...
r22823 # transform to list because smartsets are not comparable to
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 # lists. This should be improved to honor laziness of
Pierre-Yves David
rebase: transform the smartset to a list before comparing with a list...
r22823 # smartset.
if list(base) == [dest.rev()]:
Mads Kiilerich
rebase: improve error message for --base being empty or causing emptiness...
r20249 if basef:
ui.status(_('nothing to rebase - %s is both "base"'
' and destination\n') % dest)
else:
ui.status(_('nothing to rebase - working directory '
'parent is also destination\n'))
elif not repo.revs('%ld - ::%d', base, dest):
if basef:
ui.status(_('nothing to rebase - "base" %s is '
'already an ancestor of destination '
'%s\n') %
('+'.join(str(repo[r]) for r in base),
dest))
else:
ui.status(_('nothing to rebase - working '
'directory parent is already an '
'ancestor of destination %s\n') % dest)
else: # can it happen?
ui.status(_('nothing to rebase from %s to %s\n') %
('+'.join(str(repo[r]) for r in base), dest))
Ryan McElroy
rebase: factor out nothing to rebase return code...
r26671 return _nothingtorebase()
Matt Mackall
rebase: simplify set generation
r15271
Durham Goode
obsolete: add allowunstable option...
r22952 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
if (not (keepf or allowunstable)
Pierre-Yves David
clfilter: drop unnecessary explicit filtering on rebase...
r18269 and repo.revs('first(children(%ld) - %ld)',
Pierre-Yves David
rebase: allow non-head rebase-set when obsolete is enabled...
r18164 rebaseset, rebaseset)):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Matt Mackall
rebase: simplify check for orphaned descendants
r15272 _("can't remove original changesets with"
" unrebased descendants"),
hint=_('use --keep to keep original changesets'))
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 obsoletenotrebased = {}
if ui.configbool('experimental', 'rebaseskipobsolete'):
rebasesetrevs = set(rebaseset)
obsoletenotrebased = _computeobsoletenotrebased(repo,
rebasesetrevs,
dest)
# - plain prune (no successor) changesets are rebased
# - split changesets are not rebased if at least one of the
# changeset resulting from the split is an ancestor of dest
rebaseset = rebasesetrevs - set(obsoletenotrebased)
result = buildstate(repo, dest, rebaseset, collapsef,
obsoletenotrebased)
Stefano Tortarolo
rebase: refactoring...
r10351 if not result:
# Empty state built, nothing to rebase
Martin Geisler
use ui instead of repo.ui when the former is in scope
r8615 ui.status(_('nothing to rebase\n'))
Ryan McElroy
rebase: factor out nothing to rebase return code...
r26671 return _nothingtorebase()
Mads Kiilerich
rebase: remove old code for handling empty rebaseset
r20250
root = min(rebaseset)
if not keepf and not repo[root].mutable():
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("can't rebase public changeset %s")
Siddharth Agarwal
rebase: check no-op before checking phase (issue3891)...
r19059 % repo[root],
Wagner Bruna
messages: quote "hg help" hints consistently
r23917 hint=_('see "hg help phases" for details'))
Mads Kiilerich
rebase: remove old code for handling empty rebaseset
r20250
originalwd, target, state = result
if collapsef:
targetancestors = repo.changelog.ancestors([target],
inclusive=True)
external = externalparent(repo, state, targetancestors)
Stefano Tortarolo
Add rebase extension
r6906
Mads Kiilerich
rebase: tell when reopening a closed branch head...
r21027 if dest.closesbranch() and not keepbranchesf:
ui.status(_('reopening closed branch head %s\n') % dest)
Stefano Tortarolo
rebase: store/restore arguments correctly...
r7952 if keepbranchesf:
Augie Fackler
rebase: rework extrafn handling to support multiple extrafns...
r19860 # insert _savebranch at the start of extrafns so if
# there's a user-provided extrafn it can clobber branch if
# desired
extrafns.insert(0, _savebranch)
Stefano Tortarolo
rebase: block collapse with keepbranches on multiple named branches (issue2112)...
r14897 if collapsef:
branches = set()
for rev in state:
branches.add(repo[rev].branch())
if len(branches) > 1:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot collapse multiple named '
Stefano Tortarolo
rebase: block collapse with keepbranches on multiple named branches (issue2112)...
r14897 'branches'))
Stefano Tortarolo
Add rebase extension
r6906 # Rebase
Stefano Tortarolo
rebase: refactoring...
r10351 if not targetancestors:
Siddharth Agarwal
rebase: use lazy ancestor membership testing...
r18093 targetancestors = repo.changelog.ancestors([target], inclusive=True)
Stefano Tortarolo
Add rebase extension
r6906
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884 # Keep track of the current bookmarks in order to reset them later
currentbookmarks = repo._bookmarks.copy()
Ryan McElroy
bookmarks: rename bookmarkcurrent to activebookmark (API)...
r24947 activebookmark = activebookmark or repo._activebookmark
David Schleimer
bookmarks: correctly update current bookmarks on rebase (issue2277)...
r17046 if activebookmark:
Ryan McElroy
bookmarks: rename unsetcurrent to deactivate (API)...
r24944 bookmarks.deactivate(repo)
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884
Augie Fackler
rebase: rework extrafn handling to support multiple extrafns...
r19860 extrafn = _makeextrafn(extrafns)
timeless
rebase/progress: Adding progress for rebasing
r11729 sortedstate = sorted(state)
total = len(sortedstate)
pos = 0
for rev in sortedstate:
Mads Kiilerich
rebase: show more useful status information while rebasing...
r23517 ctx = repo[rev]
desc = '%d:%s "%s"' % (ctx.rev(), ctx,
ctx.description().split('\n', 1)[0])
names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
if names:
desc += ' (%s)' % ' '.join(names)
timeless
rebase/progress: Adding progress for rebasing
r11729 pos += 1
Pierre-Yves David
rebase: add a 'revtodo' constant...
r23490 if state[rev] == revtodo:
Mads Kiilerich
rebase: show more useful status information while rebasing...
r23517 ui.status(_('rebasing %s\n') % desc)
ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
timeless
progress: dropping superfluous space from units
r12744 _('changesets'), total)
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 p1, p2, base = defineparents(repo, rev, target, state,
targetancestors)
Stefano Tortarolo
rebase: store/restore arguments correctly...
r7952 storestatus(repo, originalwd, target, state, collapsef, keepf,
Durham Goode
rebase: restore active bookmark after rebase --continue...
r18755 keepbranchesf, external, activebookmark)
Stefano Tortarolo
rebase: refactoring...
r10351 if len(repo.parents()) == 2:
repo.ui.debug('resuming interrupted rebase\n')
else:
Stefano Tortarolo
rebase: add --tool argument for specifying merge tool
r13856 try:
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
'rebase')
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 stats = rebasenode(repo, rev, p1, base, state,
collapsef, target)
Stefano Tortarolo
rebase: add --tool argument for specifying merge tool
r13856 if stats and stats[3] > 0:
Augie Fackler
rebase: switch from util.Abort to util.InterventionRequired where appropriate (bc)
r18933 raise error.InterventionRequired(
_('unresolved conflicts (see hg '
'resolve, then hg rebase --continue)'))
Stefano Tortarolo
rebase: add --tool argument for specifying merge tool
r13856 finally:
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 ui.setconfig('ui', 'forcemerge', '', 'rebase')
Stefano Tortarolo
rebase: refactoring...
r10351 if not collapsef:
Mads Kiilerich
rebase: avoid redundant repo[rev].rev() - just keep working in rev space
r23461 merging = p2 != nullrev
FUJIWARA Katsunori
rebase: change "editform" to distinguish merge commits from others...
r22251 editform = cmdutil.mergeeditform(merging, 'rebase')
editor = cmdutil.getcommiteditor(editform=editform, **opts)
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 newnode = concludenode(repo, rev, p1, p2, extrafn=extrafn,
timeless@mozdev.org
rebase: avoid losing branch commits with --keepbranch (issue4835)
r26360 editor=editor,
Stanislau Hlebik
rebase: pass date parameter to concludenode
r26869 keepbranches=keepbranchesf,
date=date)
Stefano Tortarolo
rebase: refactoring...
r10351 else:
# Skip commit if we are collapsing
Durham Goode
dirstate: wrap setparent calls with begin/endparentchange (issue4353)...
r22405 repo.dirstate.beginparentchange()
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 repo.setparents(repo[p1].node())
Durham Goode
dirstate: wrap setparent calls with begin/endparentchange (issue4353)...
r22405 repo.dirstate.endparentchange()
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 newnode = None
Stefano Tortarolo
rebase: refactoring...
r10351 # Update the state
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 if newnode is not None:
state[rev] = repo[newnode].rev()
Mads Kiilerich
rebase: improve debug messages while processing the list of rebases
r23519 ui.debug('rebased as %s\n' % short(newnode))
Stefano Tortarolo
rebase: refactoring...
r10351 else:
if not collapsef:
Mads Kiilerich
rebase: fix wrong 'no changes to commit' when using --collapse...
r26811 ui.warn(_('note: rebase of %d:%s created no changes '
'to commit\n') % (rev, ctx))
Stefano Tortarolo
rebase: refactoring...
r10351 skipped.add(rev)
state[rev] = p1
Mads Kiilerich
rebase: improve debug messages while processing the list of rebases
r23519 ui.debug('next revision set to %s\n' % p1)
Mads Kiilerich
rebase: show more useful status information while rebasing...
r23517 elif state[rev] == nullmerge:
Mads Kiilerich
rebase: improve debug messages while processing the list of rebases
r23519 ui.debug('ignoring null merge rebase of %s\n' % rev)
Mads Kiilerich
rebase: show more useful status information while rebasing...
r23517 elif state[rev] == revignored:
ui.status(_('not rebasing ignored %s\n') % desc)
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 elif state[rev] == revprecursor:
targetctx = repo[obsoletenotrebased[rev]]
desctarget = '%d:%s "%s"' % (targetctx.rev(), targetctx,
targetctx.description().split('\n', 1)[0])
msg = _('note: not rebasing %s, already in destination as %s\n')
ui.status(msg % (desc, desctarget))
Mads Kiilerich
rebase: show more useful status information while rebasing...
r23517 else:
ui.status(_('already rebased %s as %s\n') %
(desc, repo[state[rev]]))
Stefano Tortarolo
rebase: refactoring...
r10351
timeless
rebase/progress: Adding progress for rebasing
r11729 ui.progress(_('rebasing'), None)
Stefano Tortarolo
Add rebase extension
r6906 ui.note(_('rebase merging completed\n'))
Stefano Tortarolo
rebase: add option to not commit after a collapsing...
r10677 if collapsef and not keepopen:
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 p1, p2, _base = defineparents(repo, min(state), target,
state, targetancestors)
FUJIWARA Katsunori
rebase: use "rebase.collapse" as "editform" for "--collapse" always...
r22206 editopt = opts.get('edit')
editform = 'rebase.collapse'
Radomir Dopieralski
rebase: add -m/--message to rebase --collapse (issue2389)...
r13661 if collapsemsg:
commitmsg = collapsemsg
else:
commitmsg = 'Collapsed revision'
for rebased in state:
Pierre-Yves David
rebase: lose the comparison to `nullmerge`...
r18446 if rebased not in skipped and state[rebased] > nullmerge:
Radomir Dopieralski
rebase: add -m/--message to rebase --collapse (issue2389)...
r13661 commitmsg += '\n* %s' % repo[rebased].description()
FUJIWARA Katsunori
rebase: use "rebase.collapse" as "editform" for "--collapse" always...
r22206 editopt = True
editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 newnode = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
timeless@mozdev.org
rebase: avoid losing branch commits with --keepbranch (issue4835)
r26360 extrafn=extrafn, editor=editor,
Stanislau Hlebik
rebase: pass date parameter to concludenode
r26869 keepbranches=keepbranchesf,
date=date)
Mads Kiilerich
rebase: always store rev in state, also when collapsing
r23460 if newnode is None:
newrev = target
else:
newrev = repo[newnode].rev()
Durham Goode
rebase: fix working copy location after a --collapse (issue4080)...
r19986 for oldrev in state.iterkeys():
if state[oldrev] > nullmerge:
Mads Kiilerich
rebase: always store rev in state, also when collapsing
r23460 state[oldrev] = newrev
Stefano Tortarolo
Add rebase extension
r6906
if 'qtip' in repo.tags():
updatemq(repo, state, skipped, **opts)
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884 if currentbookmarks:
# Nodeids are needed to reset bookmarks
nstate = {}
for k, v in state.iteritems():
Pierre-Yves David
rebase: lose the comparison to `nullmerge`...
r18446 if v > nullmerge:
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884 nstate[repo[k].node()] = repo[v].node()
Siddharth Agarwal
rebase: derive node from target rev (issue3802)...
r18549 # XXX this is the same as dest.node() for the non-continue path --
# this should probably be cleaned up
targetnode = repo[target].node()
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884
Pierre-Yves David
rebase: preserve working directory parent (BC)...
r19925 # restore original working directory
# (we do this before stripping)
newwd = state.get(originalwd, originalwd)
Pierre-Yves David
rebase: ignore negative state when updating back to original wc parent...
r23440 if newwd < 0:
# original directory is a parent of rebase set root or ignored
newwd = originalwd
Pierre-Yves David
rebase: preserve working directory parent (BC)...
r19925 if newwd not in [c.rev() for c in repo[None].parents()]:
ui.note(_("update back to initial working directory parent\n"))
hg.updaterepo(repo, newwd, False)
Stefano Tortarolo
rebase: store/restore arguments correctly...
r7952 if not keepf:
Pierre-Yves David
rebase: properly handle --collapse when creating obsolescence marker...
r17613 collapsedas = None
if collapsef:
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 collapsedas = newnode
Pierre-Yves David
rebase: do not invent successor to skipped changeset...
r18444 clearrebased(ui, repo, state, skipped, collapsedas)
Stefano Tortarolo
Add rebase extension
r6906
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884 if currentbookmarks:
Siddharth Agarwal
rebase: derive node from target rev (issue3802)...
r18549 updatebookmarks(repo, targetnode, nstate, currentbookmarks)
Yuya Nishihara
rebase: do not try to reactivate deleted divergent bookmark...
r20523 if activebookmark not in repo._bookmarks:
# active bookmark was divergent one and has been deleted
activebookmark = None
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884
Stefano Tortarolo
Add rebase extension
r6906 clearstatus(repo)
Matt Mackall
rebase: only show "rebase completed" message with -v
r11203 ui.note(_("rebase completed\n"))
Mads Kiilerich
refactoring: use unlinkpath with ignoremissing
r18386 util.unlinkpath(repo.sjoin('undo'), ignoremissing=True)
Stefano Tortarolo
Add rebase extension
r6906 if skipped:
ui.note(_("%d revisions have been skipped\n") % len(skipped))
David Schleimer
bookmarks: correctly update current bookmarks on rebase (issue2277)...
r17046
if (activebookmark and
Pierre-Yves David
rebase: preserve active bookmark when not at head (issue3813)...
r19926 repo['.'].node() == repo._bookmarks[activebookmark]):
Ryan McElroy
bookmarks: rename setcurrent to activate (API)...
r24945 bookmarks.activate(repo, activebookmark)
David Schleimer
bookmarks: correctly update current bookmarks on rebase (issue2277)...
r17046
Stefano Tortarolo
Add rebase extension
r6906 finally:
Ronny Pfannschmidt
switch lock releasing in the extensions from gc to explicit
r8112 release(lock, wlock)
Stefano Tortarolo
Add rebase extension
r6906
Mads Kiilerich
rebase: refactor and rename checkexternal - it is a getter more than a setter
r19955 def externalparent(repo, state, targetancestors):
"""Return the revision that should be used as the second parent
when the revisions in state is collapsed on top of targetancestors.
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():
if (p.rev() not in state
and p.rev() not in targetancestors):
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()
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('unable to collapse on top of %s, there is more '
Mads Kiilerich
rebase: improve error message for more than one external parent
r19956 'than one external parent: %s') %
(max(targetancestors),
', '.join(str(p) for p in sorted(parents))))
Stefano Tortarolo
rebase: refactoring...
r10351
timeless@mozdev.org
rebase: avoid losing branch commits with --keepbranch (issue4835)
r26360 def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None,
Stanislau Hlebik
rebase: add date parameter to concludenode function...
r26868 keepbranches=False, date=None):
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev
but also store useful information in extra.
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 Return node of committed revision.'''
FUJIWARA Katsunori
rebase: use dirstateguard instead of dirstate.invalidate...
r24998 dsguard = cmdutil.dirstateguard(repo, 'rebase')
Stefano Tortarolo
Add rebase extension
r6906 try:
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 repo.setparents(repo[p1].node(), repo[p2].node())
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 ctx = repo[rev]
Stefano Tortarolo
rebase: refactoring...
r10351 if commitmsg is None:
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 commitmsg = ctx.description()
timeless@mozdev.org
rebase: avoid losing branch commits with --keepbranch (issue4835)
r26360 keepbranch = keepbranches and repo[p1].branch() != ctx.branch()
Patrick Mezard
rebase: fix --collapse with --keepbranches (issue2100)...
r10762 extra = {'rebase_source': ctx.hex()}
if extrafn:
extrafn(ctx, extra)
Pierre-Yves David
rebase: do not retract phase boundary by hand...
r22038
backup = repo.ui.backupconfig('phases', 'new-commit')
try:
targetphase = max(ctx.phase(), phases.draft)
repo.ui.setconfig('phases', 'new-commit', targetphase, 'rebase')
timeless@mozdev.org
rebase: avoid losing branch commits with --keepbranch (issue4835)
r26360 if keepbranch:
repo.ui.setconfig('ui', 'allowemptycommit', True)
Pierre-Yves David
rebase: do not retract phase boundary by hand...
r22038 # Commit might fail if unresolved files exist
Stanislau Hlebik
rebase: add date parameter to concludenode function...
r26868 if date is None:
date = ctx.date()
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 newnode = repo.commit(text=commitmsg, user=ctx.user(),
Stanislau Hlebik
rebase: add date parameter to concludenode function...
r26868 date=date, extra=extra, editor=editor)
Pierre-Yves David
rebase: do not retract phase boundary by hand...
r22038 finally:
repo.ui.restoreconfig(backup)
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 repo.dirstate.setbranch(repo[newnode].branch())
FUJIWARA Katsunori
rebase: use dirstateguard instead of dirstate.invalidate...
r24998 dsguard.close()
Mads Kiilerich
rebase: clarify naming of variables holding node hashes - don't call them rev
r23459 return newnode
FUJIWARA Katsunori
rebase: use dirstateguard instead of dirstate.invalidate...
r24998 finally:
release(dsguard)
Stefano Tortarolo
Add rebase extension
r6906
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 def rebasenode(repo, rev, p1, base, state, collapse, target):
'Rebase a single revision rev on top of p1 using base as merge ancestor'
Stefano Tortarolo
Add rebase extension
r6906 # Merge phase
Stefano Tortarolo
rebase: refactoring...
r10351 # Update to target and merge it with local
Mads Kiilerich
rebase: avoid redundant repo[rev].rev() - just keep working in rev space
r23461 if repo['.'].rev() != p1:
repo.ui.debug(" update to %d:%s\n" % (p1, repo[p1]))
Stefano Tortarolo
rebase: refactoring...
r10351 merge.update(repo, p1, False, True, False)
Stefano Tortarolo
Add rebase extension
r6906 else:
Stefano Tortarolo
rebase: refactoring...
r10351 repo.ui.debug(" already in target\n")
FUJIWARA Katsunori
dirstate: make dirstate.write() callers pass transaction object to it...
r26748 repo.dirstate.write(repo.currenttransaction())
Mads Kiilerich
rebase: avoid redundant repo[rev].rev() - just keep working in rev space
r23461 repo.ui.debug(" 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:
Mads Kiilerich
rebase: avoid redundant repo[rev].rev() - just keep working in rev space
r23461 repo.ui.debug(" 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.
Matt Mackall
rebase: move duplicatecopies next to merge...
r22905 stats = merge.update(repo, rev, True, True, False, base, collapse,
Durham Goode
rebase: specify custom conflict marker labels for rebase (BC)...
r21526 labels=['dest', 'source'])
Matt Mackall
rebase: move duplicatecopies next to merge...
r22905 if collapse:
copies.duplicatecopies(repo, rev, target)
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()
copies.duplicatecopies(repo, rev, p1rev, skiprev=target)
return stats
Dirkjan Ochtman
strip trailing whitespace, replace tabs by spaces
r6923
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 def nearestrebased(repo, rev, state):
"""return the nearest ancestors of rev in the rebase result"""
rebased = [r for r in state if state[r] > nullmerge]
candidates = repo.revs('max(%ld and (::%d))', rebased, rev)
if candidates:
Pierre-Yves David
rebase: use `last` instead of direct indexing...
r22820 return state[candidates.first()]
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 else:
return None
Stefano Tortarolo
Add rebase extension
r6906 def defineparents(repo, rev, target, state, targetancestors):
'Return the new parent relationship of the revision that will be rebased'
parents = repo[rev].parents()
p1 = p2 = nullrev
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p1n = parents[0].rev()
if p1n in targetancestors:
Stefano Tortarolo
Add rebase extension
r6906 p1 = target
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 elif p1n in state:
if state[p1n] == nullmerge:
Stefano Tortarolo
rebase: add --detach option to detach intermediate revisions (issue1950)...
r10352 p1 = target
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 elif state[p1n] in (revignored, revprecursor):
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p1 = nearestrebased(repo, p1n, state)
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 if p1 is None:
p1 = target
Stefano Tortarolo
rebase: add --detach option to detach intermediate revisions (issue1950)...
r10352 else:
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p1 = state[p1n]
else: # p1n external
Stefano Tortarolo
Add rebase extension
r6906 p1 = target
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p2 = p1n
Stefano Tortarolo
Add rebase extension
r6906
if len(parents) == 2 and parents[1].rev() not in targetancestors:
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p2n = parents[1].rev()
Stefano Tortarolo
Add rebase extension
r6906 # interesting second parent
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 if p2n in state:
if p1 == target: # p1n in targetancestors or external
p1 = state[p2n]
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 elif state[p2n] in (revignored, revprecursor):
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p2 = nearestrebased(repo, p2n, state)
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 if p2 is None:
# no ancestors rebased yet, detach
p2 = target
Stefano Tortarolo
Add rebase extension
r6906 else:
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p2 = state[p2n]
else: # p2n external
if p2 != nullrev: # p1n external too => rev is a merged revision
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot use revision %d as base, result '
Stefano Tortarolo
Add rebase extension
r6906 'would have 3 parents') % rev)
Matt Mackall
rebase: fix some weird mixed-case naming
r22906 p2 = p2n
Stefano Tortarolo
rebase: refactoring...
r10351 repo.ui.debug(" future parents are %d and %d\n" %
(repo[p1].rev(), repo[p2].rev()))
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484
if rev == min(state):
# Case (1) initial changeset of a non-detaching rebase.
# Let the merge mechanism find the base itself.
base = None
elif not repo[rev].p2():
# Case (2) detaching the node with a single parent, use this parent
base = repo[rev].p1().rev()
else:
Mads Kiilerich
rebase: clarify comment about merge ancestor when rebasing merges...
r23732 # Assuming there is a p1, this is the case where there also is a p2.
# We are thus rebasing a merge and need to pick the right merge base.
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 #
# Imagine we have:
Mads Kiilerich
rebase: clarify comment about merge ancestor when rebasing merges...
r23732 # - M: current rebase revision in this step
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 # - A: one parent of M
Mads Kiilerich
rebase: clarify comment about merge ancestor when rebasing merges...
r23732 # - B: other parent of M
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 # - D: destination of this merge step (p1 var)
#
Mads Kiilerich
rebase: clarify comment about merge ancestor when rebasing merges...
r23732 # Consider the case where D is a descendant of A or B and the other is
# 'outside'. In this case, the right merge base is the D ancestor.
#
# An informal proof, assuming A is 'outside' and B is the D ancestor:
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 #
# If we pick B as the base, the merge involves:
# - changes from B to M (actual changeset payload)
# - changes from B to D (induced by rebase) as D is a rebased
# version of B)
# Which exactly represent the rebase operation.
#
Mads Kiilerich
rebase: clarify comment about merge ancestor when rebasing merges...
r23732 # If we pick A as the base, the merge involves:
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 # - changes from A to M (actual changeset payload)
# - changes from A to D (with include changes between unrelated A and B
# plus changes induced by rebase)
# Which does not represent anything sensible and creates a lot of
Mads Kiilerich
rebase: clarify comment about merge ancestor when rebasing merges...
r23732 # conflicts. A is thus not the right choice - B is.
#
# Note: The base found in this 'proof' is only correct in the specified
# case. This base does not make sense if is not D a descendant of A or B
# or if the other is not parent 'outside' (especially not if the other
# parent has been rebased). The current implementation does not
# make it feasible to consider different cases separately. In these
# other cases we currently just leave it to the user to correctly
# resolve an impossible merge using a wrong ancestor.
Mads Kiilerich
rebase: move base calculation from rebasenode() to defineparents()...
r23484 for p in repo[rev].parents():
if state.get(p.rev()) == p1:
base = p.rev()
break
else: # fallback when base not found
base = None
# Raise because this function is called wrong (see issue 4106)
raise AssertionError('no base found to rebase on '
'(defineparents called wrong)')
return p1, p2, base
Stefano Tortarolo
Add rebase extension
r6906
Stefano Tortarolo
rebase: keep original mq patch format (Issue1574)...
r7955 def isagitpatch(repo, patchname):
'Return true if the given patch is in git format'
mqpatch = os.path.join(repo.mq.path, patchname)
for line in patch.linereader(file(mqpatch, 'rb')):
if line.startswith('diff --git'):
return True
return False
Stefano Tortarolo
Add rebase extension
r6906 def updatemq(repo, state, skipped, **opts):
'Update rebased mq patches - finalize and then import them'
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:
Martin Geisler
do not attempt to translate ui.debug output
r9467 repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 (rev, p.name))
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]
Mads Kiilerich
rebase: show a note for updated mq patches...
r23520 repo.ui.note(_('updating mq patch %s to %s:%s\n') %
(name, state[rev], repo[state[rev]]))
Nicolas Dumazet
rebase: small cosmetic cleanups
r11537 mq.qimport(repo, (), patchname=name, git=isgit,
rev=[str(state[rev])])
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.
newseries = [s for s in original_series
if mq.guard_re.split(s, 1)[0] not in skippedpatches]
mq.fullseries[:] = newseries
mq.seriesdirty = True
Adrian Buehlmann
mq: rename save_dirty to savedirty
r14580 mq.savedirty()
Stefano Tortarolo
Add rebase extension
r6906
Siddharth Agarwal
rebase: derive node from target rev (issue3802)...
r18549 def updatebookmarks(repo, targetnode, nstate, originalbookmarks):
Siddharth Agarwal
rebase: delete divergent bookmarks on destination (issue3685)...
r18514 'Move bookmarks to their correct changesets, and delete divergent ones'
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 marks = repo._bookmarks
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884 for k, v in originalbookmarks.iteritems():
if v in nstate:
Siddharth Agarwal
rebase: remove bogus nullmerge check in updatebookmarks...
r18512 # update the bookmarks for revs that have moved
marks[k] = nstate[v]
Siddharth Agarwal
rebase: derive node from target rev (issue3802)...
r18549 bookmarks.deletedivergent(repo, [targetnode], k)
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 marks.write()
Stefano Tortarolo
rebase: reset bookmarks (issue2265 and issue2873)
r14884
Stefano Tortarolo
rebase: store/restore arguments correctly...
r7952 def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches,
Durham Goode
rebase: restore active bookmark after rebase --continue...
r18755 external, activebookmark):
Stefano Tortarolo
Add rebase extension
r6906 'Store the current status to allow recovery'
Angel Ezquerra
localrepo: remove all external users of localrepo.opener...
r23877 f = repo.vfs("rebasestate", "w")
Stefano Tortarolo
Add rebase extension
r6906 f.write(repo[originalwd].hex() + '\n')
f.write(repo[target].hex() + '\n')
f.write(repo[external].hex() + '\n')
f.write('%d\n' % int(collapse))
Stefano Tortarolo
rebase: store/restore arguments correctly...
r7952 f.write('%d\n' % int(keep))
f.write('%d\n' % int(keepbranches))
Durham Goode
rebase: restore active bookmark after rebase --continue...
r18755 f.write('%s\n' % (activebookmark or ''))
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 for d, v in state.iteritems():
Stefano Tortarolo
Add rebase extension
r6906 oldrev = repo[d].hex()
Pierre-Yves David
rebase: handle revtodo as a special value when storing/restoring state...
r23491 if v >= 0:
Stefano Tortarolo
rebase: treat nullmerge as a special case in rebasestate (issue3046)...
r15464 newrev = repo[v].hex()
Pierre-Yves David
rebase: handle revtodo as a special value when storing/restoring state...
r23491 elif v == revtodo:
# To maintain format compatibility, we have to use nullid.
# Please do remove this special case when upgrading the format.
newrev = hex(nullid)
Stefano Tortarolo
rebase: treat nullmerge as a special case in rebasestate (issue3046)...
r15464 else:
newrev = v
Stefano Tortarolo
Add rebase extension
r6906 f.write("%s:%s\n" % (oldrev, newrev))
f.close()
Martin Geisler
do not attempt to translate ui.debug output
r9467 repo.ui.debug('rebase status stored\n')
Stefano Tortarolo
Add rebase extension
r6906
def clearstatus(repo):
'Remove the status files'
Pierre-Yves David
rebase: ensure rebase revision remains visible (issue4504)...
r23970 _clearrebasesetvisibiliy(repo)
Mads Kiilerich
refactoring: use unlinkpath with ignoremissing
r18386 util.unlinkpath(repo.join("rebasestate"), ignoremissing=True)
Stefano Tortarolo
Add rebase extension
r6906
def restorestatus(repo):
'Restore a previously stored status'
Christian Delahousse
rebase: reduce scope of try catch in restorestate...
r26745 keepbranches = None
target = None
collapse = False
external = nullrev
activebookmark = None
state = {}
Stefano Tortarolo
Add rebase extension
r6906 try:
Angel Ezquerra
localrepo: remove all external users of localrepo.opener...
r23877 f = repo.vfs("rebasestate")
Stefano Tortarolo
Add rebase extension
r6906 for i, l in enumerate(f.read().splitlines()):
if i == 0:
originalwd = repo[l].rev()
elif i == 1:
target = repo[l].rev()
elif i == 2:
external = repo[l].rev()
elif i == 3:
collapse = bool(int(l))
Stefano Tortarolo
rebase: store/restore arguments correctly...
r7952 elif i == 4:
keep = bool(int(l))
elif i == 5:
keepbranches = bool(int(l))
Durham Goode
rebase: restore active bookmark after rebase --continue...
r18755 elif i == 6 and not (len(l) == 81 and ':' in l):
# line 6 is a recent addition, so for backwards compatibility
# check that the line doesn't look like the oldrev:newrev lines
activebookmark = l
Stefano Tortarolo
Add rebase extension
r6906 else:
oldrev, newrev = l.split(':')
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 if newrev in (str(nullmerge), str(revignored),
str(revprecursor)):
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 state[repo[oldrev].rev()] = int(newrev)
Pierre-Yves David
rebase: handle revtodo as a special value when storing/restoring state...
r23491 elif newrev == nullid:
state[repo[oldrev].rev()] = revtodo
# Legacy compat special case
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 else:
Stefano Tortarolo
rebase: treat nullmerge as a special case in rebasestate (issue3046)...
r15464 state[repo[oldrev].rev()] = repo[newrev].rev()
Matt Mackall
rebase: abort cleanly when we encounter a damaged rebasestate (issue4155)
r20327
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as err:
Stefano Tortarolo
Add rebase extension
r6906 if err.errno != errno.ENOENT:
raise
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no rebase in progress'))
Stefano Tortarolo
Add rebase extension
r6906
Christian Delahousse
rebase: reduce scope of try catch in restorestate...
r26745 if keepbranches is None:
raise error.Abort(_('.hg/rebasestate is incomplete'))
skipped = set()
# recompute the set of skipped revs
if not collapse:
seen = set([target])
for old, new in sorted(state.items()):
if new != revtodo and new in seen:
skipped.add(old)
seen.add(new)
repo.ui.debug('computed skipped revs: %s\n' %
(' '.join(str(r) for r in sorted(skipped)) or None))
repo.ui.debug('rebase status resumed\n')
_setrebasesetvisibility(repo, state.keys())
return (originalwd, target, state, skipped,
collapse, keep, keepbranches, external, activebookmark)
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'''
Matt Mackall
rebase: don't clobber wd on --abort when we've updated away (issue4009)
r19516 parents = [p.rev() for p in repo.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.
firstunrebased = min([old for old, new in state.iteritems()
if new == nullrev])
if firstunrebased in parents:
Matt Mackall
rebase: don't clobber wd on --abort when we've updated away (issue4009)
r19516 return True
return False
Tony Tung
rebase: restore bookmark state on abort...
r24758 def abort(repo, originalwd, target, state, activebookmark=None):
'''Restore the repository to its original state. Additional args:
activebookmark: the name of the bookmark that should be active after the
restore'''
Christian Delahousse
rebase: properly abort when destination is public (issue4896)...
r26677
Christian Delahousse
rebase: on abort delete rebase state file no matter what...
r26744 try:
# If the first commits in the rebased set get skipped during the rebase,
# their values within the state mapping will be the target rev id. The
# dstates list must must not contain the target rev (issue4896)
dstates = [s for s in state.values() if s >= 0 and s != target]
immutable = [d for d in dstates if not repo[d].mutable()]
cleanup = True
if immutable:
repo.ui.warn(_("warning: can't clean up public changesets %s\n")
% ', '.join(str(repo[r]) for r in immutable),
hint=_('see "hg help phases" for details'))
cleanup = False
Matt Mackall
rebase: properly calculate descendant set when aborting (issue3332)...
r16280
Christian Delahousse
rebase: on abort delete rebase state file no matter what...
r26744 descendants = set()
if dstates:
descendants = set(repo.changelog.descendants(dstates))
if descendants - set(dstates):
repo.ui.warn(_("warning: new changesets detected on target branch, "
"can't strip\n"))
cleanup = False
Matt Mackall
rebase: allow aborting when descendants detected...
r19518
Christian Delahousse
rebase: on abort delete rebase state file no matter what...
r26744 if cleanup:
# Update away from the rebase if necessary
if needupdate(repo, state):
merge.update(repo, originalwd, False, True, False)
Matt Mackall
rebase: don't clobber wd on --abort when we've updated away (issue4009)
r19516
Christian Delahousse
rebase: on abort delete rebase state file no matter what...
r26744 # Strip from the first rebased revision
rebased = filter(lambda x: x >= 0 and x != target, state.values())
if rebased:
strippoints = [
c.node() for c in repo.set('roots(%ld)', rebased)]
# no backup of rebased cset versions needed
repair.strip(repo.ui, repo, strippoints)
Matt Mackall
rebase: allow aborting when descendants detected...
r19518
Christian Delahousse
rebase: on abort delete rebase state file no matter what...
r26744 if activebookmark and activebookmark in repo._bookmarks:
bookmarks.activate(repo, activebookmark)
Tony Tung
rebase: restore bookmark state on abort...
r24758
Christian Delahousse
rebase: on abort delete rebase state file no matter what...
r26744 finally:
clearstatus(repo)
repo.ui.warn(_('rebase aborted\n'))
Matt Mackall
rebase: allow aborting when descendants detected...
r19518 return 0
Stefano Tortarolo
Add rebase extension
r6906
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 def buildstate(repo, dest, rebaseset, collapse, obsoletenotrebased):
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
dest: context
rebaseset: set of rev
Pierre-Yves David
rebase: do not add second parent to rebased changeset (drop detach option) (BC)...
r17005 '''
Pierre-Yves David
rebase: ensure rebase revision remains visible (issue4504)...
r23970 _setrebasesetvisibility(repo, rebaseset)
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.
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267 if 'qtip' in repo.tags() and (dest.node() in
Benoit Boissinot
mq: avoid many hex/bin conversions, keep the binary node when possible
r10678 [s.node for s in repo.mq.applied]):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot rebase onto an applied mq patch'))
Greg Ward
rebase: always check if rebasing onto an applied mq patch....
r10672
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267 roots = list(repo.set('roots(%ld)', rebaseset))
if not roots:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no matching revisions'))
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 roots.sort()
state = {}
detachset = set()
for root in roots:
commonbase = root.ancestor(dest)
if commonbase == root:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('source is ancestor of destination'))
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 if commonbase == dest:
samebranch = root.branch() == dest.branch()
if not collapse and samebranch and root in dest.children():
repo.ui.debug('source is a child of destination\n')
return None
Stefano Tortarolo
Add rebase extension
r6906
Mads Kiilerich
rebase: fix 'rebase onto %d starting from %s' - show root instead of list repr...
r20545 repo.ui.debug('rebase onto %d starting from %s\n' % (dest, root))
Pierre-Yves David
rebase: add a 'revtodo' constant...
r23490 state.update(dict.fromkeys(rebaseset, revtodo))
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 # Rebase tries to turn <dest> into a parent of <root> while
# preserving the number of parents of rebased changesets:
#
# - A changeset with a single parent will always be rebased as a
# changeset with a single parent.
#
# - A merge will be rebased as merge unless its parents are both
# ancestors of <dest> or are themselves in the rebased set and
# pruned while rebased.
#
# If one parent of <root> is an ancestor of <dest>, the rebased
# version of this parent will be <dest>. This is always true with
# --base option.
#
# Otherwise, we need to *replace* the original parents with
# <dest>. This "detaches" the rebased set from its former location
# and rebases it onto <dest>. Changes introduced by ancestors of
# <root> not common with <dest> (the detachset, marked as
# nullmerge) are "removed" from the rebased changesets.
#
# - If <root> has a single parent, set it to <dest>.
#
# - If <root> is a merge, we cannot decide which parent to
# replace, the rebase operation is not clearly defined.
#
# The table below sums up this behavior:
#
# +------------------+----------------------+-------------------------+
# | | one parent | merge |
# +------------------+----------------------+-------------------------+
# | parent in | new parent is <dest> | parents in ::<dest> are |
# | ::<dest> | | remapped to <dest> |
# +------------------+----------------------+-------------------------+
# | unrelated source | new parent is <dest> | ambiguous, abort |
# +------------------+----------------------+-------------------------+
#
# The actual abort is handled by `defineparents`
if len(root.parents()) <= 1:
# ancestors of <root> not ancestors of <dest>
detachset.update(repo.changelog.findmissingrevs([commonbase.rev()],
[root.rev()]))
for r in detachset:
if r not in state:
state[r] = nullmerge
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 if len(roots) > 1:
# If we have multiple roots, we may have "hole" in the rebase set.
# Rebase roots that descend from those "hole" should not be detached as
# other root are. We use the special `revignored` to inform rebase that
Mads Kiilerich
spelling: fix some minor issues found by spell checker
r18644 # the revision should be ignored but that `defineparents` should search
# a rebase destination that make sense regarding rebased topology.
Pierre-Yves David
rebase: properly handle unrebased revision between rebased one...
r18447 rebasedomain = set(repo.revs('%ld::%ld', rebaseset, rebaseset))
for ignored in set(rebasedomain) - set(rebaseset):
state[ignored] = revignored
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 for r in obsoletenotrebased:
state[r] = revprecursor
Pierre-Yves David
rebase: use revset as soon as possible in internal logic...
r15267 return repo['.'].rev(), dest.rev(), state
Stefano Tortarolo
Add rebase extension
r6906
Pierre-Yves David
rebase: do not invent successor to skipped changeset...
r18444 def clearrebased(ui, repo, state, skipped, collapsedas=None):
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
`collapsedas` node."""
Durham Goode
obsolete: add createmarkers option...
r22951 if obsolete.isenabled(repo, obsolete.createmarkersopt):
Pierre-Yves David
rebase: allow creation obsolescence relation instead of stripping...
r17612 markers = []
for rev, newrev in sorted(state.items()):
if newrev >= 0:
Pierre-Yves David
rebase: do not invent successor to skipped changeset...
r18444 if rev in skipped:
succs = ()
elif collapsedas is not None:
succs = (repo[collapsedas],)
else:
succs = (repo[newrev],)
markers.append((repo[rev], succs))
Pierre-Yves David
rebase: allow creation obsolescence relation instead of stripping...
r17612 if markers:
obsolete.createmarkers(repo, markers)
else:
Pierre-Yves David
rebase: lose the comparison to `nullmerge`...
r18446 rebased = [rev for rev in state if state[rev] > nullmerge]
Pierre-Yves David
rebase: allow creation obsolescence relation instead of stripping...
r17612 if rebased:
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 stripped = []
for root in repo.set('roots(%ld)', rebased):
if set(repo.changelog.descendants([root.rev()])) - set(state):
ui.warn(_("warning: new changesets detected "
"on source branch, not stripping\n"))
else:
stripped.append(root.node())
if stripped:
Pierre-Yves David
rebase: allow creation obsolescence relation instead of stripping...
r17612 # backup the old csets by default
Pierre-Yves David
rebase: support multiple roots for rebaseset...
r18424 repair.strip(ui, repo, stripped, "all")
Pierre-Yves David
rebase: extract final changesets cleanup logic in a dedicated function...
r17611
Matt Mackall
extensions: use new wrapper functions
r7216 def pullrebase(orig, ui, repo, *args, **opts):
Stefano Tortarolo
Add rebase extension
r6906 'Call rebase after pull if the latter has been invoked with --rebase'
if opts.get('rebase'):
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 wlock = lock = None
try:
wlock = repo.wlock()
lock = repo.lock()
if opts.get('update'):
del opts['update']
ui.debug('--update and --rebase are not compatible, ignoring '
'the update flag\n')
Stefano Tortarolo
Add rebase extension
r6906
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 movemarkfrom = repo['.'].node()
revsprepull = len(repo)
origpostincoming = commands.postincoming
def _dummy(*args, **kwargs):
pass
commands.postincoming = _dummy
try:
orig(ui, repo, *args, **opts)
finally:
commands.postincoming = origpostincoming
revspostpull = len(repo)
if revspostpull > revsprepull:
# --rev option from pull conflict with rebase own --rev
# dropping it
if 'rev' in opts:
del opts['rev']
# positional argument from pull conflicts with rebase's own
# --source.
if 'source' in opts:
del opts['source']
rebase(ui, repo, **opts)
branch = repo[None].branch()
dest = repo[branch].rev()
if dest != repo['.'].rev():
# there was nothing to rebase we force an update
hg.update(repo, dest)
if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
ui.status(_("updating bookmark %s\n")
% repo._activebookmark)
Sune Foldager
rebase: improve output of hg pull --rebase (issue2072)
r10628 finally:
Pierre-Yves David
rebase: lock the repo during the full rebase operation...
r26029 release(lock, wlock)
Stefano Tortarolo
Add rebase extension
r6906 else:
Adrian Buehlmann
rebase: add option --tool/-t for 'pull --rebase'...
r14444 if opts.get('tool'):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('--tool can only be used with --rebase'))
Matt Mackall
extensions: use new wrapper functions
r7216 orig(ui, repo, *args, **opts)
Stefano Tortarolo
Add rebase extension
r6906
Pierre-Yves David
rebase: ensure rebase revision remains visible (issue4504)...
r23970 def _setrebasesetvisibility(repo, revs):
"""store the currently rebased set on the repo object
This is used by another function to prevent rebased revision to because
hidden (see issue4505)"""
repo = repo.unfiltered()
revs = set(revs)
repo._rebaseset = revs
# invalidate cache if visibility changes
hiddens = repo.filteredrevcache.get('visible', set())
if revs & hiddens:
repo.invalidatevolatilesets()
def _clearrebasesetvisibiliy(repo):
"""remove rebaseset data from the repo"""
repo = repo.unfiltered()
if '_rebaseset' in vars(repo):
del repo._rebaseset
def _rebasedvisible(orig, repo):
"""ensure rebased revs stay visible (see issue4505)"""
blockers = orig(repo)
blockers.update(getattr(repo, '_rebaseset', ()))
return blockers
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 def _computeobsoletenotrebased(repo, rebasesetrevs, dest):
"""return a mapping obsolete => successor for all obsolete nodes to be
rebased that have a successors in the destination"""
obsoletenotrebased = {}
Mads Kiilerich
spelling: trivial spell checking
r26781 # Build a mapping successor => obsolete nodes for the obsolete
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 # nodes to be rebased
allsuccessors = {}
Pierre-Yves David
rebase: use a direct reference to repo.changelog...
r26674 cl = repo.changelog
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 for r in rebasesetrevs:
n = repo[r]
if n.obsolete():
Pierre-Yves David
rebase: use a direct reference to repo.changelog...
r26674 node = cl.node(r)
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 for s in obsolete.allsuccessors(repo.obsstore, [node]):
Pierre-Yves David
rebase: properly handle chains of markers with missing nodes...
r26675 try:
allsuccessors[cl.rev(s)] = cl.rev(node)
except LookupError:
pass
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349
if allsuccessors:
# Look for successors of obsolete nodes to be rebased among
# the ancestors of dest
Pierre-Yves David
rebase: use a direct reference to repo.changelog...
r26674 ancs = cl.ancestors([repo[dest].rev()],
stoprev=min(allsuccessors),
inclusive=True)
Laurent Charignon
rebase: don't rebase obsolete commit whose successor is already rebased...
r26349 for s in allsuccessors:
if s in ancs:
obsoletenotrebased[allsuccessors[s]] = s
return obsoletenotrebased
Bryan O'Sullivan
summary: indicate if a rebase is underway
r19214 def summaryhook(ui, repo):
if not os.path.exists(repo.join('rebasestate')):
return
FUJIWARA Katsunori
rebase: catch RepoLookupError at restoring rebase state for summary...
r19849 try:
state = restorestatus(repo)[2]
except error.RepoLookupError:
# i18n: column positioning for "hg summary"
msg = _('rebase: (use "hg rebase --abort" to clear broken state)\n')
ui.write(msg)
return
Pierre-Yves David
rebase: use '>= 0' to know is a revision was rebased...
r23489 numrebased = len([i for i in state.itervalues() if i >= 0])
Bryan O'Sullivan
summary: indicate if a rebase is underway
r19214 # i18n: column positioning for "hg summary"
ui.write(_('rebase: %s, %s (rebase --continue)\n') %
(ui.label(_('%d rebased'), 'rebase.rebased') % numrebased,
ui.label(_('%d remaining'), 'rebase.remaining') %
(len(state) - numrebased)))
Stefano Tortarolo
Add rebase extension
r6906 def uisetup(ui):
Pierre-Yves David
rebase: ensure rebase revision remains visible (issue4504)...
r23970 #Replace pull with a decorator to provide --rebase option
Matt Mackall
extensions: use new wrapper functions
r7216 entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
entry[1].append(('', 'rebase', None,
Adrian Buehlmann
rebase: add option --tool/-t for 'pull --rebase'...
r14444 _("rebase working directory to branch head")))
entry[1].append(('t', 'tool', '',
_("specify merge tool for rebase")))
Bryan O'Sullivan
summary: indicate if a rebase is underway
r19214 cmdutil.summaryhooks.add('rebase', summaryhook)
Matt Mackall
rebase: add checkunfinished support (issue3955)
r19478 cmdutil.unfinishedstates.append(
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 ['rebasestate', False, False, _('rebase in progress'),
Matt Mackall
rebase: add checkunfinished support (issue3955)
r19478 _("use 'hg rebase --continue' or 'hg rebase --abort'")])
Pierre-Yves David
rebase: ensure rebase revision remains visible (issue4504)...
r23970 # ensure rebased rev are not hidden
extensions.wrapfunction(repoview, '_getdynamicblockers', _rebasedvisible)
Pierre-Yves David
rebase: rename and test '_destrebase'...
r26719 revset.symbols['_destrebase'] = _revsetdestrebase