##// END OF EJS Templates
merge: never do premerge on symlinks...
Mads Kiilerich -
r18257:a35d0128 default
parent child Browse files
Show More
@@ -1,373 +1,375 b''
1 # filemerge.py - file-level merge handling for Mercurial
1 # filemerge.py - file-level merge handling for Mercurial
2 #
2 #
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import short
8 from node import short
9 from i18n import _
9 from i18n import _
10 import util, simplemerge, match, error
10 import util, simplemerge, match, error
11 import os, tempfile, re, filecmp
11 import os, tempfile, re, filecmp
12
12
13 def _toolstr(ui, tool, part, default=""):
13 def _toolstr(ui, tool, part, default=""):
14 return ui.config("merge-tools", tool + "." + part, default)
14 return ui.config("merge-tools", tool + "." + part, default)
15
15
16 def _toolbool(ui, tool, part, default=False):
16 def _toolbool(ui, tool, part, default=False):
17 return ui.configbool("merge-tools", tool + "." + part, default)
17 return ui.configbool("merge-tools", tool + "." + part, default)
18
18
19 def _toollist(ui, tool, part, default=[]):
19 def _toollist(ui, tool, part, default=[]):
20 return ui.configlist("merge-tools", tool + "." + part, default)
20 return ui.configlist("merge-tools", tool + "." + part, default)
21
21
22 internals = {}
22 internals = {}
23
23
24 def internaltool(name, trymerge, onfailure=None):
24 def internaltool(name, trymerge, onfailure=None):
25 '''return a decorator for populating internal merge tool table'''
25 '''return a decorator for populating internal merge tool table'''
26 def decorator(func):
26 def decorator(func):
27 fullname = 'internal:' + name
27 fullname = 'internal:' + name
28 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
28 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
29 internals[fullname] = func
29 internals[fullname] = func
30 func.trymerge = trymerge
30 func.trymerge = trymerge
31 func.onfailure = onfailure
31 func.onfailure = onfailure
32 return func
32 return func
33 return decorator
33 return decorator
34
34
35 def _findtool(ui, tool):
35 def _findtool(ui, tool):
36 if tool in internals:
36 if tool in internals:
37 return tool
37 return tool
38 for kn in ("regkey", "regkeyalt"):
38 for kn in ("regkey", "regkeyalt"):
39 k = _toolstr(ui, tool, kn)
39 k = _toolstr(ui, tool, kn)
40 if not k:
40 if not k:
41 continue
41 continue
42 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
42 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
43 if p:
43 if p:
44 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
44 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
45 if p:
45 if p:
46 return p
46 return p
47 exe = _toolstr(ui, tool, "executable", tool)
47 exe = _toolstr(ui, tool, "executable", tool)
48 return util.findexe(util.expandpath(exe))
48 return util.findexe(util.expandpath(exe))
49
49
50 def _picktool(repo, ui, path, binary, symlink):
50 def _picktool(repo, ui, path, binary, symlink):
51 def check(tool, pat, symlink, binary):
51 def check(tool, pat, symlink, binary):
52 tmsg = tool
52 tmsg = tool
53 if pat:
53 if pat:
54 tmsg += " specified for " + pat
54 tmsg += " specified for " + pat
55 if not _findtool(ui, tool):
55 if not _findtool(ui, tool):
56 if pat: # explicitly requested tool deserves a warning
56 if pat: # explicitly requested tool deserves a warning
57 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
57 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
58 else: # configured but non-existing tools are more silent
58 else: # configured but non-existing tools are more silent
59 ui.note(_("couldn't find merge tool %s\n") % tmsg)
59 ui.note(_("couldn't find merge tool %s\n") % tmsg)
60 elif symlink and not _toolbool(ui, tool, "symlink"):
60 elif symlink and not _toolbool(ui, tool, "symlink"):
61 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
61 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
62 elif binary and not _toolbool(ui, tool, "binary"):
62 elif binary and not _toolbool(ui, tool, "binary"):
63 ui.warn(_("tool %s can't handle binary\n") % tmsg)
63 ui.warn(_("tool %s can't handle binary\n") % tmsg)
64 elif not util.gui() and _toolbool(ui, tool, "gui"):
64 elif not util.gui() and _toolbool(ui, tool, "gui"):
65 ui.warn(_("tool %s requires a GUI\n") % tmsg)
65 ui.warn(_("tool %s requires a GUI\n") % tmsg)
66 else:
66 else:
67 return True
67 return True
68 return False
68 return False
69
69
70 # forcemerge comes from command line arguments, highest priority
70 # forcemerge comes from command line arguments, highest priority
71 force = ui.config('ui', 'forcemerge')
71 force = ui.config('ui', 'forcemerge')
72 if force:
72 if force:
73 toolpath = _findtool(ui, force)
73 toolpath = _findtool(ui, force)
74 if toolpath:
74 if toolpath:
75 return (force, util.shellquote(toolpath))
75 return (force, util.shellquote(toolpath))
76 else:
76 else:
77 # mimic HGMERGE if given tool not found
77 # mimic HGMERGE if given tool not found
78 return (force, force)
78 return (force, force)
79
79
80 # HGMERGE takes next precedence
80 # HGMERGE takes next precedence
81 hgmerge = os.environ.get("HGMERGE")
81 hgmerge = os.environ.get("HGMERGE")
82 if hgmerge:
82 if hgmerge:
83 return (hgmerge, hgmerge)
83 return (hgmerge, hgmerge)
84
84
85 # then patterns
85 # then patterns
86 for pat, tool in ui.configitems("merge-patterns"):
86 for pat, tool in ui.configitems("merge-patterns"):
87 mf = match.match(repo.root, '', [pat])
87 mf = match.match(repo.root, '', [pat])
88 if mf(path) and check(tool, pat, symlink, False):
88 if mf(path) and check(tool, pat, symlink, False):
89 toolpath = _findtool(ui, tool)
89 toolpath = _findtool(ui, tool)
90 return (tool, util.shellquote(toolpath))
90 return (tool, util.shellquote(toolpath))
91
91
92 # then merge tools
92 # then merge tools
93 tools = {}
93 tools = {}
94 for k, v in ui.configitems("merge-tools"):
94 for k, v in ui.configitems("merge-tools"):
95 t = k.split('.')[0]
95 t = k.split('.')[0]
96 if t not in tools:
96 if t not in tools:
97 tools[t] = int(_toolstr(ui, t, "priority", "0"))
97 tools[t] = int(_toolstr(ui, t, "priority", "0"))
98 names = tools.keys()
98 names = tools.keys()
99 tools = sorted([(-p, t) for t, p in tools.items()])
99 tools = sorted([(-p, t) for t, p in tools.items()])
100 uimerge = ui.config("ui", "merge")
100 uimerge = ui.config("ui", "merge")
101 if uimerge:
101 if uimerge:
102 if uimerge not in names:
102 if uimerge not in names:
103 return (uimerge, uimerge)
103 return (uimerge, uimerge)
104 tools.insert(0, (None, uimerge)) # highest priority
104 tools.insert(0, (None, uimerge)) # highest priority
105 tools.append((None, "hgmerge")) # the old default, if found
105 tools.append((None, "hgmerge")) # the old default, if found
106 for p, t in tools:
106 for p, t in tools:
107 if check(t, None, symlink, binary):
107 if check(t, None, symlink, binary):
108 toolpath = _findtool(ui, t)
108 toolpath = _findtool(ui, t)
109 return (t, util.shellquote(toolpath))
109 return (t, util.shellquote(toolpath))
110
110
111 # internal merge or prompt as last resort
111 # internal merge or prompt as last resort
112 if symlink or binary:
112 if symlink or binary:
113 return "internal:prompt", None
113 return "internal:prompt", None
114 return "internal:merge", None
114 return "internal:merge", None
115
115
116 def _eoltype(data):
116 def _eoltype(data):
117 "Guess the EOL type of a file"
117 "Guess the EOL type of a file"
118 if '\0' in data: # binary
118 if '\0' in data: # binary
119 return None
119 return None
120 if '\r\n' in data: # Windows
120 if '\r\n' in data: # Windows
121 return '\r\n'
121 return '\r\n'
122 if '\r' in data: # Old Mac
122 if '\r' in data: # Old Mac
123 return '\r'
123 return '\r'
124 if '\n' in data: # UNIX
124 if '\n' in data: # UNIX
125 return '\n'
125 return '\n'
126 return None # unknown
126 return None # unknown
127
127
128 def _matcheol(file, origfile):
128 def _matcheol(file, origfile):
129 "Convert EOL markers in a file to match origfile"
129 "Convert EOL markers in a file to match origfile"
130 tostyle = _eoltype(util.readfile(origfile))
130 tostyle = _eoltype(util.readfile(origfile))
131 if tostyle:
131 if tostyle:
132 data = util.readfile(file)
132 data = util.readfile(file)
133 style = _eoltype(data)
133 style = _eoltype(data)
134 if style:
134 if style:
135 newdata = data.replace(style, tostyle)
135 newdata = data.replace(style, tostyle)
136 if newdata != data:
136 if newdata != data:
137 util.writefile(file, newdata)
137 util.writefile(file, newdata)
138
138
139 @internaltool('prompt', False)
139 @internaltool('prompt', False)
140 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
140 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
141 """Asks the user which of the local or the other version to keep as
141 """Asks the user which of the local or the other version to keep as
142 the merged version."""
142 the merged version."""
143 ui = repo.ui
143 ui = repo.ui
144 fd = fcd.path()
144 fd = fcd.path()
145
145
146 if ui.promptchoice(_(" no tool found to merge %s\n"
146 if ui.promptchoice(_(" no tool found to merge %s\n"
147 "keep (l)ocal or take (o)ther?") % fd,
147 "keep (l)ocal or take (o)ther?") % fd,
148 (_("&Local"), _("&Other")), 0):
148 (_("&Local"), _("&Other")), 0):
149 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
149 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
150 else:
150 else:
151 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
151 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
152
152
153 @internaltool('local', False)
153 @internaltool('local', False)
154 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
154 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
155 """Uses the local version of files as the merged version."""
155 """Uses the local version of files as the merged version."""
156 return 0
156 return 0
157
157
158 @internaltool('other', False)
158 @internaltool('other', False)
159 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
159 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
160 """Uses the other version of files as the merged version."""
160 """Uses the other version of files as the merged version."""
161 repo.wwrite(fcd.path(), fco.data(), fco.flags())
161 repo.wwrite(fcd.path(), fco.data(), fco.flags())
162 return 0
162 return 0
163
163
164 @internaltool('fail', False)
164 @internaltool('fail', False)
165 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
165 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
166 """
166 """
167 Rather than attempting to merge files that were modified on both
167 Rather than attempting to merge files that were modified on both
168 branches, it marks them as unresolved. The resolve command must be
168 branches, it marks them as unresolved. The resolve command must be
169 used to resolve these conflicts."""
169 used to resolve these conflicts."""
170 return 1
170 return 1
171
171
172 def _premerge(repo, toolconf, files):
172 def _premerge(repo, toolconf, files):
173 tool, toolpath, binary, symlink = toolconf
173 tool, toolpath, binary, symlink = toolconf
174 if symlink:
175 return 1
174 a, b, c, back = files
176 a, b, c, back = files
175
177
176 ui = repo.ui
178 ui = repo.ui
177
179
178 # do we attempt to simplemerge first?
180 # do we attempt to simplemerge first?
179 try:
181 try:
180 premerge = _toolbool(ui, tool, "premerge", not (binary or symlink))
182 premerge = _toolbool(ui, tool, "premerge", not binary)
181 except error.ConfigError:
183 except error.ConfigError:
182 premerge = _toolstr(ui, tool, "premerge").lower()
184 premerge = _toolstr(ui, tool, "premerge").lower()
183 valid = 'keep'.split()
185 valid = 'keep'.split()
184 if premerge not in valid:
186 if premerge not in valid:
185 _valid = ', '.join(["'" + v + "'" for v in valid])
187 _valid = ', '.join(["'" + v + "'" for v in valid])
186 raise error.ConfigError(_("%s.premerge not valid "
188 raise error.ConfigError(_("%s.premerge not valid "
187 "('%s' is neither boolean nor %s)") %
189 "('%s' is neither boolean nor %s)") %
188 (tool, premerge, _valid))
190 (tool, premerge, _valid))
189
191
190 if premerge:
192 if premerge:
191 r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
193 r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
192 if not r:
194 if not r:
193 ui.debug(" premerge successful\n")
195 ui.debug(" premerge successful\n")
194 return 0
196 return 0
195 if premerge != 'keep':
197 if premerge != 'keep':
196 util.copyfile(back, a) # restore from backup and try again
198 util.copyfile(back, a) # restore from backup and try again
197 return 1 # continue merging
199 return 1 # continue merging
198
200
199 @internaltool('merge', True,
201 @internaltool('merge', True,
200 _("merging %s incomplete! "
202 _("merging %s incomplete! "
201 "(edit conflicts, then use 'hg resolve --mark')\n"))
203 "(edit conflicts, then use 'hg resolve --mark')\n"))
202 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files):
204 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files):
203 """
205 """
204 Uses the internal non-interactive simple merge algorithm for merging
206 Uses the internal non-interactive simple merge algorithm for merging
205 files. It will fail if there are any conflicts and leave markers in
207 files. It will fail if there are any conflicts and leave markers in
206 the partially merged file."""
208 the partially merged file."""
207 tool, toolpath, binary, symlink = toolconf
209 tool, toolpath, binary, symlink = toolconf
208 if symlink:
210 if symlink:
209 return False, 1
211 return False, 1
210
212
211 r = _premerge(repo, toolconf, files)
213 r = _premerge(repo, toolconf, files)
212 if r:
214 if r:
213 a, b, c, back = files
215 a, b, c, back = files
214
216
215 ui = repo.ui
217 ui = repo.ui
216
218
217 r = simplemerge.simplemerge(ui, a, b, c, label=['local', 'other'])
219 r = simplemerge.simplemerge(ui, a, b, c, label=['local', 'other'])
218 return True, r
220 return True, r
219 return False, 0
221 return False, 0
220
222
221 @internaltool('dump', True)
223 @internaltool('dump', True)
222 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files):
224 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files):
223 """
225 """
224 Creates three versions of the files to merge, containing the
226 Creates three versions of the files to merge, containing the
225 contents of local, other and base. These files can then be used to
227 contents of local, other and base. These files can then be used to
226 perform a merge manually. If the file to be merged is named
228 perform a merge manually. If the file to be merged is named
227 ``a.txt``, these files will accordingly be named ``a.txt.local``,
229 ``a.txt``, these files will accordingly be named ``a.txt.local``,
228 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
230 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
229 same directory as ``a.txt``."""
231 same directory as ``a.txt``."""
230 r = _premerge(repo, toolconf, files)
232 r = _premerge(repo, toolconf, files)
231 if r:
233 if r:
232 a, b, c, back = files
234 a, b, c, back = files
233
235
234 fd = fcd.path()
236 fd = fcd.path()
235
237
236 util.copyfile(a, a + ".local")
238 util.copyfile(a, a + ".local")
237 repo.wwrite(fd + ".other", fco.data(), fco.flags())
239 repo.wwrite(fd + ".other", fco.data(), fco.flags())
238 repo.wwrite(fd + ".base", fca.data(), fca.flags())
240 repo.wwrite(fd + ".base", fca.data(), fca.flags())
239 return False, r
241 return False, r
240
242
241 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files):
243 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files):
242 r = _premerge(repo, toolconf, files)
244 r = _premerge(repo, toolconf, files)
243 if r:
245 if r:
244 tool, toolpath, binary, symlink = toolconf
246 tool, toolpath, binary, symlink = toolconf
245 a, b, c, back = files
247 a, b, c, back = files
246 out = ""
248 out = ""
247 env = dict(HG_FILE=fcd.path(),
249 env = dict(HG_FILE=fcd.path(),
248 HG_MY_NODE=short(mynode),
250 HG_MY_NODE=short(mynode),
249 HG_OTHER_NODE=str(fco.changectx()),
251 HG_OTHER_NODE=str(fco.changectx()),
250 HG_BASE_NODE=str(fca.changectx()),
252 HG_BASE_NODE=str(fca.changectx()),
251 HG_MY_ISLINK='l' in fcd.flags(),
253 HG_MY_ISLINK='l' in fcd.flags(),
252 HG_OTHER_ISLINK='l' in fco.flags(),
254 HG_OTHER_ISLINK='l' in fco.flags(),
253 HG_BASE_ISLINK='l' in fca.flags())
255 HG_BASE_ISLINK='l' in fca.flags())
254
256
255 ui = repo.ui
257 ui = repo.ui
256
258
257 args = _toolstr(ui, tool, "args", '$local $base $other')
259 args = _toolstr(ui, tool, "args", '$local $base $other')
258 if "$output" in args:
260 if "$output" in args:
259 out, a = a, back # read input from backup, write to original
261 out, a = a, back # read input from backup, write to original
260 replace = dict(local=a, base=b, other=c, output=out)
262 replace = dict(local=a, base=b, other=c, output=out)
261 args = util.interpolate(r'\$', replace, args,
263 args = util.interpolate(r'\$', replace, args,
262 lambda s: util.shellquote(util.localpath(s)))
264 lambda s: util.shellquote(util.localpath(s)))
263 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
265 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
264 out=ui.fout)
266 out=ui.fout)
265 return True, r
267 return True, r
266 return False, 0
268 return False, 0
267
269
268 def filemerge(repo, mynode, orig, fcd, fco, fca):
270 def filemerge(repo, mynode, orig, fcd, fco, fca):
269 """perform a 3-way merge in the working directory
271 """perform a 3-way merge in the working directory
270
272
271 mynode = parent node before merge
273 mynode = parent node before merge
272 orig = original local filename before merge
274 orig = original local filename before merge
273 fco = other file context
275 fco = other file context
274 fca = ancestor file context
276 fca = ancestor file context
275 fcd = local file context for current/destination file
277 fcd = local file context for current/destination file
276 """
278 """
277
279
278 def temp(prefix, ctx):
280 def temp(prefix, ctx):
279 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
281 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
280 (fd, name) = tempfile.mkstemp(prefix=pre)
282 (fd, name) = tempfile.mkstemp(prefix=pre)
281 data = repo.wwritedata(ctx.path(), ctx.data())
283 data = repo.wwritedata(ctx.path(), ctx.data())
282 f = os.fdopen(fd, "wb")
284 f = os.fdopen(fd, "wb")
283 f.write(data)
285 f.write(data)
284 f.close()
286 f.close()
285 return name
287 return name
286
288
287 if not fco.cmp(fcd): # files identical?
289 if not fco.cmp(fcd): # files identical?
288 return None
290 return None
289
291
290 ui = repo.ui
292 ui = repo.ui
291 fd = fcd.path()
293 fd = fcd.path()
292 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
294 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
293 symlink = 'l' in fcd.flags() + fco.flags()
295 symlink = 'l' in fcd.flags() + fco.flags()
294 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
296 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
295 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
297 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
296 (tool, fd, binary, symlink))
298 (tool, fd, binary, symlink))
297
299
298 if tool in internals:
300 if tool in internals:
299 func = internals[tool]
301 func = internals[tool]
300 trymerge = func.trymerge
302 trymerge = func.trymerge
301 onfailure = func.onfailure
303 onfailure = func.onfailure
302 else:
304 else:
303 func = _xmerge
305 func = _xmerge
304 trymerge = True
306 trymerge = True
305 onfailure = _("merging %s failed!\n")
307 onfailure = _("merging %s failed!\n")
306
308
307 toolconf = tool, toolpath, binary, symlink
309 toolconf = tool, toolpath, binary, symlink
308
310
309 if not trymerge:
311 if not trymerge:
310 return func(repo, mynode, orig, fcd, fco, fca, toolconf)
312 return func(repo, mynode, orig, fcd, fco, fca, toolconf)
311
313
312 a = repo.wjoin(fd)
314 a = repo.wjoin(fd)
313 b = temp("base", fca)
315 b = temp("base", fca)
314 c = temp("other", fco)
316 c = temp("other", fco)
315 back = a + ".orig"
317 back = a + ".orig"
316 util.copyfile(a, back)
318 util.copyfile(a, back)
317
319
318 if orig != fco.path():
320 if orig != fco.path():
319 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
321 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
320 else:
322 else:
321 ui.status(_("merging %s\n") % fd)
323 ui.status(_("merging %s\n") % fd)
322
324
323 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
325 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
324
326
325 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
327 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
326 (a, b, c, back))
328 (a, b, c, back))
327 if not needcheck:
329 if not needcheck:
328 if r:
330 if r:
329 if onfailure:
331 if onfailure:
330 ui.warn(onfailure % fd)
332 ui.warn(onfailure % fd)
331 else:
333 else:
332 os.unlink(back)
334 os.unlink(back)
333
335
334 os.unlink(b)
336 os.unlink(b)
335 os.unlink(c)
337 os.unlink(c)
336 return r
338 return r
337
339
338 if not r and (_toolbool(ui, tool, "checkconflicts") or
340 if not r and (_toolbool(ui, tool, "checkconflicts") or
339 'conflicts' in _toollist(ui, tool, "check")):
341 'conflicts' in _toollist(ui, tool, "check")):
340 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
342 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
341 re.MULTILINE):
343 re.MULTILINE):
342 r = 1
344 r = 1
343
345
344 checked = False
346 checked = False
345 if 'prompt' in _toollist(ui, tool, "check"):
347 if 'prompt' in _toollist(ui, tool, "check"):
346 checked = True
348 checked = True
347 if ui.promptchoice(_("was merge of '%s' successful (yn)?") % fd,
349 if ui.promptchoice(_("was merge of '%s' successful (yn)?") % fd,
348 (_("&Yes"), _("&No")), 1):
350 (_("&Yes"), _("&No")), 1):
349 r = 1
351 r = 1
350
352
351 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
353 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
352 'changed' in _toollist(ui, tool, "check")):
354 'changed' in _toollist(ui, tool, "check")):
353 if filecmp.cmp(a, back):
355 if filecmp.cmp(a, back):
354 if ui.promptchoice(_(" output file %s appears unchanged\n"
356 if ui.promptchoice(_(" output file %s appears unchanged\n"
355 "was merge successful (yn)?") % fd,
357 "was merge successful (yn)?") % fd,
356 (_("&Yes"), _("&No")), 1):
358 (_("&Yes"), _("&No")), 1):
357 r = 1
359 r = 1
358
360
359 if _toolbool(ui, tool, "fixeol"):
361 if _toolbool(ui, tool, "fixeol"):
360 _matcheol(a, back)
362 _matcheol(a, back)
361
363
362 if r:
364 if r:
363 if onfailure:
365 if onfailure:
364 ui.warn(onfailure % fd)
366 ui.warn(onfailure % fd)
365 else:
367 else:
366 os.unlink(back)
368 os.unlink(back)
367
369
368 os.unlink(b)
370 os.unlink(b)
369 os.unlink(c)
371 os.unlink(c)
370 return r
372 return r
371
373
372 # tell hggettext to extract docstrings from these functions:
374 # tell hggettext to extract docstrings from these functions:
373 i18nfunctions = internals.values()
375 i18nfunctions = internals.values()
General Comments 0
You need to be logged in to leave comments. Login now