diff --git a/hgext/rebase.py b/hgext/rebase.py index ef677c81ac..6fc98a755b 100644 --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -528,18 +528,33 @@ class rebaseruntime(object): # and re-run as an on-disk merge. clearstatus(repo) mergemod.mergestate.clean(repo) + + # internal config: merge.numconflictpaths + numconfictpaths = ui.config("merge", "numconflictpaths", 3) + if len(e.paths) > numconfictpaths > 0: + pathstr = ", ".join( + e.paths[0:numconfictpaths] + ) + ", and %d more" % (len(e.paths) - numconfictpaths) + else: + pathstr = ", ".join(e.paths) + + if e.type == error.InMemoryMergeConflictsError.TYPE_FILE_CONFLICTS: + kindstr = _("hit merge conflicts") + else: + kindstr = _("artifact rebuild required") + if cmdutil.uncommittedchanges(repo): raise error.UncommitedChangesAbort( _( - "must use on-disk merge for this rebase (%s), but you have working copy changes" + "must use on-disk merge for this rebase (%s in %s), but you have working copy changes" ) - % e, + % (kindstr, pathstr), hint=_("commit, revert, or shelve them"), ) else: ui.warn( - _("hit merge conflicts; switching to on-disk merge (%s)\n") - % e + _("%s (in %s); switching to on-disk merge\n") + % (kindstr, pathstr) ) ui.log( "rebase", diff --git a/mercurial/error.py b/mercurial/error.py index 9b1f30a25e..3ce99874e7 100644 --- a/mercurial/error.py +++ b/mercurial/error.py @@ -416,6 +416,19 @@ class PeerTransportError(Abort): class InMemoryMergeConflictsError(Exception): """Exception raised when merge conflicts arose during an in-memory merge.""" + TYPE_FILE_CONFLICTS = 1 + TYPE_MERGEDRIVER = 2 + + def __init__(self, msg, type, paths): + """ + :param type: TYPE_FILE_CONFLICTS or TYPE_MERGEDRIVER_RUN + :param paths: The affected paths (for file conflicts, just the first) + """ + self.type = type + self.paths = paths + + Exception.__init__(self, msg) + __bytes__ = _tobytes diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py index 0e8a841d10..69ce58878c 100644 --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -274,7 +274,9 @@ def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf, labels=None): # conflicts. if fcd.changectx().isinmemory(): raise error.InMemoryMergeConflictsError( - "in-memory merge does not support file conflicts" + "in-memory merge does not support file conflicts", + type=error.InMemoryMergeConflictsError.TYPE_FILE_CONFLICTS, + paths=[fcd.path()], ) prompts = partextras(labels) @@ -535,7 +537,9 @@ def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): if isinstance(fcd, context.overlayworkingfilectx): raise error.InMemoryMergeConflictsError( - "in-memory merge does not " "support the :dump tool." + "in-memory merge does not support the :dump tool.", + type=error.InMemoryMergeConflictsError.TYPE_FILE_CONFLICTS, + paths=[fcd.path()], ) util.writefile(a + ".local", fcd.decodeddata()) @@ -562,7 +566,9 @@ def _xmergeimm(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): # directory and tell the user how to get it is my best idea, but it's # clunky.) raise error.InMemoryMergeConflictsError( - "in-memory merge does not support " "external merge tools" + "in-memory merge does not support external merge tools", + type=error.InMemoryMergeConflictsError.TYPE_FILE_CONFLICTS, + paths=[fcd.path()], ) @@ -821,7 +827,9 @@ def _filemerge(premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None): if onfailure: if wctx.isinmemory(): raise error.InMemoryMergeConflictsError( - "in-memory merge does " "not support merge " "conflicts" + "in-memory merge does not support merge conflicts", + type=error.InMemoryMergeConflictsError.TYPE_FILE_CONFLICTS, + paths=[fcd.path()], ) ui.warn(onfailure % relfd) return True, 1, False @@ -852,7 +860,9 @@ def _filemerge(premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None): if onfailure: if wctx.isinmemory(): raise error.InMemoryMergeConflictsError( - "in-memory merge " "does not support " "merge conflicts" + "in-memory merge does not support merge conflicts", + type=error.InMemoryMergeConflictsError.TYPE_FILE_CONFLICTS, + paths=[fcd.path()], ) ui.warn(onfailure % relfd) _onfilemergefailure(ui) diff --git a/mercurial/merge.py b/mercurial/merge.py index a743ff82f3..7dd244dd95 100644 --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -1684,7 +1684,11 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None): "some of your files require mergedriver to run, " "which in-memory merge does not support" ) - raise error.InMemoryMergeConflictsError(errorstr) + raise error.InMemoryMergeConflictsError( + errorstr, + type=error.InMemoryMergeConflictsError.TYPE_MERGEDRIVER, + paths=driverresolved, + ) # the driver might leave some files unresolved unresolvedf = set(ms.unresolved()) diff --git a/tests/test-rebase-inmemory-conflicts.t b/tests/test-rebase-inmemory-conflicts.t index a54555ae0d..391fc5b771 100644 --- a/tests/test-rebase-inmemory-conflicts.t +++ b/tests/test-rebase-inmemory-conflicts.t @@ -49,7 +49,7 @@ Make conflicts halfway up the stack: rebasing 4:881eb15e0fdf "e" (e) rebasing 5:e692c3b32196 "f" merging c - hit merge conflicts; switching to on-disk merge (in-memory merge does not support merge conflicts) + hit merge conflicts (in c); switching to on-disk merge rebasing 5:e692c3b32196 "f" merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') @@ -91,7 +91,7 @@ Try it with uncommitted changes, ensure it aborts nicely: rebasing 5:c33e7f678afd "f" transaction abort! rollback completed - abort: must use on-disk merge for this rebase (in-memory merge does not support file conflicts), but you have working copy changes + abort: must use on-disk merge for this rebase (hit merge conflicts in c), but you have working copy changes (commit, revert, or shelve them) [255] $ hg st diff --git a/tests/test-rebase-inmemory-mergedriver.t b/tests/test-rebase-inmemory-mergedriver.t index 41c83666d6..9d95c96a57 100644 --- a/tests/test-rebase-inmemory-mergedriver.t +++ b/tests/test-rebase-inmemory-mergedriver.t @@ -90,7 +90,7 @@ we expect to see "generators version = NEW". rebasing 2:* "prefix FILE with 0" (base_1 tip) (glob) generators version = BASE base's someFunction() called - hit merge conflicts; switching to on-disk merge (some of your files require mergedriver to run, which in-memory merge does not support) + artifact rebuild required (in FILE); switching to on-disk merge rebasing 2:* "prefix FILE with 0" (base_1 tip) (glob) generators version = NEW new_required_arg = new_required diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t index 7cd698aba0..cc4d51d01a 100644 --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -205,7 +205,7 @@ Rerun with merge conflicts, demonstrating switching to on-disk merge: $ hg rebase -r 3 -d 4 rebasing 3:844a7de3e617 "c" merging c - hit merge conflicts; switching to on-disk merge (in-memory merge does not support merge conflicts) + hit merge conflicts (in c); switching to on-disk merge rebasing 3:844a7de3e617 "c" merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark')