diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -20,7 +20,7 @@ import merge as mergemod import minirst, revset, fileset import dagparser, context, simplemerge, graphmod, copies import random, operator -import setdiscovery, treediscovery, dagutil, pvec, localrepo +import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil import phases, obsolete, exchange, bundle2, repair, lock as lockmod import ui as uimod @@ -6597,6 +6597,8 @@ def update(ui, repo, node=None, rev=None cmdutil.bailifchanged(repo, merge=False) if rev is None: rev = repo[repo[None].branch()].rev() + elif rev is None: + rev = destutil.destupdate(repo, clean=clean) repo.ui.setconfig('ui', 'forcemerge', tool, 'update') diff --git a/mercurial/destutil.py b/mercurial/destutil.py --- a/mercurial/destutil.py +++ b/mercurial/destutil.py @@ -11,7 +11,7 @@ from . import ( obsolete, ) -def destupdate(repo): +def destupdate(repo, clean=False): """destination for bare update operation """ # Here is where we should consider bookmarks, divergent bookmarks, and tip @@ -52,4 +52,28 @@ def destupdate(repo): # get the max revision for the given successors set, # i.e. the 'tip' of a set node = repo.revs('max(%ln)', successors).first() - return repo[node].rev() + rev = repo[node].rev() + + if not clean: + # Check that the update is linear. + # + # Mercurial do not allow update-merge for non linear pattern + # (that would be technically possible but was considered too confusing + # for user a long time ago) + # + # See mercurial.merge.update for details + if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True): + dirty = wc.dirty(missing=True) + foreground = obsolete.foreground(repo, [p1.node()]) + if not repo[rev].node() in foreground: + if dirty: + msg = _("uncommitted changes") + hint = _("commit and merge, or update --clean to" + " discard changes") + raise error.Abort(msg, hint=hint) + else: # destination is not a descendant. + msg = _("not a linear update") + hint = _("merge or update --check to force update") + raise error.Abort(msg, hint=hint) + + return rev