annotate mercurial/filemerge.py @ 13944:bc32bb0e909f

util: new function checkfilename checkfilename checks for restrictions on filenames imposed by Mercurial itself, irrespective of on what platform it is run.
author Adrian Buehlmann <adrian@cadifra.com>
date Fri, 15 Apr 2011 16:15:30 +0200
parents 984175605311
children 135e244776f0
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 _
11146
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
10 import util, simplemerge, match, error
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
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
12
6013
bb441d77df99 filemerge: handle missing regappend
Matt Mackall <mpm@selenic.com>
parents: 6007
diff changeset
13 def _toolstr(ui, tool, part, default=""):
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
14 return ui.config("merge-tools", tool + "." + part, default)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
15
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
16 def _toolbool(ui, tool, part, default=False):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
17 return ui.configbool("merge-tools", tool + "." + part, default)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
18
11148
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
19 def _toollist(ui, tool, part, default=[]):
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
20 return ui.configlist("merge-tools", tool + "." + part, default)
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
21
8831
91e26fb24fb1 filemerge: add internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8830
diff changeset
22 _internal = ['internal:' + s
91e26fb24fb1 filemerge: add internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8830
diff changeset
23 for s in 'fail local other merge prompt dump'.split()]
8830
a9850eda2973 filemerge: add internal:prompt target
Matt Mackall <mpm@selenic.com>
parents: 8615
diff changeset
24
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
25 def _findtool(ui, tool):
8830
a9850eda2973 filemerge: add internal:prompt target
Matt Mackall <mpm@selenic.com>
parents: 8615
diff changeset
26 if tool in _internal:
6522
2b181fb3a70a use internal merge tool when specified for a merge-pattern in hgrc
Dov Feldstern <dfeldstern@fastimap.com>
parents: 6212
diff changeset
27 return tool
13565
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
28 for kn in ("regkey", "regkeyalt"):
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
29 k = _toolstr(ui, tool, kn)
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
30 if not k:
984175605311 filemerge: introduce a 'regkeyalt' merge tool variable
Steve Borho <steve@borho.org>
parents: 12788
diff changeset
31 continue
6006
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
32 p = util.lookup_reg(k, _toolstr(ui, tool, "regname"))
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
33 if p:
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
34 p = util.find_exe(p + _toolstr(ui, tool, "regappend"))
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
35 if p:
3c9dbb743d20 merge: add registry look up bits to tool search
Matt Mackall <mpm@selenic.com>
parents: 6005
diff changeset
36 return p
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
37 return util.find_exe(_toolstr(ui, tool, "executable", tool))
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
38
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
39 def _picktool(repo, ui, path, binary, symlink):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
40 def check(tool, pat, symlink, binary):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
41 tmsg = tool
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
42 if pat:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
43 tmsg += " specified for " + pat
7397
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
44 if not _findtool(ui, tool):
4c92d8971809 More verbose logging when filemerge searches for merge-tool
Mads Kiilerich <mads@kiilerich.com>
parents: 6762
diff changeset
45 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
46 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
47 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
48 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
49 elif symlink and not _toolbool(ui, tool, "symlink"):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
50 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
51 elif binary and not _toolbool(ui, tool, "binary"):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
52 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
53 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
54 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
55 else:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
56 return True
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
57 return False
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
58
12788
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
59 # 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
60 force = ui.config('ui', 'forcemerge')
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
61 if force:
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
62 toolpath = _findtool(ui, force)
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
63 if toolpath:
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
64 return (force, '"' + toolpath + '"')
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
65 else:
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
66 # 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
67 return (force, force)
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
68
de793925862e merge: implement --tool arguments using new ui.forcemerge configurable
Steve Borho <steve@borho.org>
parents: 12047
diff changeset
69 # HGMERGE takes next precedence
6025
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
70 hgmerge = os.environ.get("HGMERGE")
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
71 if hgmerge:
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
72 return (hgmerge, hgmerge)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
73
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
74 # then patterns
6016
288ec2f6faa2 filemerge: fix pattern matching
dhruva <dhruvakm@gmail.com>
parents: 6015
diff changeset
75 for pat, tool in ui.configitems("merge-patterns"):
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
76 mf = match.match(repo.root, '', [pat])
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
77 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
78 toolpath = _findtool(ui, tool)
23e608f42f2c fix spaces/identation issues
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
79 return (tool, '"' + toolpath + '"')
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
80
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
81 # then merge tools
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
82 tools = {}
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
83 for k, v in ui.configitems("merge-tools"):
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
84 t = k.split('.')[0]
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
85 if t not in tools:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
86 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
87 names = tools.keys()
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
88 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
89 uimerge = ui.config("ui", "merge")
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
90 if uimerge:
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
91 if uimerge not in names:
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
92 return (uimerge, uimerge)
0ee885fea464 filemerge: more backwards compatible behavior for ui.merge
Steve Borho <steve@borho.org>
parents: 6075
diff changeset
93 tools.insert(0, (None, uimerge)) # highest priority
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
94 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
95 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
96 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
97 toolpath = _findtool(ui, t)
6025
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
98 return (t, '"' + toolpath + '"')
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
99 # internal merge as last resort
f2335246e5c7 filemerge: wrap quotes around tool path
Steve Borho <steve@borho.org>
parents: 6016
diff changeset
100 return (not (symlink or binary) and "internal:merge" or None, None)
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
101
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
102 def _eoltype(data):
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
103 "Guess the EOL type of a file"
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
104 if '\0' in data: # binary
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
105 return None
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
106 if '\r\n' in data: # Windows
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
107 return '\r\n'
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
108 if '\r' in data: # Old Mac
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
109 return '\r'
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
110 if '\n' in data: # UNIX
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
111 return '\n'
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
112 return None # unknown
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
113
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
114 def _matcheol(file, origfile):
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
115 "Convert EOL markers in a file to match origfile"
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
116 tostyle = _eoltype(open(origfile, "rb").read())
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
117 if tostyle:
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
118 data = open(file, "rb").read()
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
119 style = _eoltype(data)
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
120 if style:
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
121 newdata = data.replace(style, tostyle)
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
122 if newdata != data:
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
123 open(file, "wb").write(newdata)
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
124
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
125 def filemerge(repo, mynode, orig, fcd, fco, fca):
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
126 """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
127
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
128 mynode = parent node before merge
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
129 orig = original local filename before merge
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
130 fco = other file context
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
131 fca = ancestor file context
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
132 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
133 """
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
134
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
135 def temp(prefix, ctx):
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
136 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
137 (fd, name) = tempfile.mkstemp(prefix=pre)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
138 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
139 f = os.fdopen(fd, "wb")
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
140 f.write(data)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
141 f.close()
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
142 return name
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
143
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
144 def isbin(ctx):
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
145 try:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
146 return util.binary(ctx.data())
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
147 except IOError:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
148 return False
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
149
11702
eb07fbc21e9c filectx: use cmp(self, fctx) instead of cmp(self, text)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11149
diff changeset
150 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
151 return None
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
152
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
153 ui = repo.ui
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
154 fd = fcd.path()
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
155 binary = isbin(fcd) or isbin(fco) or isbin(fca)
6744
d3691d31fc9c context: remove islink and isexec methods
Matt Mackall <mpm@selenic.com>
parents: 6743
diff changeset
156 symlink = 'l' in fcd.flags() + fco.flags()
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
157 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
158 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
159 (tool, fd, binary, symlink))
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
160
8830
a9850eda2973 filemerge: add internal:prompt target
Matt Mackall <mpm@selenic.com>
parents: 8615
diff changeset
161 if not tool or tool == 'internal:prompt':
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
162 tool = "internal:local"
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8861
diff changeset
163 if ui.promptchoice(_(" no tool found to merge %s\n"
9049
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
164 "keep (l)ocal or take (o)ther?") % fd,
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
165 (_("&Local"), _("&Other")), 0):
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
166 tool = "internal:other"
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
167 if tool == "internal:local":
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
168 return 0
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
169 if tool == "internal:other":
6743
86e8187b721a simplify flag handling
Matt Mackall <mpm@selenic.com>
parents: 6533
diff changeset
170 repo.wwrite(fd, fco.data(), fco.flags())
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
171 return 0
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
172 if tool == "internal:fail":
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
173 return 1
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
174
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
175 # do the actual merge
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
176 a = repo.wjoin(fd)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
177 b = temp("base", fca)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
178 c = temp("other", fco)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
179 out = ""
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
180 back = a + ".orig"
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
181 util.copyfile(a, back)
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
182
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
183 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
184 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
185 else:
8615
94ca38e63576 use ui instead of repo.ui when the former is in scope
Martin Geisler <mg@lazybytes.net>
parents: 8567
diff changeset
186 ui.status(_("merging %s\n") % fd)
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
187
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9049
diff changeset
188 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
189
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
190 # do we attempt to simplemerge first?
11146
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
191 try:
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
192 premerge = _toolbool(ui, tool, "premerge", not (binary or symlink))
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
193 except error.ConfigError:
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
194 premerge = _toolstr(ui, tool, "premerge").lower()
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
195 valid = 'keep'.split()
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
196 if premerge not in valid:
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
197 _valid = ', '.join(["'" + v + "'" for v in valid])
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
198 raise error.ConfigError(_("%s.premerge not valid "
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
199 "('%s' is neither boolean nor %s)") %
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
200 (tool, premerge, _valid))
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
201
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
202 if premerge:
8269
bb9f13974d8e simplemerge: use ui.warn() for warnings
Steve Borho <steve@borho.org>
parents: 8259
diff changeset
203 r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
204 if not r:
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9049
diff changeset
205 ui.debug(" premerge successful\n")
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
206 os.unlink(back)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
207 os.unlink(b)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
208 os.unlink(c)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
209 return 0
11146
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
210 if premerge != 'keep':
523330d567cf merge: tool.premerge=keep will leave premerge markers in $local
David Champion <dgc@uchicago.edu>
parents: 10944
diff changeset
211 util.copyfile(back, a) # restore from backup and try again
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
212
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
213 env = dict(HG_FILE=fd,
6512
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
214 HG_MY_NODE=short(mynode),
368a4ec603cc merge: introduce mergestate
Matt Mackall <mpm@selenic.com>
parents: 6212
diff changeset
215 HG_OTHER_NODE=str(fco.changectx()),
9709
5858117a0077 merge: supply base node to merge tools in the environment
Sune Foldager <cryo@cyanite.org>
parents: 9467
diff changeset
216 HG_BASE_NODE=str(fca.changectx()),
6744
d3691d31fc9c context: remove islink and isexec methods
Matt Mackall <mpm@selenic.com>
parents: 6743
diff changeset
217 HG_MY_ISLINK='l' in fcd.flags(),
d3691d31fc9c context: remove islink and isexec methods
Matt Mackall <mpm@selenic.com>
parents: 6743
diff changeset
218 HG_OTHER_ISLINK='l' in fco.flags(),
d3691d31fc9c context: remove islink and isexec methods
Matt Mackall <mpm@selenic.com>
parents: 6743
diff changeset
219 HG_BASE_ISLINK='l' in fca.flags())
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
220
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
221 if tool == "internal:merge":
8269
bb9f13974d8e simplemerge: use ui.warn() for warnings
Steve Borho <steve@borho.org>
parents: 8259
diff changeset
222 r = simplemerge.simplemerge(ui, a, b, c, label=['local', 'other'])
8831
91e26fb24fb1 filemerge: add internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8830
diff changeset
223 elif tool == 'internal:dump':
91e26fb24fb1 filemerge: add internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8830
diff changeset
224 a = repo.wjoin(fd)
91e26fb24fb1 filemerge: add internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8830
diff changeset
225 util.copyfile(a, a + ".local")
8861
90f74b31ed4f filemerge: fix internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8831
diff changeset
226 repo.wwrite(fd + ".other", fco.data(), fco.flags())
90f74b31ed4f filemerge: fix internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8831
diff changeset
227 repo.wwrite(fd + ".base", fca.data(), fca.flags())
8831
91e26fb24fb1 filemerge: add internal:dump
Matt Mackall <mpm@selenic.com>
parents: 8830
diff changeset
228 return 1 # unresolved
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
229 else:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
230 args = _toolstr(ui, tool, "args", '$local $base $other')
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
231 if "$output" in args:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
232 out, a = a, back # read input from backup, write to original
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
233 replace = dict(local=a, base=b, other=c, output=out)
11988
8380ed691df8 util: add an interpolate() function to for replacing multiple values
Steve Losh <steve@stevelosh.com>
parents: 11702
diff changeset
234 args = util.interpolate(r'\$', replace, args,
8380ed691df8 util: add an interpolate() function to for replacing multiple values
Steve Losh <steve@stevelosh.com>
parents: 11702
diff changeset
235 lambda s: '"%s"' % util.localpath(s))
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
236 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env)
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
237
11148
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
238 if not r and (_toolbool(ui, tool, "checkconflicts") or
a912f26777d3 merge: introduce tool.check parameter
David Champion <dgc@uchicago.edu>
parents: 11146
diff changeset
239 'conflicts' in _toollist(ui, tool, "check")):
12046
8e7960feb139 Fix merge-tools.checkconflicts
Thomas Arendsen Hein <thomas@intevation.de>
parents: 12008
diff changeset
240 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
8e7960feb139 Fix merge-tools.checkconflicts
Thomas Arendsen Hein <thomas@intevation.de>
parents: 12008
diff changeset
241 re.MULTILINE):
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
242 r = 1
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
243
11149
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
244 checked = False
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
245 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
246 checked = True
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
247 if ui.promptchoice(_("was merge of '%s' successful (yn)?") % fd,
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
248 (_("&Yes"), _("&No")), 1):
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
249 r = 1
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
250
d3c1eddfdbcf merge: tool.check = prompt will force an interactive merge check
David Champion <dgc@uchicago.edu>
parents: 11148
diff changeset
251 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
252 'changed' in _toollist(ui, tool, "check")):
6075
63e0e57ab157 filemerge: add 'checkchanged' merge tool property
Steve Borho <steve@borho.org>
parents: 6025
diff changeset
253 if filecmp.cmp(repo.wjoin(fd), back):
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8861
diff changeset
254 if ui.promptchoice(_(" output file %s appears unchanged\n"
9049
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
255 "was merge successful (yn)?") % fd,
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
256 (_("&Yes"), _("&No")), 1):
6075
63e0e57ab157 filemerge: add 'checkchanged' merge tool property
Steve Borho <steve@borho.org>
parents: 6025
diff changeset
257 r = 1
63e0e57ab157 filemerge: add 'checkchanged' merge tool property
Steve Borho <steve@borho.org>
parents: 6025
diff changeset
258
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
259 if _toolbool(ui, tool, "fixeol"):
6015
26ef792f834e filemerge: fix path to working file when fixeol is enabled
Lee Cantey <lcantey@gmail.com>
parents: 6013
diff changeset
260 _matcheol(repo.wjoin(fd), back)
6005
3c33032d8906 merge: add support for tool EOL fixups
Matt Mackall <mpm@selenic.com>
parents: 6004
diff changeset
261
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
262 if r:
8615
94ca38e63576 use ui instead of repo.ui when the former is in scope
Martin Geisler <mg@lazybytes.net>
parents: 8567
diff changeset
263 ui.warn(_("merging %s failed!\n") % fd)
6004
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
264 else:
5af5f0f9d724 merge: allow smarter tool configuration
Matt Mackall <mpm@selenic.com>
parents: 6003
diff changeset
265 os.unlink(back)
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
266
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
267 os.unlink(b)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
268 os.unlink(c)
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
269 return r