# HG changeset patch # User Kyle Lippincott # Date 1532650263 25200 # Node ID 6c8e3c847977c296ccdf9575a003aec3ba14cf40 # Parent afb442f58cbfb7f54216ca24b42eda08cf6115e0 resolve: add option to warn/abort on -m with unresolved conflict markers When a user is dropped out of Mercurial to a terminal to resolve files, we emit messages like: conflicts while merging file1! (edit, then use 'hg resolve --mark') conflicts while merging file2! (edit, then use 'hg resolve --mark') We don't mention a file name in the hint, so some users might do something like `$EDITOR file1; hg resolve --mark`, see that it says "(no more unresolved files)" and forget to deal with file2 before running the next command. Even if we did mention a file name in the hint, it's too easy to forget it (maybe the merge spans a couple days or something). This option lets us inform the user that they might have missed something. In the scenario above, the output would be something like: warning: the following files still have conflict markers: file2 (no more unresolved files) Differential Revision: https://phab.mercurial-scm.org/D4035 diff -r afb442f58cbf -r 6c8e3c847977 mercurial/commands.py --- a/mercurial/commands.py Mon Jul 02 18:39:48 2018 -0700 +++ b/mercurial/commands.py Thu Jul 26 17:11:03 2018 -0700 @@ -35,6 +35,7 @@ error, exchange, extensions, + filemerge, formatter, graphmod, hbisect, @@ -4594,6 +4595,9 @@ runconclude = False tocomplete = [] + hasconflictmarkers = [] + if mark: + markcheck = ui.config('experimental', 'resolve.mark-check') for f in ms: if not m(f): continue @@ -4629,6 +4633,12 @@ continue if mark: + if markcheck: + with repo.wvfs(f) as fobj: + fdata = fobj.read() + if filemerge.hasconflictmarkers(fdata) and \ + ms[f] != mergemod.MERGE_RECORD_RESOLVED: + hasconflictmarkers.append(f) ms.mark(f, mergemod.MERGE_RECORD_RESOLVED) elif unmark: ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED) @@ -4663,6 +4673,13 @@ if inst.errno != errno.ENOENT: raise + if hasconflictmarkers: + ui.warn(_('warning: the following files still have conflict ' + 'markers:\n ') + '\n '.join(hasconflictmarkers) + '\n') + if markcheck == 'abort' and not all: + raise error.Abort(_('conflict markers detected'), + hint=_('use --all to mark anyway')) + for f in tocomplete: try: # resolve file diff -r afb442f58cbf -r 6c8e3c847977 mercurial/configitems.py --- a/mercurial/configitems.py Mon Jul 02 18:39:48 2018 -0700 +++ b/mercurial/configitems.py Thu Jul 26 17:11:03 2018 -0700 @@ -931,6 +931,9 @@ default=True, alias=[('format', 'aggressivemergedeltas')], ) +coreconfigitem('experimental', 'resolve.mark-check', + default=None, +) coreconfigitem('server', 'bookmarks-pushkey-compat', default=True, ) diff -r afb442f58cbf -r 6c8e3c847977 mercurial/filemerge.py --- a/mercurial/filemerge.py Mon Jul 02 18:39:48 2018 -0700 +++ b/mercurial/filemerge.py Thu Jul 26 17:11:03 2018 -0700 @@ -916,14 +916,17 @@ _haltmerge() # default action is 'continue', in which case we neither prompt nor halt +def hasconflictmarkers(data): + return bool(re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", data, + re.MULTILINE)) + def _check(repo, r, ui, tool, fcd, files): fd = fcd.path() unused, unused, unused, back = files if not r and (_toolbool(ui, tool, "checkconflicts") or 'conflicts' in _toollist(ui, tool, "check")): - if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(), - re.MULTILINE): + if hasconflictmarkers(fcd.data()): r = 1 checked = False diff -r afb442f58cbf -r 6c8e3c847977 tests/test-resolve.t --- a/tests/test-resolve.t Mon Jul 02 18:39:48 2018 -0700 +++ b/tests/test-resolve.t Thu Jul 26 17:11:03 2018 -0700 @@ -373,4 +373,53 @@ $ hg resolve -l +resolve -m can be configured to look for remaining conflict markers + $ hg up -qC 2 + $ hg merge -q --tool=internal:merge 1 + warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') + warning: conflicts while merging file2! (edit, then use 'hg resolve --mark') + [1] + $ hg resolve -l + U file1 + U file2 + $ echo 'remove markers' > file1 + $ hg --config experimental.resolve.mark-check=abort resolve -m + warning: the following files still have conflict markers: + file2 + abort: conflict markers detected + (use --all to mark anyway) + [255] + $ hg resolve -l + U file1 + U file2 +Try with --all from the hint + $ hg --config experimental.resolve.mark-check=abort resolve -m --all + warning: the following files still have conflict markers: + file2 + (no more unresolved files) + $ hg resolve -l + R file1 + R file2 + $ hg resolve --unmark + $ hg resolve -l + U file1 + U file2 + $ hg --config experimental.resolve.mark-check=warn resolve -m + warning: the following files still have conflict markers: + file2 + (no more unresolved files) + $ hg resolve -l + R file1 + R file2 +If the file is already marked as resolved, we don't warn about it + $ hg resolve --unmark file1 + $ hg resolve -l + U file1 + R file2 + $ hg --config experimental.resolve.mark-check=warn resolve -m + (no more unresolved files) + $ hg resolve -l + R file1 + R file2 + $ cd ..