diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -69,11 +69,12 @@ def _makeextrafn(copiers): c(ctx, extra) return extrafn -def _destrebase(repo): - # Destination defaults to the latest revision in the - # current branch - branch = repo[None].branch() - return repo[branch].rev() +def _destrebase(repo, sourceset): + """small wrapper around destmerge to pass the right extra args + + Please wrap destutil.destmerge instead.""" + return destutil.destmerge(repo, action='rebase', sourceset=sourceset, + onheadcheck=False) revsetpredicate = revset.extpredicate() @@ -83,12 +84,12 @@ def _revsetdestrebase(repo, subset, x): # 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")) - return subset & revset.baseset([_destrebase(repo)]) + sourceset = None + if x is not None: + sourceset = revset.getset(repo, revset.fullreposet(repo), x) + return subset & revset.baseset([_destrebase(repo, sourceset)]) @command('rebase', [('s', 'source', '', @@ -127,10 +128,13 @@ def rebase(ui, repo, **opts): Published commits cannot be rebased (see :hg:`help phases`). To copy commits, see :hg:`help graft`. - If you don't specify a destination changeset (``-d/--dest``), - 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.) + 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.) Here are the ways to select changesets: @@ -544,9 +548,6 @@ def _definesets(ui, repo, destf=None, sr if destf: dest = scmutil.revsingle(repo, destf) - else: - dest = repo[_destrebase(repo)] - destf = str(dest) if revf: rebaseset = scmutil.revrange(repo, revf) @@ -566,6 +567,10 @@ def _definesets(ui, repo, destf=None, sr ui.status(_('empty "base" revision set - ' "can't compute rebase set\n")) return None, None + if not destf: + dest = repo[_destrebase(repo, base)] + destf = str(dest) + commonanc = repo.revs('ancestor(%ld, %d)', base, dest).first() if commonanc is not None: rebaseset = repo.revs('(%d::(%ld) - %d)::', @@ -599,6 +604,11 @@ def _definesets(ui, repo, destf=None, sr ui.status(_('nothing to rebase from %s to %s\n') % ('+'.join(str(repo[r]) for r in base), dest)) return None, None + + if not destf: + dest = repo[_destrebase(repo, rebaseset)] + destf = str(dest) + return dest, rebaseset def externalparent(repo, state, targetancestors): @@ -1198,9 +1208,15 @@ def pullrebase(orig, ui, repo, *args, ** # --source. if 'source' in opts: del opts['source'] - if rebase(ui, repo, **opts) == _nothingtorebase(): + try: + rebase(ui, repo, **opts) + except error.NoMergeDestAbort: + # we can maybe update instead rev, _a, _b = destutil.destupdate(repo) - if rev != repo['.'].rev(): # we could update + if rev == repo['.'].rev(): + ui.status(_('nothing to rebase\n')) + else: + ui.status(_('nothing to rebase - updating instead\n')) # not passing argument to get the bare update behavior # with warning and trumpets commands.update(ui, repo) diff --git a/mercurial/destutil.py b/mercurial/destutil.py --- a/mercurial/destutil.py +++ b/mercurial/destutil.py @@ -141,6 +141,10 @@ msgdestmerge = { (_("multiple matching bookmarks to merge -" " please merge with an explicit rev or bookmark"), _("run 'hg heads' to see all heads")), + 'rebase': + (_("multiple matching bookmarks to rebase -" + " please rebase to an explicit rev or bookmark"), + _("run 'hg heads' to see all heads")), }, # no other matching divergent bookmark 'nootherbookmarks': @@ -148,52 +152,80 @@ msgdestmerge = { (_("no matching bookmark to merge - " "please merge with an explicit rev or bookmark"), _("run 'hg heads' to see all heads")), + 'rebase': + (_("no matching bookmark to rebase - " + "please rebase to an explicit rev or bookmark"), + _("run 'hg heads' to see all heads")), }, # branch have too many unbookmarked heads, no obvious destination 'toomanyheads': {'merge': (_("branch '%s' has %d heads - please merge with an explicit rev"), _("run 'hg heads .' to see heads")), + 'rebase': + (_("branch '%s' has %d heads - please rebase to an explicit rev"), + _("run 'hg heads .' to see heads")), }, # branch have no other unbookmarked heads 'bookmarkedheads': {'merge': (_("heads are bookmarked - please merge with an explicit rev"), _("run 'hg heads' to see all heads")), + 'rebase': + (_("heads are bookmarked - please rebase to an explicit rev"), + _("run 'hg heads' to see all heads")), }, # branch have just a single heads, but there is other branches 'nootherbranchheads': {'merge': (_("branch '%s' has one head - please merge with an explicit rev"), _("run 'hg heads' to see all heads")), + 'rebase': + (_("branch '%s' has one head - please rebase to an explicit rev"), + _("run 'hg heads' to see all heads")), }, # repository have a single head 'nootherheads': - {'merge': - (_('nothing to merge'), - None), + {'merge': + (_('nothing to merge'), + None), + 'rebase': + (_('nothing to rebase'), + None), }, # repository have a single head and we are not on it 'nootherheadsbehind': {'merge': (_('nothing to merge'), _("use 'hg update' instead")), + 'rebase': + (_('nothing to rebase'), + _("use 'hg update' instead")), }, # We are not on a head 'notatheads': {'merge': (_('working directory not at a head revision'), - _("use 'hg update' or merge with an explicit revision")) + _("use 'hg update' or merge with an explicit revision")), + 'rebase': + (_('working directory not at a head revision'), + _("use 'hg update' or rebase to an explicit revision")) }, 'emptysourceset': {'merge': (_('source set is empty'), - None) + None), + 'rebase': + (_('source set is empty'), + None), }, 'multiplebranchessourceset': {'merge': (_('source set is rooted in multiple branches'), - None) + None), + 'rebase': + (_('rebaseset is rooted in multiple named branches'), + _('specify an explicit destination with --dest')), }, } diff --git a/tests/test-largefiles-misc.t b/tests/test-largefiles-misc.t --- a/tests/test-largefiles-misc.t +++ b/tests/test-largefiles-misc.t @@ -1095,7 +1095,7 @@ Test "pull --rebase" when rebase is enab adding manifests adding file changes added 1 changesets with 1 changes to 1 files - nothing to rebase - working directory parent is already an ancestor of destination bf5e395ced2c + nothing to rebase - updating instead 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd .. diff --git a/tests/test-rebase-named-branches.t b/tests/test-rebase-named-branches.t --- a/tests/test-rebase-named-branches.t +++ b/tests/test-rebase-named-branches.t @@ -327,14 +327,13 @@ rebase 'b2' to another lower branch head $ hg up -qr 2 $ hg rebase - nothing to rebase - working directory parent is also destination - [1] + rebasing 2:792845bb77ee "b2" + note: rebase of 2:792845bb77ee created no changes to commit + saved backup bundle to $TESTTMP/case1/.hg/strip-backup/792845bb77ee-627120ee-backup.hg (glob) $ hg tglog - o 3: 'c1' c + o 2: 'c1' c | - | @ 2: 'b2' b - |/ - | o 1: 'b1' b + | @ 1: 'b1' b |/ o 0: '0' @@ -373,8 +372,9 @@ rebase 'c1' to the branch head 'c2' that o 0: '0' $ hg rebase - nothing to rebase - working directory parent is also destination - [1] + abort: branch 'c' has one head - please rebase to an explicit rev + (run 'hg heads' to see all heads) + [255] $ hg tglog _ 4: 'c2 closed' c | diff --git a/tests/test-rebase-pull.t b/tests/test-rebase-pull.t --- a/tests/test-rebase-pull.t +++ b/tests/test-rebase-pull.t @@ -85,7 +85,7 @@ Invoke pull --rebase and nothing to reba adding manifests adding file changes added 1 changesets with 1 changes to 1 files - nothing to rebase - working directory parent is already an ancestor of destination 77ae9631bcca + nothing to rebase - updating instead 1 files updated, 0 files merged, 0 files removed, 0 files unresolved updating bookmark norebase @@ -285,7 +285,7 @@ pull --rebase update (no rebase) use pro adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) - nothing to rebase - working directory parent is already an ancestor of destination 65bc164c1d9b + nothing to rebase - updating instead 1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1 other heads for branch "default" $ hg tglog diff --git a/tests/test-rebase-scenario-global.t b/tests/test-rebase-scenario-global.t --- a/tests/test-rebase-scenario-global.t +++ b/tests/test-rebase-scenario-global.t @@ -818,13 +818,17 @@ Testing from lower head Testing from upper head + $ hg log -r '_destrebase(4)' + changeset: 3:1910d5ff34ea + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: second source with subdir + $ hg up 4 1 files updated, 0 files merged, 2 files removed, 0 files unresolved $ hg log -r '_destrebase()' - changeset: 4:5f7bc9025ed2 - tag: tip - parent: 1:58d79cc1cf43 + changeset: 3:1910d5ff34ea user: test date: Thu Jan 01 00:00:00 1970 +0000 - summary: aaa + summary: second source with subdir