# HG changeset patch # User Steve Borho # Date 2010-10-20 03:33:52 # Node ID de793925862eeb9df97941f5699d6ab789f92736 # Parent 763be3cd084a04022e62a613bba5b6a4d9767291 merge: implement --tool arguments using new ui.forcemerge configurable ui.forcemerge is set before calling into merge or resolve commands, then unset to prevent ui pollution for further operations. ui.forcemerge takes precedence over HGMERGE, but mimics HGMERGE behavior if the given --tool is not found by the merge-tools machinery. This makes it possible to do: hg resolve --tool="python mymerge.py" FILE With this approach, HGMERGE and ui.merge are not harmed by --tool diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2586,12 +2586,6 @@ def merge(ui, repo, node=None, **opts): if not node: node = opts.get('rev') - t = opts.get('tool') - if t: - if 'HGMERGE' in os.environ: - os.environ['HGMERGE'] = '' - ui.setconfig('ui', 'merge', t) - if not node: branch = repo.changectx(None).branch() bheads = repo.branchheads(branch) @@ -2632,7 +2626,12 @@ def merge(ui, repo, node=None, **opts): displayer.close() return 0 - return hg.merge(repo, node, force=opts.get('force')) + try: + # ui.forcemerge is an internal variable, do not document + ui.setconfig('ui', 'forcemerge', opts.get('tool', '')) + return hg.merge(repo, node, force=opts.get('force')) + finally: + ui.setconfig('ui', 'forcemerge', '') def outgoing(ui, repo, dest=None, **opts): """show changesets not found in the destination @@ -2979,12 +2978,6 @@ def resolve(ui, repo, *pats, **opts): raise util.Abort(_('no files or directories specified; ' 'use --all to remerge all files')) - t = opts.get('tool') - if t: - if 'HGMERGE' in os.environ: - os.environ['HGMERGE'] = '' - ui.setconfig('ui', 'merge', t) - ms = mergemod.mergestate(repo) m = cmdutil.match(repo, pats, opts) ret = 0 @@ -3010,9 +3003,13 @@ def resolve(ui, repo, *pats, **opts): a = repo.wjoin(f) util.copyfile(a, a + ".resolve") - # resolve file - if ms.resolve(f, wctx, mctx): - ret = 1 + try: + # resolve file + ui.setconfig('ui', 'forcemerge', opts.get('tool', '')) + if ms.resolve(f, wctx, mctx): + ret = 1 + finally: + ui.setconfig('ui', 'forcemerge', '') # replace filemerge's .orig file with our resolve file util.rename(a + ".resolve", a + ".orig") diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -54,7 +54,17 @@ def _picktool(repo, ui, path, binary, sy return True return False - # HGMERGE takes precedence + # forcemerge comes from command line arguments, highest priority + force = ui.config('ui', 'forcemerge') + if force: + toolpath = _findtool(ui, force) + if toolpath: + return (force, '"' + toolpath + '"') + else: + # mimic HGMERGE if given tool not found + return (force, force) + + # HGMERGE takes next precedence hgmerge = os.environ.get("HGMERGE") if hgmerge: return (hgmerge, hgmerge) diff --git a/tests/test-merge-symlinks.t b/tests/test-merge-symlinks.t --- a/tests/test-merge-symlinks.t +++ b/tests/test-merge-symlinks.t @@ -37,7 +37,7 @@ a file, once as a link. Bundle was gener Merge them and display *_ISLINK vars merge heads - $ HGMERGE="python ../echo.py" hg merge + $ hg merge --tool="python ../echo.py" HG_FILE l HG_MY_ISLINK 1 HG_OTHER_ISLINK 0 diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t --- a/tests/test-merge-tools.t +++ b/tests/test-merge-tools.t @@ -506,6 +506,49 @@ Premerge $ echo +ui.merge specifies internal:other but is overruled by --tool=false + + $ domerge -r 2 --config ui.merge=internal:other --tool=false + [merge-tools] + false.whatever= + true.priority=1 + true.executable=cat + # hg update -C 1 + # hg merge -r 2 --config ui.merge=internal:other --tool=false + merging f + merging f failed! + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + # cat f + revision 1 + space + # hg stat + M f + ? f.orig + +HGMERGE specifies internal:other but is overruled by --tool=false + + $ HGMERGE=internal:other ; export HGMERGE + $ domerge -r 2 --tool=false + [merge-tools] + false.whatever= + true.priority=1 + true.executable=cat + # hg update -C 1 + # hg merge -r 2 --tool=false + merging f + merging f failed! + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + # cat f + revision 1 + space + # hg stat + M f + ? f.orig + + $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests + Default is silent simplemerge: $ domerge -r 3 diff --git a/tests/test-rename-merge2.t b/tests/test-rename-merge2.t --- a/tests/test-rename-merge2.t +++ b/tests/test-rename-merge2.t @@ -7,7 +7,6 @@ > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3])) > f.close() > EOF - $ HGMERGE="python ../merge"; export HGMERGE perform a test merge with possible renaming args: @@ -49,7 +48,7 @@ args: > echo "--------------" > echo "test L:$1 R:$2 W:$3 - $4" > echo "--------------" - > hg merge -y --debug --traceback + > hg merge -y --debug --traceback --tool="python ../merge" > > echo "--------------" > hg status -camC -X rev diff --git a/tests/test-resolve.t b/tests/test-resolve.t --- a/tests/test-resolve.t +++ b/tests/test-resolve.t @@ -21,7 +21,7 @@ create a second head failing merge - $ HGMERGE=internal:fail hg merge + $ hg merge --tool=internal:fail 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1]