annotate mercurial/filemerge.py @ 22022:2ea6d906cf9b

merge: use no-minimal for premerge too ecc1387138ba disabled minimal for `internal:merge` but forgot to also disabled it for premerge. This is now done. This gives me an occasion to shamelessly includes my explanation of why this minimisation feature must disappear: [this is why it's pointless to reject patches with misspellings in the description - mpm] Detailled explanation ===================== The ``simplemerge`` code use in ``internal:merge`` has a feature called "minimization". It reprocess conflicting chunks to find common changes inside them and excludes such common sections from the marker. This approach seems a significant win at first glance but produces very confusing results in some other cases. Simple example -------------- A simple example is enough to show the benefit of this feature. In this merge, both sides change all numbers from letters to digits, but one side is also changing some values. $ cat << EOF > base > Small Mathematical Series. > One > Two > Three > Four > Five > Hop we are done. > EOF $ cat << EOF > local > Small Mathematical Series. > 1 > 2 > 3 > 4 > 5 > Hop we are done. > EOF $ cat << EOF > other > Small Mathematical Series. > 1 > 2 > 3 > 6 > 8 > Hop we are done. > EOF In the minimalists case, the markers focus on the disagreement between the two sides. $ $TESTDIR/../contrib/simplemerge --print local base other Small Mathematical Series. 1 2 3 <<<<<<< local 4 5 ======= 6 8 >>>>>>> other Hop we are done. warning: conflicts during merge. [1] In the non minimalist case, the whole chunk is included in the conflict marker. Making it harder spot actual differences. $ $TESTDIR/../contrib/simplemerge --print --no-minimal local base other Small Mathematical Series. <<<<<<< local 1 2 3 4 5 ======= 1 2 3 6 8 >>>>>>> other Hop we are done. warning: conflicts during merge. [1] Practical Advantages of minimalisation: merge of grafted change --------------------------------------------------------------- This feature can be very useful when a change have been grafted in another branch and then some change have been made to the grafted code. $ cat << EOF > base > # empty file > EOF $ cat << EOF > local > def somefunction(one, two): > some = one > stuff = two > are(happening) > here() > EOF $ cat << EOF > other > def somefunction(one, two): > some = one > change = two > are(happening) > here() > EOF The minimalist case recognises the grafted content as similar and highlight the actual change. $ $TESTDIR/../contrib/simplemerge --print local base other def somefunction(one, two): some = one <<<<<<< local stuff = two ======= change = two >>>>>>> other are(happening) here() warning: conflicts during merge. [1] Again, the non-minimalist case produces a larger conflict. Making it harder to spot the actual conflict. $ $TESTDIR/../contrib/simplemerge --print --no-minimal local base other <<<<<<< local def somefunction(one, two): some = one stuff = two are(happening) here() ======= def somefunction(one, two): some = one change = two are(happening) here() >>>>>>> other warning: conflicts during merge. [1] Practical disadvantage: multiple functions on each side --------------------------------------------------------------- So, if this "minimalist" help so much, why introduce a setting to disable it? The issue is that this minimisation will grab any common lines for breaking chunks. This may result in partial context when solving a merge. The most simple example is a merge where both side added some (different) functions separated by blank lines. The "minimalist" approach will recognise the blank line as "common" and over slice the chunks, turning a simple conflict case into multiple pairs of conflicting functions. $ cat << EOF > base > # empty file > EOF $ cat << EOF > local > def function1(): > bla() > bla() > bla() > > def function2(): > ble() > ble() > ble() > EOF $ cat << EOF > other > def function3(): > bli() > bli() > bli() > > def function4(): > blo() > blo() > blo() > EOF The minimal case presents each function as a separated context. $ $TESTDIR/../contrib/simplemerge --print local base other <<<<<<< local def function1(): bla() bla() bla() ======= def function3(): bli() bli() bli() >>>>>>> other <<<<<<< local def function2(): ble() ble() ble() ======= def function4(): blo() blo() blo() >>>>>>> other warning: conflicts during merge. [1] The non-minimalist approach produces a simpler version with more context in each block. Solving such conflicts is usually as simple as dropping the 3 lines dedicated to markers. $ $TESTDIR/../contrib/simplemerge --prin --no-minimal local base other <<<<<<< local def function1(): bla() bla() bla() def function2(): ble() ble() ble() ======= def function3(): bli() bli() bli() def function4(): blo() blo() blo() >>>>>>> other warning: conflicts during merge. [1] Practical disaster: programing language have a lot of common line ================================================================= If only blank lines between function where the only frequent content of a code file. But programming language tend to repeat them self much more often. In that case, the minimalist approach turns a simple conflict into a massive mess. Consider this example where two unrelated functions are added on each side. Those function shares common programming constructs by chance. $ cat << EOF > base > # empty file > EOF $ cat << EOF > local > def longfunction(): > if bla: > foo > else: > bar > try: > ret = some stuff > except Exception: > ret = None > if ret is not None: > return ret > return 0 > > def shortfunction(foo): > goo() > ret = foo + 5 > return ret > EOF $ cat << EOF > other > def otherlongfunction(): > for x in xxx: > if coin: > break > tutu > else: > bar() > baz() > ret = week() > try: > groumpf = tutu > fool() > except Exception: > zoo() > pool() > if cond: > return ret > > # some big block > ret ** 6 > koin() > return ret > EOF The minimalist approach will hash the whole conflict into small chunks that does not match any meaningful semantic and are impossible to solve. $ $TESTDIR/../contrib/simplemerge --print local base other <<<<<<< local def longfunction(): if bla: foo ======= def otherlongfunction(): for x in xxx: if coin: break tutu >>>>>>> other else: <<<<<<< local bar ======= bar() baz() ret = week() >>>>>>> other try: <<<<<<< local ret = some stuff ======= groumpf = tutu fool() >>>>>>> other except Exception: <<<<<<< local ret = None if ret is not None: ======= zoo() pool() if cond: >>>>>>> other return ret <<<<<<< local return 0 ======= >>>>>>> other <<<<<<< local def shortfunction(foo): goo() ret = foo + 5 ======= # some big block ret ** 6 koin() >>>>>>> other return ret warning: conflicts during merge. [1] The non minimalist approach will properly produce a single set of conflict markers. Highlighting that the two chunk are unrelated. Such conflict from unrelated content added at the same place is usually solved by dropping the marker an keeping both content. Something impossible with minimised markers. $ $TESTDIR/../contrib/simplemerge --prin --no-minimal local base other <<<<<<< local def longfunction(): if bla: foo else: bar try: ret = some stuff except Exception: ret = None if ret is not None: return ret return 0 def shortfunction(foo): goo() ret = foo + 5 return ret ======= def otherlongfunction(): for x in xxx: if coin: break tutu else: bar() baz() ret = week() try: groumpf = tutu fool() except Exception: zoo() pool() if cond: return ret # some big block ret ** 6 koin() return ret >>>>>>> other warning: conflicts during merge. [1]
author Pierre-Yves David <pierre-yves.david@fb.com>
date Tue, 29 Jul 2014 11:55:01 -0700
parents e9801c7b6ff0
children f18830651811
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 # filemerge.py - file-level merge handling for Mercurial
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9709
diff changeset
6 # GNU General Public License version 2 or any later version.
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7
7873
4a4c7f6a5912 cleanup: drop unused imports
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7397
diff changeset
8 from node import short
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
9 from i18n import _
21519
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
10 import util, simplemerge, match, error, templater, templatekw
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8269
diff changeset
11 import os, tempfile, re, filecmp
21922
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
12 import tagmerge
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
13
6013
bb441d77df99 filemerge: handle missing regappend
Matt Mackall <mpm@selenic.com>
parents: 6007
diff changeset
14 def _toolstr(ui, tool, part, default=""):
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
15 return ui.config("merge-tools", tool + "." + part, default)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
16
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
17 def _toolbool(ui, tool, part, default=False):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
18 return ui.configbool("merge-tools", tool + "." + part, default)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
19
11148
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
20 def _toollist(ui, tool, part, default=[]):
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
21 return ui.configlist("merge-tools", tool + "." + part, default)
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
22
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
23 internals = {}
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
24
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
25 def internaltool(name, trymerge, onfailure=None):
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
26 '''return a decorator for populating internal merge tool table'''
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
27 def decorator(func):
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
28 fullname = 'internal:' + name
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
29 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
30 internals[fullname] = func
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
31 func.trymerge = trymerge
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
32 func.onfailure = onfailure
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
33 return func
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
34 return decorator
8830
a9850eda2973 filemerge: add internal:prompt target
Matt Mackall <mpm@selenic.com>
parents: 8615
diff changeset
35
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
36 def _findtool(ui, tool):
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
37 if tool in internals:
6522
2b181fb3a70a use internal merge tool when specified for a merge-pattern in hgrc
Dov Feldstern <dfeldstern@fastimap.com>
parents: 6212
diff changeset
38 return tool
13565
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
39 for kn in ("regkey", "regkeyalt"):
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
40 k = _toolstr(ui, tool, kn)
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
41 if not k:
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
42 continue
14230
d51630301241 rename util.lookup_reg to lookupreg
Adrian Buehlmann <adrian@cadifra.com>
parents: 14168
diff changeset
43 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
6006
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
44 if p:
14271
4030630fb59c rename util.find_exe to findexe
Adrian Buehlmann <adrian@cadifra.com>
parents: 14230
diff changeset
45 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
6006
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
46 if p:
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
47 return p
15264
157d93c41c10 merge: expand environment variables and ~/ in tool.executable
Greg Ward <greg@gerg.ca>
parents: 14749
diff changeset
48 exe = _toolstr(ui, tool, "executable", tool)
157d93c41c10 merge: expand environment variables and ~/ in tool.executable
Greg Ward <greg@gerg.ca>
parents: 14749
diff changeset
49 return util.findexe(util.expandpath(exe))
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
50
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
51 def _picktool(repo, ui, path, binary, symlink):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
52 def check(tool, pat, symlink, binary):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
53 tmsg = tool
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
54 if pat:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
55 tmsg += " specified for " + pat
7397
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
56 if not _findtool(ui, tool):
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
57 if pat: # explicitly requested tool deserves a warning
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
58 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
59 else: # configured but non-existing tools are more silent
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
60 ui.note(_("couldn't find merge tool %s\n") % tmsg)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
61 elif symlink and not _toolbool(ui, tool, "symlink"):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
62 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
63 elif binary and not _toolbool(ui, tool, "binary"):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
64 ui.warn(_("tool %s can't handle binary\n") % tmsg)
6007
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
65 elif not util.gui() and _toolbool(ui, tool, "gui"):
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
66 ui.warn(_("tool %s requires a GUI\n") % tmsg)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
67 else:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
68 return True
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
69 return False
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
70
12788
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
71 # forcemerge comes from command line arguments, highest priority
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
72 force = ui.config('ui', 'forcemerge')
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
73 if force:
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
74 toolpath = _findtool(ui, force)
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
75 if toolpath:
17885
9a2cf955db84 filemerge: use util.shellquote when calling merge (issue3581)
Keegan Carruthers-Smith <keegancsmith@fb.com>
parents: 16256
diff changeset
76 return (force, util.shellquote(toolpath))
12788
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
77 else:
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
78 # mimic HGMERGE if given tool not found
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
79 return (force, force)
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
80
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
81 # HGMERGE takes next precedence
6025
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
82 hgmerge = os.environ.get("HGMERGE")
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
83 if hgmerge:
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
84 return (hgmerge, hgmerge)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
85
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
86 # then patterns
6016
288ec2f6faa2 filemerge: fix pattern matching
dhruva <dhruvakm@gmail.com>
parents: 6015
diff changeset
87 for pat, tool in ui.configitems("merge-patterns"):
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
88 mf = match.match(repo.root, '', [pat])
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
89 if mf(path) and check(tool, pat, symlink, False):
10339
23e608f42f2c fix spaces/identation issues
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
90 toolpath = _findtool(ui, tool)
17885
9a2cf955db84 filemerge: use util.shellquote when calling merge (issue3581)
Keegan Carruthers-Smith <keegancsmith@fb.com>
parents: 16256
diff changeset
91 return (tool, util.shellquote(toolpath))
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
92
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
93 # then merge tools
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
94 tools = {}
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
95 for k, v in ui.configitems("merge-tools"):
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
96 t = k.split('.')[0]
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
97 if t not in tools:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
98 tools[t] = int(_toolstr(ui, t, "priority", "0"))
6076
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
99 names = tools.keys()
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
100 tools = sorted([(-p, t) for t, p in tools.items()])
6076
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
101 uimerge = ui.config("ui", "merge")
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
102 if uimerge:
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
103 if uimerge not in names:
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
104 return (uimerge, uimerge)
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
105 tools.insert(0, (None, uimerge)) # highest priority
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
106 tools.append((None, "hgmerge")) # the old default, if found
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
107 for p, t in tools:
7397
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
108 if check(t, None, symlink, binary):
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
109 toolpath = _findtool(ui, t)
17885
9a2cf955db84 filemerge: use util.shellquote when calling merge (issue3581)
Keegan Carruthers-Smith <keegancsmith@fb.com>
parents: 16256
diff changeset
110 return (t, util.shellquote(toolpath))
16254
c7eef052c9e3 filemerge: restore default prompt for binary/symlink lost in 83925d3a4559
Matt Mackall <mpm@selenic.com>
parents: 16205
diff changeset
111
c7eef052c9e3 filemerge: restore default prompt for binary/symlink lost in 83925d3a4559
Matt Mackall <mpm@selenic.com>
parents: 16205
diff changeset
112 # internal merge or prompt as last resort
c7eef052c9e3 filemerge: restore default prompt for binary/symlink lost in 83925d3a4559
Matt Mackall <mpm@selenic.com>
parents: 16205
diff changeset
113 if symlink or binary:
c7eef052c9e3 filemerge: restore default prompt for binary/symlink lost in 83925d3a4559
Matt Mackall <mpm@selenic.com>
parents: 16205
diff changeset
114 return "internal:prompt", None
c7eef052c9e3 filemerge: restore default prompt for binary/symlink lost in 83925d3a4559
Matt Mackall <mpm@selenic.com>
parents: 16205
diff changeset
115 return "internal:merge", None
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
116
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
117 def _eoltype(data):
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
118 "Guess the EOL type of a file"
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
119 if '\0' in data: # binary
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
120 return None
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
121 if '\r\n' in data: # Windows
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
122 return '\r\n'
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
123 if '\r' in data: # Old Mac
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
124 return '\r'
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
125 if '\n' in data: # UNIX
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
126 return '\n'
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
127 return None # unknown
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
128
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
129 def _matcheol(file, origfile):
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
130 "Convert EOL markers in a file to match origfile"
14168
135e244776f0 prevent transient leaks of file handle by using new helper functions
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13565
diff changeset
131 tostyle = _eoltype(util.readfile(origfile))
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
132 if tostyle:
14168
135e244776f0 prevent transient leaks of file handle by using new helper functions
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13565
diff changeset
133 data = util.readfile(file)
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
134 style = _eoltype(data)
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
135 if style:
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
136 newdata = data.replace(style, tostyle)
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
137 if newdata != data:
14168
135e244776f0 prevent transient leaks of file handle by using new helper functions
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13565
diff changeset
138 util.writefile(file, newdata)
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
139
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
140 @internaltool('prompt', False)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
141 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
142 """Asks the user which of the local or the other version to keep as
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
143 the merged version."""
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
144 ui = repo.ui
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
145 fd = fcd.path()
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
146
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
147 if ui.promptchoice(_(" no tool found to merge %s\n"
19226
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18325
diff changeset
148 "keep (l)ocal or take (o)ther?"
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18325
diff changeset
149 "$$ &Local $$ &Other") % fd, 0):
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
150 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
151 else:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
152 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
153
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
154 @internaltool('local', False)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
155 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
156 """Uses the local version of files as the merged version."""
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
157 return 0
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
158
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
159 @internaltool('other', False)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
160 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
161 """Uses the other version of files as the merged version."""
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
162 repo.wwrite(fcd.path(), fco.data(), fco.flags())
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
163 return 0
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
164
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
165 @internaltool('fail', False)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
166 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
167 """
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
168 Rather than attempting to merge files that were modified on both
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
169 branches, it marks them as unresolved. The resolve command must be
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
170 used to resolve these conflicts."""
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
171 return 1
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
172
21273
20b8090d8125 merge: define conflict marker labels in filemerge()
Durham Goode <durham@fb.com>
parents: 21100
diff changeset
173 def _premerge(repo, toolconf, files, labels=None):
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
174 tool, toolpath, binary, symlink = toolconf
18257
a35d0128545e merge: never do premerge on symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 18256
diff changeset
175 if symlink:
a35d0128545e merge: never do premerge on symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 18256
diff changeset
176 return 1
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
177 a, b, c, back = files
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
178
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
179 ui = repo.ui
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
180
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
181 # do we attempt to simplemerge first?
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
182 try:
18257
a35d0128545e merge: never do premerge on symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 18256
diff changeset
183 premerge = _toolbool(ui, tool, "premerge", not binary)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
184 except error.ConfigError:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
185 premerge = _toolstr(ui, tool, "premerge").lower()
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
186 valid = 'keep'.split()
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
187 if premerge not in valid:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
188 _valid = ', '.join(["'" + v + "'" for v in valid])
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
189 raise error.ConfigError(_("%s.premerge not valid "
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
190 "('%s' is neither boolean nor %s)") %
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
191 (tool, premerge, _valid))
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
192
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
193 if premerge:
22022
2ea6d906cf9b merge: use no-minimal for premerge too
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22021
diff changeset
194 r = simplemerge.simplemerge(ui, a, b, c, quiet=True, label=labels,
2ea6d906cf9b merge: use no-minimal for premerge too
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22021
diff changeset
195 no_minimal=True)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
196 if not r:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
197 ui.debug(" premerge successful\n")
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
198 return 0
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
199 if premerge != 'keep':
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
200 util.copyfile(back, a) # restore from backup and try again
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
201 return 1 # continue merging
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
202
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
203 @internaltool('merge', True,
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
204 _("merging %s incomplete! "
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
205 "(edit conflicts, then use 'hg resolve --mark')\n"))
21273
20b8090d8125 merge: define conflict marker labels in filemerge()
Durham Goode <durham@fb.com>
parents: 21100
diff changeset
206 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
207 """
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
208 Uses the internal non-interactive simple merge algorithm for merging
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
209 files. It will fail if there are any conflicts and leave markers in
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
210 the partially merged file."""
18256
d084df89d948 merge: make internal merge fail cleanly on symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 17885
diff changeset
211 tool, toolpath, binary, symlink = toolconf
d084df89d948 merge: make internal merge fail cleanly on symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 17885
diff changeset
212 if symlink:
18325
297bf69966a0 merge: warn when internal:merge cannot merge symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 18257
diff changeset
213 repo.ui.warn(_('warning: internal:merge cannot merge symlinks '
297bf69966a0 merge: warn when internal:merge cannot merge symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 18257
diff changeset
214 'for %s\n') % fcd.path())
18256
d084df89d948 merge: make internal merge fail cleanly on symlinks
Mads Kiilerich <mads@kiilerich.com>
parents: 17885
diff changeset
215 return False, 1
21273
20b8090d8125 merge: define conflict marker labels in filemerge()
Durham Goode <durham@fb.com>
parents: 21100
diff changeset
216 r = _premerge(repo, toolconf, files, labels=labels)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
217 if r:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
218 a, b, c, back = files
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
219
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
220 ui = repo.ui
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
221
21921
ecc1387138ba filemerge: use non-minimal conflict marker regions (BC)
Matt Mackall <mpm@selenic.com>
parents: 21918
diff changeset
222 r = simplemerge.simplemerge(ui, a, b, c, label=labels, no_minimal=True)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
223 return True, r
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
224 return False, 0
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
225
21922
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
226 @internaltool('tagmerge', True,
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
227 _("automatic tag merging of %s failed! "
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
228 "(use 'hg resolve --tool internal:merge' or another merge "
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
229 "tool of your choice)\n"))
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
230 def _itagmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
231 """
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
232 Uses the internal tag merge algorithm (experimental).
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
233 """
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
234 return tagmerge.merge(repo, fcd, fco, fca)
50e20154cb68 filemerge: add internal:tagmerge merge tool
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 21921
diff changeset
235
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
236 @internaltool('dump', True)
21273
20b8090d8125 merge: define conflict marker labels in filemerge()
Durham Goode <durham@fb.com>
parents: 21100
diff changeset
237 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
16127
14dc2bbba6d2 filemerge: remove some redundancy in decorators/docstrings
Matt Mackall <mpm@selenic.com>
parents: 16126
diff changeset
238 """
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
239 Creates three versions of the files to merge, containing the
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
240 contents of local, other and base. These files can then be used to
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
241 perform a merge manually. If the file to be merged is named
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
242 ``a.txt``, these files will accordingly be named ``a.txt.local``,
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
243 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
244 same directory as ``a.txt``."""
21273
20b8090d8125 merge: define conflict marker labels in filemerge()
Durham Goode <durham@fb.com>
parents: 21100
diff changeset
245 r = _premerge(repo, toolconf, files, labels=labels)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
246 if r:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
247 a, b, c, back = files
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
248
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
249 fd = fcd.path()
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
250
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
251 util.copyfile(a, a + ".local")
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
252 repo.wwrite(fd + ".other", fco.data(), fco.flags())
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
253 repo.wwrite(fd + ".base", fca.data(), fca.flags())
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
254 return False, r
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
255
21273
20b8090d8125 merge: define conflict marker labels in filemerge()
Durham Goode <durham@fb.com>
parents: 21100
diff changeset
256 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
20b8090d8125 merge: define conflict marker labels in filemerge()
Durham Goode <durham@fb.com>
parents: 21100
diff changeset
257 r = _premerge(repo, toolconf, files, labels=labels)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
258 if r:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
259 tool, toolpath, binary, symlink = toolconf
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
260 a, b, c, back = files
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
261 out = ""
20676
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
262 env = {'HG_FILE': fcd.path(),
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
263 'HG_MY_NODE': short(mynode),
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
264 'HG_OTHER_NODE': str(fco.changectx()),
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
265 'HG_BASE_NODE': str(fca.changectx()),
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
266 'HG_MY_ISLINK': 'l' in fcd.flags(),
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
267 'HG_OTHER_ISLINK': 'l' in fco.flags(),
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
268 'HG_BASE_ISLINK': 'l' in fca.flags(),
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
269 }
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
270
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
271 ui = repo.ui
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
272
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
273 args = _toolstr(ui, tool, "args", '$local $base $other')
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
274 if "$output" in args:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
275 out, a = a, back # read input from backup, write to original
20676
89b2336e5ccf filemerge: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 19226
diff changeset
276 replace = {'local': a, 'base': b, 'other': c, 'output': out}
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
277 args = util.interpolate(r'\$', replace, args,
17885
9a2cf955db84 filemerge: use util.shellquote when calling merge (issue3581)
Keegan Carruthers-Smith <keegancsmith@fb.com>
parents: 16256
diff changeset
278 lambda s: util.shellquote(util.localpath(s)))
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
279 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
280 out=ui.fout)
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
281 return True, r
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
282 return False, 0
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
283
21519
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
284 def _formatconflictmarker(repo, ctx, template, label, pad):
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
285 """Applies the given template to the ctx, prefixed by the label.
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
286
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
287 Pad is the minimum width of the label prefix, so that multiple markers
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
288 can have aligned templated parts.
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
289 """
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
290 if ctx.node() is None:
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
291 ctx = ctx.p1()
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
292
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
293 props = templatekw.keywords.copy()
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
294 props['templ'] = template
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
295 props['ctx'] = ctx
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
296 props['repo'] = repo
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
297 templateresult = template('conflictmarker', **props)
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
298
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
299 label = ('%s:' % label).ljust(pad + 1)
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
300 mark = '%s %s' % (label, templater.stringify(templateresult))
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
301
21864
755bf1bbe0a9 filemerge: use only the first line of the generated conflict marker for safety
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21693
diff changeset
302 if mark:
755bf1bbe0a9 filemerge: use only the first line of the generated conflict marker for safety
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21693
diff changeset
303 mark = mark.splitlines()[0] # split for safety
755bf1bbe0a9 filemerge: use only the first line of the generated conflict marker for safety
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21693
diff changeset
304
21865
78e56e70c70a filemerge: use 'util.ellipsis' to trim custom conflict markers correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21864
diff changeset
305 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ')
78e56e70c70a filemerge: use 'util.ellipsis' to trim custom conflict markers correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21864
diff changeset
306 return util.ellipsis(mark, 80 - 8)
21519
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
307
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
308 _defaultconflictmarker = ('{node|short} ' +
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
309 '{ifeq(tags, "tip", "", "{tags} ")}' +
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
310 '{if(bookmarks, "{bookmarks} ")}' +
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
311 '{ifeq(branch, "default", "", "{branch} ")}' +
21693
9c35f3a8cac4 merge: drop the quotes around commit description
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21524
diff changeset
312 '- {author|user}: {desc|firstline}')
21519
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
313
21524
47b97d9af27e merge: add labels parameter from merge.update to filemerge
Durham Goode <durham@fb.com>
parents: 21519
diff changeset
314 _defaultconflictlabels = ['local', 'other']
47b97d9af27e merge: add labels parameter from merge.update to filemerge
Durham Goode <durham@fb.com>
parents: 21519
diff changeset
315
21519
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
316 def _formatlabels(repo, fcd, fco, labels):
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
317 """Formats the given labels using the conflict marker template.
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
318
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
319 Returns a list of formatted labels.
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
320 """
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
321 cd = fcd.changectx()
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
322 co = fco.changectx()
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
323
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
324 ui = repo.ui
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
325 template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker)
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
326 template = templater.parsestring(template, quoted=False)
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
327 tmpl = templater.templater(None, cache={ 'conflictmarker' : template })
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
328
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
329 pad = max(len(labels[0]), len(labels[1]))
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
330
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
331 return [_formatconflictmarker(repo, cd, tmpl, labels[0], pad),
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
332 _formatconflictmarker(repo, co, tmpl, labels[1], pad)]
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
333
21524
47b97d9af27e merge: add labels parameter from merge.update to filemerge
Durham Goode <durham@fb.com>
parents: 21519
diff changeset
334 def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
335 """perform a 3-way merge in the working directory
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
336
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
337 mynode = parent node before merge
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
338 orig = original local filename before merge
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
339 fco = other file context
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
340 fca = ancestor file context
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
341 fcd = local file context for current/destination file
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
342 """
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
343
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
344 def temp(prefix, ctx):
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
345 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
346 (fd, name) = tempfile.mkstemp(prefix=pre)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
347 data = repo.wwritedata(ctx.path(), ctx.data())
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
348 f = os.fdopen(fd, "wb")
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
349 f.write(data)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
350 f.close()
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
351 return name
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
352
11702
eb07fbc21e9c filectx: use cmp(self, fctx) instead of cmp(self, text)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11149
diff changeset
353 if not fco.cmp(fcd): # files identical?
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
354 return None
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
355
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
356 ui = repo.ui
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
357 fd = fcd.path()
15738
e86dd8dfdea0 context: add isbinary function
Laurens Holst <laurens.hg@grauw.nl>
parents: 15501
diff changeset
358 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
6744
d3691d31fc9c context: remove islink and isexec methods
Matt Mackall <mpm@selenic.com>
parents: 6743
diff changeset
359 symlink = 'l' in fcd.flags() + fco.flags()
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
360 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9049
diff changeset
361 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
362 (tool, fd, binary, symlink))
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
363
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
364 if tool in internals:
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
365 func = internals[tool]
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
366 trymerge = func.trymerge
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
367 onfailure = func.onfailure
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
368 else:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
369 func = _xmerge
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
370 trymerge = True
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
371 onfailure = _("merging %s failed!\n")
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
372
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
373 toolconf = tool, toolpath, binary, symlink
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
374
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
375 if not trymerge:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
376 return func(repo, mynode, orig, fcd, fco, fca, toolconf)
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
377
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
378 a = repo.wjoin(fd)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
379 b = temp("base", fca)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
380 c = temp("other", fco)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
381 back = a + ".orig"
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
382 util.copyfile(a, back)
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
383
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
384 if orig != fco.path():
8615
94ca38e63576 use ui instead of repo.ui when the former is in scope
Martin Geisler <mg@lazybytes.net>
parents: 8567
diff changeset
385 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
386 else:
8615
94ca38e63576 use ui instead of repo.ui when the former is in scope
Martin Geisler <mg@lazybytes.net>
parents: 8567
diff changeset
387 ui.status(_("merging %s\n") % fd)
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
388
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9049
diff changeset
389 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
390
21918
10abc3a5c6b2 filemerge: use 'basic' as the default of '[ui] mergemarkers' for safety
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 21865
diff changeset
391 markerstyle = ui.config('ui', 'mergemarkers', 'basic')
22021
e9801c7b6ff0 merge: refactor labels selection code
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21922
diff changeset
392 if not labels:
e9801c7b6ff0 merge: refactor labels selection code
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21922
diff changeset
393 labels = _defaultconflictlabels
e9801c7b6ff0 merge: refactor labels selection code
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21922
diff changeset
394 if markerstyle != 'basic':
e9801c7b6ff0 merge: refactor labels selection code
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21922
diff changeset
395 labels = _formatlabels(repo, fcd, fco, labels)
21519
25d5a9ecbb85 merge: add conflict marker formatter (BC)
Durham Goode <durham@fb.com>
parents: 21273
diff changeset
396
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
397 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
22021
e9801c7b6ff0 merge: refactor labels selection code
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21922
diff changeset
398 (a, b, c, back), labels=labels)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
399 if not needcheck:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
400 if r:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
401 if onfailure:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
402 ui.warn(onfailure % fd)
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
403 else:
21100
098a274764b3 filemerge: better handling of failing remove of temporary files
Mads Kiilerich <madski@unity3d.com>
parents: 20676
diff changeset
404 util.unlink(back)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
405
21100
098a274764b3 filemerge: better handling of failing remove of temporary files
Mads Kiilerich <madski@unity3d.com>
parents: 20676
diff changeset
406 util.unlink(b)
098a274764b3 filemerge: better handling of failing remove of temporary files
Mads Kiilerich <madski@unity3d.com>
parents: 20676
diff changeset
407 util.unlink(c)
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
408 return r
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
409
11148
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
410 if not r and (_toolbool(ui, tool, "checkconflicts") or
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
411 'conflicts' in _toollist(ui, tool, "check")):
12046
8e7960feb139 Fix merge-tools.checkconflicts
Thomas Arendsen Hein <thomas@intevation.de>
parents: 12008
diff changeset
412 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
8e7960feb139 Fix merge-tools.checkconflicts
Thomas Arendsen Hein <thomas@intevation.de>
parents: 12008
diff changeset
413 re.MULTILINE):
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
414 r = 1
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
415
11149
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
416 checked = False
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
417 if 'prompt' in _toollist(ui, tool, "check"):
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
418 checked = True
19226
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18325
diff changeset
419 if ui.promptchoice(_("was merge of '%s' successful (yn)?"
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18325
diff changeset
420 "$$ &Yes $$ &No") % fd, 1):
11149
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
421 r = 1
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
422
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
423 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
424 'changed' in _toollist(ui, tool, "check")):
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
425 if filecmp.cmp(a, back):
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8861
diff changeset
426 if ui.promptchoice(_(" output file %s appears unchanged\n"
19226
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18325
diff changeset
427 "was merge successful (yn)?"
c58b6ab4c26f ui: merge prompt text components into a singe string
Matt Mackall <mpm@selenic.com>
parents: 18325
diff changeset
428 "$$ &Yes $$ &No") % fd, 1):
6075
63e0e57ab157 filemerge: add 'checkchanged' merge tool property
Steve Borho <steve@borho.org>
parents: 6025
diff changeset
429 r = 1
63e0e57ab157 filemerge: add 'checkchanged' merge tool property
Steve Borho <steve@borho.org>
parents: 6025
diff changeset
430
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
431 if _toolbool(ui, tool, "fixeol"):
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
432 _matcheol(a, back)
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
433
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
434 if r:
16125
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
435 if onfailure:
83925d3a4559 filemerge: refactoring of 'filemerge()'
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15738
diff changeset
436 ui.warn(onfailure % fd)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
437 else:
21100
098a274764b3 filemerge: better handling of failing remove of temporary files
Mads Kiilerich <madski@unity3d.com>
parents: 20676
diff changeset
438 util.unlink(back)
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
439
21100
098a274764b3 filemerge: better handling of failing remove of temporary files
Mads Kiilerich <madski@unity3d.com>
parents: 20676
diff changeset
440 util.unlink(b)
098a274764b3 filemerge: better handling of failing remove of temporary files
Mads Kiilerich <madski@unity3d.com>
parents: 20676
diff changeset
441 util.unlink(c)
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
442 return r
16126
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
443
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
444 # tell hggettext to extract docstrings from these functions:
0c4bec9596d8 filemerge: create detail of internal merge tools from documentation string
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16125
diff changeset
445 i18nfunctions = internals.values()