##// END OF EJS Templates
filemerge: remove leading space from " no tool found..."...
Martin von Zweigbergk -
r26967:7a8e9a98 default
parent child Browse files
Show More
@@ -1,586 +1,586
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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import filecmp
10 import filecmp
11 import os
11 import os
12 import re
12 import re
13 import tempfile
13 import tempfile
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import short
16 from .node import short
17
17
18 from . import (
18 from . import (
19 cmdutil,
19 cmdutil,
20 error,
20 error,
21 match,
21 match,
22 simplemerge,
22 simplemerge,
23 tagmerge,
23 tagmerge,
24 templatekw,
24 templatekw,
25 templater,
25 templater,
26 util,
26 util,
27 )
27 )
28
28
29 def _toolstr(ui, tool, part, default=""):
29 def _toolstr(ui, tool, part, default=""):
30 return ui.config("merge-tools", tool + "." + part, default)
30 return ui.config("merge-tools", tool + "." + part, default)
31
31
32 def _toolbool(ui, tool, part, default=False):
32 def _toolbool(ui, tool, part, default=False):
33 return ui.configbool("merge-tools", tool + "." + part, default)
33 return ui.configbool("merge-tools", tool + "." + part, default)
34
34
35 def _toollist(ui, tool, part, default=[]):
35 def _toollist(ui, tool, part, default=[]):
36 return ui.configlist("merge-tools", tool + "." + part, default)
36 return ui.configlist("merge-tools", tool + "." + part, default)
37
37
38 internals = {}
38 internals = {}
39 # Merge tools to document.
39 # Merge tools to document.
40 internalsdoc = {}
40 internalsdoc = {}
41
41
42 # internal tool merge types
42 # internal tool merge types
43 nomerge = None
43 nomerge = None
44 mergeonly = 'mergeonly' # just the full merge, no premerge
44 mergeonly = 'mergeonly' # just the full merge, no premerge
45 fullmerge = 'fullmerge' # both premerge and merge
45 fullmerge = 'fullmerge' # both premerge and merge
46
46
47 def internaltool(name, mergetype, onfailure=None, precheck=None):
47 def internaltool(name, mergetype, onfailure=None, precheck=None):
48 '''return a decorator for populating internal merge tool table'''
48 '''return a decorator for populating internal merge tool table'''
49 def decorator(func):
49 def decorator(func):
50 fullname = ':' + name
50 fullname = ':' + name
51 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
51 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
52 internals[fullname] = func
52 internals[fullname] = func
53 internals['internal:' + name] = func
53 internals['internal:' + name] = func
54 internalsdoc[fullname] = func
54 internalsdoc[fullname] = func
55 func.mergetype = mergetype
55 func.mergetype = mergetype
56 func.onfailure = onfailure
56 func.onfailure = onfailure
57 func.precheck = precheck
57 func.precheck = precheck
58 return func
58 return func
59 return decorator
59 return decorator
60
60
61 def _findtool(ui, tool):
61 def _findtool(ui, tool):
62 if tool in internals:
62 if tool in internals:
63 return tool
63 return tool
64 return findexternaltool(ui, tool)
64 return findexternaltool(ui, tool)
65
65
66 def findexternaltool(ui, tool):
66 def findexternaltool(ui, tool):
67 for kn in ("regkey", "regkeyalt"):
67 for kn in ("regkey", "regkeyalt"):
68 k = _toolstr(ui, tool, kn)
68 k = _toolstr(ui, tool, kn)
69 if not k:
69 if not k:
70 continue
70 continue
71 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
71 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
72 if p:
72 if p:
73 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
73 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
74 if p:
74 if p:
75 return p
75 return p
76 exe = _toolstr(ui, tool, "executable", tool)
76 exe = _toolstr(ui, tool, "executable", tool)
77 return util.findexe(util.expandpath(exe))
77 return util.findexe(util.expandpath(exe))
78
78
79 def _picktool(repo, ui, path, binary, symlink):
79 def _picktool(repo, ui, path, binary, symlink):
80 def check(tool, pat, symlink, binary):
80 def check(tool, pat, symlink, binary):
81 tmsg = tool
81 tmsg = tool
82 if pat:
82 if pat:
83 tmsg += " specified for " + pat
83 tmsg += " specified for " + pat
84 if not _findtool(ui, tool):
84 if not _findtool(ui, tool):
85 if pat: # explicitly requested tool deserves a warning
85 if pat: # explicitly requested tool deserves a warning
86 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
86 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
87 else: # configured but non-existing tools are more silent
87 else: # configured but non-existing tools are more silent
88 ui.note(_("couldn't find merge tool %s\n") % tmsg)
88 ui.note(_("couldn't find merge tool %s\n") % tmsg)
89 elif symlink and not _toolbool(ui, tool, "symlink"):
89 elif symlink and not _toolbool(ui, tool, "symlink"):
90 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
90 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
91 elif binary and not _toolbool(ui, tool, "binary"):
91 elif binary and not _toolbool(ui, tool, "binary"):
92 ui.warn(_("tool %s can't handle binary\n") % tmsg)
92 ui.warn(_("tool %s can't handle binary\n") % tmsg)
93 elif not util.gui() and _toolbool(ui, tool, "gui"):
93 elif not util.gui() and _toolbool(ui, tool, "gui"):
94 ui.warn(_("tool %s requires a GUI\n") % tmsg)
94 ui.warn(_("tool %s requires a GUI\n") % tmsg)
95 else:
95 else:
96 return True
96 return True
97 return False
97 return False
98
98
99 # internal config: ui.forcemerge
99 # internal config: ui.forcemerge
100 # forcemerge comes from command line arguments, highest priority
100 # forcemerge comes from command line arguments, highest priority
101 force = ui.config('ui', 'forcemerge')
101 force = ui.config('ui', 'forcemerge')
102 if force:
102 if force:
103 toolpath = _findtool(ui, force)
103 toolpath = _findtool(ui, force)
104 if toolpath:
104 if toolpath:
105 return (force, util.shellquote(toolpath))
105 return (force, util.shellquote(toolpath))
106 else:
106 else:
107 # mimic HGMERGE if given tool not found
107 # mimic HGMERGE if given tool not found
108 return (force, force)
108 return (force, force)
109
109
110 # HGMERGE takes next precedence
110 # HGMERGE takes next precedence
111 hgmerge = os.environ.get("HGMERGE")
111 hgmerge = os.environ.get("HGMERGE")
112 if hgmerge:
112 if hgmerge:
113 return (hgmerge, hgmerge)
113 return (hgmerge, hgmerge)
114
114
115 # then patterns
115 # then patterns
116 for pat, tool in ui.configitems("merge-patterns"):
116 for pat, tool in ui.configitems("merge-patterns"):
117 mf = match.match(repo.root, '', [pat])
117 mf = match.match(repo.root, '', [pat])
118 if mf(path) and check(tool, pat, symlink, False):
118 if mf(path) and check(tool, pat, symlink, False):
119 toolpath = _findtool(ui, tool)
119 toolpath = _findtool(ui, tool)
120 return (tool, util.shellquote(toolpath))
120 return (tool, util.shellquote(toolpath))
121
121
122 # then merge tools
122 # then merge tools
123 tools = {}
123 tools = {}
124 disabled = set()
124 disabled = set()
125 for k, v in ui.configitems("merge-tools"):
125 for k, v in ui.configitems("merge-tools"):
126 t = k.split('.')[0]
126 t = k.split('.')[0]
127 if t not in tools:
127 if t not in tools:
128 tools[t] = int(_toolstr(ui, t, "priority", "0"))
128 tools[t] = int(_toolstr(ui, t, "priority", "0"))
129 if _toolbool(ui, t, "disabled", False):
129 if _toolbool(ui, t, "disabled", False):
130 disabled.add(t)
130 disabled.add(t)
131 names = tools.keys()
131 names = tools.keys()
132 tools = sorted([(-p, t) for t, p in tools.items() if t not in disabled])
132 tools = sorted([(-p, t) for t, p in tools.items() if t not in disabled])
133 uimerge = ui.config("ui", "merge")
133 uimerge = ui.config("ui", "merge")
134 if uimerge:
134 if uimerge:
135 if uimerge not in names:
135 if uimerge not in names:
136 return (uimerge, uimerge)
136 return (uimerge, uimerge)
137 tools.insert(0, (None, uimerge)) # highest priority
137 tools.insert(0, (None, uimerge)) # highest priority
138 tools.append((None, "hgmerge")) # the old default, if found
138 tools.append((None, "hgmerge")) # the old default, if found
139 for p, t in tools:
139 for p, t in tools:
140 if check(t, None, symlink, binary):
140 if check(t, None, symlink, binary):
141 toolpath = _findtool(ui, t)
141 toolpath = _findtool(ui, t)
142 return (t, util.shellquote(toolpath))
142 return (t, util.shellquote(toolpath))
143
143
144 # internal merge or prompt as last resort
144 # internal merge or prompt as last resort
145 if symlink or binary:
145 if symlink or binary:
146 return ":prompt", None
146 return ":prompt", None
147 return ":merge", None
147 return ":merge", None
148
148
149 def _eoltype(data):
149 def _eoltype(data):
150 "Guess the EOL type of a file"
150 "Guess the EOL type of a file"
151 if '\0' in data: # binary
151 if '\0' in data: # binary
152 return None
152 return None
153 if '\r\n' in data: # Windows
153 if '\r\n' in data: # Windows
154 return '\r\n'
154 return '\r\n'
155 if '\r' in data: # Old Mac
155 if '\r' in data: # Old Mac
156 return '\r'
156 return '\r'
157 if '\n' in data: # UNIX
157 if '\n' in data: # UNIX
158 return '\n'
158 return '\n'
159 return None # unknown
159 return None # unknown
160
160
161 def _matcheol(file, origfile):
161 def _matcheol(file, origfile):
162 "Convert EOL markers in a file to match origfile"
162 "Convert EOL markers in a file to match origfile"
163 tostyle = _eoltype(util.readfile(origfile))
163 tostyle = _eoltype(util.readfile(origfile))
164 if tostyle:
164 if tostyle:
165 data = util.readfile(file)
165 data = util.readfile(file)
166 style = _eoltype(data)
166 style = _eoltype(data)
167 if style:
167 if style:
168 newdata = data.replace(style, tostyle)
168 newdata = data.replace(style, tostyle)
169 if newdata != data:
169 if newdata != data:
170 util.writefile(file, newdata)
170 util.writefile(file, newdata)
171
171
172 @internaltool('prompt', nomerge)
172 @internaltool('prompt', nomerge)
173 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
173 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
174 """Asks the user which of the local or the other version to keep as
174 """Asks the user which of the local or the other version to keep as
175 the merged version."""
175 the merged version."""
176 ui = repo.ui
176 ui = repo.ui
177 fd = fcd.path()
177 fd = fcd.path()
178
178
179 try:
179 try:
180 index = ui.promptchoice(_(" no tool found to merge %s\n"
180 index = ui.promptchoice(_("no tool found to merge %s\n"
181 "keep (l)ocal or take (o)ther?"
181 "keep (l)ocal or take (o)ther?"
182 "$$ &Local $$ &Other") % fd, 0)
182 "$$ &Local $$ &Other") % fd, 0)
183 choice = ['local', 'other'][index]
183 choice = ['local', 'other'][index]
184
184
185 if choice == 'other':
185 if choice == 'other':
186 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
186 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
187 else:
187 else:
188 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
188 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
189 except error.ResponseExpected:
189 except error.ResponseExpected:
190 ui.write("\n")
190 ui.write("\n")
191 return 1
191 return 1
192
192
193 @internaltool('local', nomerge)
193 @internaltool('local', nomerge)
194 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
194 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
195 """Uses the local version of files as the merged version."""
195 """Uses the local version of files as the merged version."""
196 return 0
196 return 0
197
197
198 @internaltool('other', nomerge)
198 @internaltool('other', nomerge)
199 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
199 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
200 """Uses the other version of files as the merged version."""
200 """Uses the other version of files as the merged version."""
201 repo.wwrite(fcd.path(), fco.data(), fco.flags())
201 repo.wwrite(fcd.path(), fco.data(), fco.flags())
202 return 0
202 return 0
203
203
204 @internaltool('fail', nomerge)
204 @internaltool('fail', nomerge)
205 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
205 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
206 """
206 """
207 Rather than attempting to merge files that were modified on both
207 Rather than attempting to merge files that were modified on both
208 branches, it marks them as unresolved. The resolve command must be
208 branches, it marks them as unresolved. The resolve command must be
209 used to resolve these conflicts."""
209 used to resolve these conflicts."""
210 return 1
210 return 1
211
211
212 def _premerge(repo, toolconf, files, labels=None):
212 def _premerge(repo, toolconf, files, labels=None):
213 tool, toolpath, binary, symlink = toolconf
213 tool, toolpath, binary, symlink = toolconf
214 if symlink:
214 if symlink:
215 return 1
215 return 1
216 a, b, c, back = files
216 a, b, c, back = files
217
217
218 ui = repo.ui
218 ui = repo.ui
219
219
220 validkeep = ['keep', 'keep-merge3']
220 validkeep = ['keep', 'keep-merge3']
221
221
222 # do we attempt to simplemerge first?
222 # do we attempt to simplemerge first?
223 try:
223 try:
224 premerge = _toolbool(ui, tool, "premerge", not binary)
224 premerge = _toolbool(ui, tool, "premerge", not binary)
225 except error.ConfigError:
225 except error.ConfigError:
226 premerge = _toolstr(ui, tool, "premerge").lower()
226 premerge = _toolstr(ui, tool, "premerge").lower()
227 if premerge not in validkeep:
227 if premerge not in validkeep:
228 _valid = ', '.join(["'" + v + "'" for v in validkeep])
228 _valid = ', '.join(["'" + v + "'" for v in validkeep])
229 raise error.ConfigError(_("%s.premerge not valid "
229 raise error.ConfigError(_("%s.premerge not valid "
230 "('%s' is neither boolean nor %s)") %
230 "('%s' is neither boolean nor %s)") %
231 (tool, premerge, _valid))
231 (tool, premerge, _valid))
232
232
233 if premerge:
233 if premerge:
234 if premerge == 'keep-merge3':
234 if premerge == 'keep-merge3':
235 if not labels:
235 if not labels:
236 labels = _defaultconflictlabels
236 labels = _defaultconflictlabels
237 if len(labels) < 3:
237 if len(labels) < 3:
238 labels.append('base')
238 labels.append('base')
239 r = simplemerge.simplemerge(ui, a, b, c, quiet=True, label=labels)
239 r = simplemerge.simplemerge(ui, a, b, c, quiet=True, label=labels)
240 if not r:
240 if not r:
241 ui.debug(" premerge successful\n")
241 ui.debug(" premerge successful\n")
242 return 0
242 return 0
243 if premerge not in validkeep:
243 if premerge not in validkeep:
244 util.copyfile(back, a) # restore from backup and try again
244 util.copyfile(back, a) # restore from backup and try again
245 return 1 # continue merging
245 return 1 # continue merging
246
246
247 def _mergecheck(repo, mynode, orig, fcd, fco, fca, toolconf):
247 def _mergecheck(repo, mynode, orig, fcd, fco, fca, toolconf):
248 tool, toolpath, binary, symlink = toolconf
248 tool, toolpath, binary, symlink = toolconf
249 if symlink:
249 if symlink:
250 repo.ui.warn(_('warning: internal %s cannot merge symlinks '
250 repo.ui.warn(_('warning: internal %s cannot merge symlinks '
251 'for %s\n') % (tool, fcd.path()))
251 'for %s\n') % (tool, fcd.path()))
252 return False
252 return False
253 return True
253 return True
254
254
255 def _merge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels, mode):
255 def _merge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels, mode):
256 """
256 """
257 Uses the internal non-interactive simple merge algorithm for merging
257 Uses the internal non-interactive simple merge algorithm for merging
258 files. It will fail if there are any conflicts and leave markers in
258 files. It will fail if there are any conflicts and leave markers in
259 the partially merged file. Markers will have two sections, one for each side
259 the partially merged file. Markers will have two sections, one for each side
260 of merge, unless mode equals 'union' which suppresses the markers."""
260 of merge, unless mode equals 'union' which suppresses the markers."""
261 a, b, c, back = files
261 a, b, c, back = files
262
262
263 ui = repo.ui
263 ui = repo.ui
264
264
265 r = simplemerge.simplemerge(ui, a, b, c, label=labels, mode=mode)
265 r = simplemerge.simplemerge(ui, a, b, c, label=labels, mode=mode)
266 return True, r
266 return True, r
267
267
268 @internaltool('union', fullmerge,
268 @internaltool('union', fullmerge,
269 _("warning: conflicts while merging %s! "
269 _("warning: conflicts while merging %s! "
270 "(edit, then use 'hg resolve --mark')\n"),
270 "(edit, then use 'hg resolve --mark')\n"),
271 precheck=_mergecheck)
271 precheck=_mergecheck)
272 def _iunion(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
272 def _iunion(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
273 """
273 """
274 Uses the internal non-interactive simple merge algorithm for merging
274 Uses the internal non-interactive simple merge algorithm for merging
275 files. It will use both left and right sides for conflict regions.
275 files. It will use both left and right sides for conflict regions.
276 No markers are inserted."""
276 No markers are inserted."""
277 return _merge(repo, mynode, orig, fcd, fco, fca, toolconf,
277 return _merge(repo, mynode, orig, fcd, fco, fca, toolconf,
278 files, labels, 'union')
278 files, labels, 'union')
279
279
280 @internaltool('merge', fullmerge,
280 @internaltool('merge', fullmerge,
281 _("warning: conflicts while merging %s! "
281 _("warning: conflicts while merging %s! "
282 "(edit, then use 'hg resolve --mark')\n"),
282 "(edit, then use 'hg resolve --mark')\n"),
283 precheck=_mergecheck)
283 precheck=_mergecheck)
284 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
284 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
285 """
285 """
286 Uses the internal non-interactive simple merge algorithm for merging
286 Uses the internal non-interactive simple merge algorithm for merging
287 files. It will fail if there are any conflicts and leave markers in
287 files. It will fail if there are any conflicts and leave markers in
288 the partially merged file. Markers will have two sections, one for each side
288 the partially merged file. Markers will have two sections, one for each side
289 of merge."""
289 of merge."""
290 return _merge(repo, mynode, orig, fcd, fco, fca, toolconf,
290 return _merge(repo, mynode, orig, fcd, fco, fca, toolconf,
291 files, labels, 'merge')
291 files, labels, 'merge')
292
292
293 @internaltool('merge3', fullmerge,
293 @internaltool('merge3', fullmerge,
294 _("warning: conflicts while merging %s! "
294 _("warning: conflicts while merging %s! "
295 "(edit, then use 'hg resolve --mark')\n"),
295 "(edit, then use 'hg resolve --mark')\n"),
296 precheck=_mergecheck)
296 precheck=_mergecheck)
297 def _imerge3(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
297 def _imerge3(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
298 """
298 """
299 Uses the internal non-interactive simple merge algorithm for merging
299 Uses the internal non-interactive simple merge algorithm for merging
300 files. It will fail if there are any conflicts and leave markers in
300 files. It will fail if there are any conflicts and leave markers in
301 the partially merged file. Marker will have three sections, one from each
301 the partially merged file. Marker will have three sections, one from each
302 side of the merge and one for the base content."""
302 side of the merge and one for the base content."""
303 if not labels:
303 if not labels:
304 labels = _defaultconflictlabels
304 labels = _defaultconflictlabels
305 if len(labels) < 3:
305 if len(labels) < 3:
306 labels.append('base')
306 labels.append('base')
307 return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels)
307 return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels)
308
308
309 def _imergeauto(repo, mynode, orig, fcd, fco, fca, toolconf, files,
309 def _imergeauto(repo, mynode, orig, fcd, fco, fca, toolconf, files,
310 labels=None, localorother=None):
310 labels=None, localorother=None):
311 """
311 """
312 Generic driver for _imergelocal and _imergeother
312 Generic driver for _imergelocal and _imergeother
313 """
313 """
314 assert localorother is not None
314 assert localorother is not None
315 tool, toolpath, binary, symlink = toolconf
315 tool, toolpath, binary, symlink = toolconf
316 a, b, c, back = files
316 a, b, c, back = files
317 r = simplemerge.simplemerge(repo.ui, a, b, c, label=labels,
317 r = simplemerge.simplemerge(repo.ui, a, b, c, label=labels,
318 localorother=localorother)
318 localorother=localorother)
319 return True, r
319 return True, r
320
320
321 @internaltool('merge-local', mergeonly, precheck=_mergecheck)
321 @internaltool('merge-local', mergeonly, precheck=_mergecheck)
322 def _imergelocal(*args, **kwargs):
322 def _imergelocal(*args, **kwargs):
323 """
323 """
324 Like :merge, but resolve all conflicts non-interactively in favor
324 Like :merge, but resolve all conflicts non-interactively in favor
325 of the local changes."""
325 of the local changes."""
326 success, status = _imergeauto(localorother='local', *args, **kwargs)
326 success, status = _imergeauto(localorother='local', *args, **kwargs)
327 return success, status
327 return success, status
328
328
329 @internaltool('merge-other', mergeonly, precheck=_mergecheck)
329 @internaltool('merge-other', mergeonly, precheck=_mergecheck)
330 def _imergeother(*args, **kwargs):
330 def _imergeother(*args, **kwargs):
331 """
331 """
332 Like :merge, but resolve all conflicts non-interactively in favor
332 Like :merge, but resolve all conflicts non-interactively in favor
333 of the other changes."""
333 of the other changes."""
334 success, status = _imergeauto(localorother='other', *args, **kwargs)
334 success, status = _imergeauto(localorother='other', *args, **kwargs)
335 return success, status
335 return success, status
336
336
337 @internaltool('tagmerge', mergeonly,
337 @internaltool('tagmerge', mergeonly,
338 _("automatic tag merging of %s failed! "
338 _("automatic tag merging of %s failed! "
339 "(use 'hg resolve --tool :merge' or another merge "
339 "(use 'hg resolve --tool :merge' or another merge "
340 "tool of your choice)\n"))
340 "tool of your choice)\n"))
341 def _itagmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
341 def _itagmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
342 """
342 """
343 Uses the internal tag merge algorithm (experimental).
343 Uses the internal tag merge algorithm (experimental).
344 """
344 """
345 return tagmerge.merge(repo, fcd, fco, fca)
345 return tagmerge.merge(repo, fcd, fco, fca)
346
346
347 @internaltool('dump', fullmerge)
347 @internaltool('dump', fullmerge)
348 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
348 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
349 """
349 """
350 Creates three versions of the files to merge, containing the
350 Creates three versions of the files to merge, containing the
351 contents of local, other and base. These files can then be used to
351 contents of local, other and base. These files can then be used to
352 perform a merge manually. If the file to be merged is named
352 perform a merge manually. If the file to be merged is named
353 ``a.txt``, these files will accordingly be named ``a.txt.local``,
353 ``a.txt``, these files will accordingly be named ``a.txt.local``,
354 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
354 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
355 same directory as ``a.txt``."""
355 same directory as ``a.txt``."""
356 a, b, c, back = files
356 a, b, c, back = files
357
357
358 fd = fcd.path()
358 fd = fcd.path()
359
359
360 util.copyfile(a, a + ".local")
360 util.copyfile(a, a + ".local")
361 repo.wwrite(fd + ".other", fco.data(), fco.flags())
361 repo.wwrite(fd + ".other", fco.data(), fco.flags())
362 repo.wwrite(fd + ".base", fca.data(), fca.flags())
362 repo.wwrite(fd + ".base", fca.data(), fca.flags())
363 return False, 1
363 return False, 1
364
364
365 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
365 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
366 tool, toolpath, binary, symlink = toolconf
366 tool, toolpath, binary, symlink = toolconf
367 a, b, c, back = files
367 a, b, c, back = files
368 out = ""
368 out = ""
369 env = {'HG_FILE': fcd.path(),
369 env = {'HG_FILE': fcd.path(),
370 'HG_MY_NODE': short(mynode),
370 'HG_MY_NODE': short(mynode),
371 'HG_OTHER_NODE': str(fco.changectx()),
371 'HG_OTHER_NODE': str(fco.changectx()),
372 'HG_BASE_NODE': str(fca.changectx()),
372 'HG_BASE_NODE': str(fca.changectx()),
373 'HG_MY_ISLINK': 'l' in fcd.flags(),
373 'HG_MY_ISLINK': 'l' in fcd.flags(),
374 'HG_OTHER_ISLINK': 'l' in fco.flags(),
374 'HG_OTHER_ISLINK': 'l' in fco.flags(),
375 'HG_BASE_ISLINK': 'l' in fca.flags(),
375 'HG_BASE_ISLINK': 'l' in fca.flags(),
376 }
376 }
377
377
378 ui = repo.ui
378 ui = repo.ui
379
379
380 args = _toolstr(ui, tool, "args", '$local $base $other')
380 args = _toolstr(ui, tool, "args", '$local $base $other')
381 if "$output" in args:
381 if "$output" in args:
382 out, a = a, back # read input from backup, write to original
382 out, a = a, back # read input from backup, write to original
383 replace = {'local': a, 'base': b, 'other': c, 'output': out}
383 replace = {'local': a, 'base': b, 'other': c, 'output': out}
384 args = util.interpolate(r'\$', replace, args,
384 args = util.interpolate(r'\$', replace, args,
385 lambda s: util.shellquote(util.localpath(s)))
385 lambda s: util.shellquote(util.localpath(s)))
386 cmd = toolpath + ' ' + args
386 cmd = toolpath + ' ' + args
387 repo.ui.debug('launching merge tool: %s\n' % cmd)
387 repo.ui.debug('launching merge tool: %s\n' % cmd)
388 r = ui.system(cmd, cwd=repo.root, environ=env)
388 r = ui.system(cmd, cwd=repo.root, environ=env)
389 repo.ui.debug('merge tool returned: %s\n' % r)
389 repo.ui.debug('merge tool returned: %s\n' % r)
390 return True, r
390 return True, r
391
391
392 def _formatconflictmarker(repo, ctx, template, label, pad):
392 def _formatconflictmarker(repo, ctx, template, label, pad):
393 """Applies the given template to the ctx, prefixed by the label.
393 """Applies the given template to the ctx, prefixed by the label.
394
394
395 Pad is the minimum width of the label prefix, so that multiple markers
395 Pad is the minimum width of the label prefix, so that multiple markers
396 can have aligned templated parts.
396 can have aligned templated parts.
397 """
397 """
398 if ctx.node() is None:
398 if ctx.node() is None:
399 ctx = ctx.p1()
399 ctx = ctx.p1()
400
400
401 props = templatekw.keywords.copy()
401 props = templatekw.keywords.copy()
402 props['templ'] = template
402 props['templ'] = template
403 props['ctx'] = ctx
403 props['ctx'] = ctx
404 props['repo'] = repo
404 props['repo'] = repo
405 templateresult = template('conflictmarker', **props)
405 templateresult = template('conflictmarker', **props)
406
406
407 label = ('%s:' % label).ljust(pad + 1)
407 label = ('%s:' % label).ljust(pad + 1)
408 mark = '%s %s' % (label, templater.stringify(templateresult))
408 mark = '%s %s' % (label, templater.stringify(templateresult))
409
409
410 if mark:
410 if mark:
411 mark = mark.splitlines()[0] # split for safety
411 mark = mark.splitlines()[0] # split for safety
412
412
413 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ')
413 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ')
414 return util.ellipsis(mark, 80 - 8)
414 return util.ellipsis(mark, 80 - 8)
415
415
416 _defaultconflictmarker = ('{node|short} ' +
416 _defaultconflictmarker = ('{node|short} ' +
417 '{ifeq(tags, "tip", "", "{tags} ")}' +
417 '{ifeq(tags, "tip", "", "{tags} ")}' +
418 '{if(bookmarks, "{bookmarks} ")}' +
418 '{if(bookmarks, "{bookmarks} ")}' +
419 '{ifeq(branch, "default", "", "{branch} ")}' +
419 '{ifeq(branch, "default", "", "{branch} ")}' +
420 '- {author|user}: {desc|firstline}')
420 '- {author|user}: {desc|firstline}')
421
421
422 _defaultconflictlabels = ['local', 'other']
422 _defaultconflictlabels = ['local', 'other']
423
423
424 def _formatlabels(repo, fcd, fco, fca, labels):
424 def _formatlabels(repo, fcd, fco, fca, labels):
425 """Formats the given labels using the conflict marker template.
425 """Formats the given labels using the conflict marker template.
426
426
427 Returns a list of formatted labels.
427 Returns a list of formatted labels.
428 """
428 """
429 cd = fcd.changectx()
429 cd = fcd.changectx()
430 co = fco.changectx()
430 co = fco.changectx()
431 ca = fca.changectx()
431 ca = fca.changectx()
432
432
433 ui = repo.ui
433 ui = repo.ui
434 template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker)
434 template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker)
435 tmpl = templater.templater(None, cache={'conflictmarker': template})
435 tmpl = templater.templater(None, cache={'conflictmarker': template})
436
436
437 pad = max(len(l) for l in labels)
437 pad = max(len(l) for l in labels)
438
438
439 newlabels = [_formatconflictmarker(repo, cd, tmpl, labels[0], pad),
439 newlabels = [_formatconflictmarker(repo, cd, tmpl, labels[0], pad),
440 _formatconflictmarker(repo, co, tmpl, labels[1], pad)]
440 _formatconflictmarker(repo, co, tmpl, labels[1], pad)]
441 if len(labels) > 2:
441 if len(labels) > 2:
442 newlabels.append(_formatconflictmarker(repo, ca, tmpl, labels[2], pad))
442 newlabels.append(_formatconflictmarker(repo, ca, tmpl, labels[2], pad))
443 return newlabels
443 return newlabels
444
444
445 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
445 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
446 """perform a 3-way merge in the working directory
446 """perform a 3-way merge in the working directory
447
447
448 premerge = whether this is a premerge
448 premerge = whether this is a premerge
449 mynode = parent node before merge
449 mynode = parent node before merge
450 orig = original local filename before merge
450 orig = original local filename before merge
451 fco = other file context
451 fco = other file context
452 fca = ancestor file context
452 fca = ancestor file context
453 fcd = local file context for current/destination file
453 fcd = local file context for current/destination file
454
454
455 Returns whether the merge is complete, and the return value of the merge.
455 Returns whether the merge is complete, and the return value of the merge.
456 """
456 """
457
457
458 def temp(prefix, ctx):
458 def temp(prefix, ctx):
459 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
459 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
460 (fd, name) = tempfile.mkstemp(prefix=pre)
460 (fd, name) = tempfile.mkstemp(prefix=pre)
461 data = repo.wwritedata(ctx.path(), ctx.data())
461 data = repo.wwritedata(ctx.path(), ctx.data())
462 f = os.fdopen(fd, "wb")
462 f = os.fdopen(fd, "wb")
463 f.write(data)
463 f.write(data)
464 f.close()
464 f.close()
465 return name
465 return name
466
466
467 if not fco.cmp(fcd): # files identical?
467 if not fco.cmp(fcd): # files identical?
468 return True, None
468 return True, None
469
469
470 ui = repo.ui
470 ui = repo.ui
471 fd = fcd.path()
471 fd = fcd.path()
472 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
472 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
473 symlink = 'l' in fcd.flags() + fco.flags()
473 symlink = 'l' in fcd.flags() + fco.flags()
474 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
474 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
475 if tool in internals and tool.startswith('internal:'):
475 if tool in internals and tool.startswith('internal:'):
476 # normalize to new-style names (':merge' etc)
476 # normalize to new-style names (':merge' etc)
477 tool = tool[len('internal'):]
477 tool = tool[len('internal'):]
478 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
478 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
479 (tool, fd, binary, symlink))
479 (tool, fd, binary, symlink))
480
480
481 if tool in internals:
481 if tool in internals:
482 func = internals[tool]
482 func = internals[tool]
483 mergetype = func.mergetype
483 mergetype = func.mergetype
484 onfailure = func.onfailure
484 onfailure = func.onfailure
485 precheck = func.precheck
485 precheck = func.precheck
486 else:
486 else:
487 func = _xmerge
487 func = _xmerge
488 mergetype = fullmerge
488 mergetype = fullmerge
489 onfailure = _("merging %s failed!\n")
489 onfailure = _("merging %s failed!\n")
490 precheck = None
490 precheck = None
491
491
492 toolconf = tool, toolpath, binary, symlink
492 toolconf = tool, toolpath, binary, symlink
493
493
494 if mergetype == nomerge:
494 if mergetype == nomerge:
495 return True, func(repo, mynode, orig, fcd, fco, fca, toolconf)
495 return True, func(repo, mynode, orig, fcd, fco, fca, toolconf)
496
496
497 if premerge:
497 if premerge:
498 if orig != fco.path():
498 if orig != fco.path():
499 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
499 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
500 else:
500 else:
501 ui.status(_("merging %s\n") % fd)
501 ui.status(_("merging %s\n") % fd)
502
502
503 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
503 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
504
504
505 if precheck and not precheck(repo, mynode, orig, fcd, fco, fca,
505 if precheck and not precheck(repo, mynode, orig, fcd, fco, fca,
506 toolconf):
506 toolconf):
507 if onfailure:
507 if onfailure:
508 ui.warn(onfailure % fd)
508 ui.warn(onfailure % fd)
509 return True, 1
509 return True, 1
510
510
511 a = repo.wjoin(fd)
511 a = repo.wjoin(fd)
512 b = temp("base", fca)
512 b = temp("base", fca)
513 c = temp("other", fco)
513 c = temp("other", fco)
514 back = cmdutil.origpath(ui, repo, a)
514 back = cmdutil.origpath(ui, repo, a)
515 if premerge:
515 if premerge:
516 util.copyfile(a, back)
516 util.copyfile(a, back)
517 files = (a, b, c, back)
517 files = (a, b, c, back)
518
518
519 r = 1
519 r = 1
520 try:
520 try:
521 markerstyle = ui.config('ui', 'mergemarkers', 'basic')
521 markerstyle = ui.config('ui', 'mergemarkers', 'basic')
522 if not labels:
522 if not labels:
523 labels = _defaultconflictlabels
523 labels = _defaultconflictlabels
524 if markerstyle != 'basic':
524 if markerstyle != 'basic':
525 labels = _formatlabels(repo, fcd, fco, fca, labels)
525 labels = _formatlabels(repo, fcd, fco, fca, labels)
526
526
527 if premerge and mergetype == fullmerge:
527 if premerge and mergetype == fullmerge:
528 r = _premerge(repo, toolconf, files, labels=labels)
528 r = _premerge(repo, toolconf, files, labels=labels)
529 # complete if premerge successful (r is 0)
529 # complete if premerge successful (r is 0)
530 return not r, r
530 return not r, r
531
531
532 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf, files,
532 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf, files,
533 labels=labels)
533 labels=labels)
534 if needcheck:
534 if needcheck:
535 r = _check(r, ui, tool, fcd, files)
535 r = _check(r, ui, tool, fcd, files)
536
536
537 if r:
537 if r:
538 if onfailure:
538 if onfailure:
539 ui.warn(onfailure % fd)
539 ui.warn(onfailure % fd)
540
540
541 return True, r
541 return True, r
542 finally:
542 finally:
543 if not r:
543 if not r:
544 util.unlink(back)
544 util.unlink(back)
545 util.unlink(b)
545 util.unlink(b)
546 util.unlink(c)
546 util.unlink(c)
547
547
548 def _check(r, ui, tool, fcd, files):
548 def _check(r, ui, tool, fcd, files):
549 fd = fcd.path()
549 fd = fcd.path()
550 a, b, c, back = files
550 a, b, c, back = files
551
551
552 if not r and (_toolbool(ui, tool, "checkconflicts") or
552 if not r and (_toolbool(ui, tool, "checkconflicts") or
553 'conflicts' in _toollist(ui, tool, "check")):
553 'conflicts' in _toollist(ui, tool, "check")):
554 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
554 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
555 re.MULTILINE):
555 re.MULTILINE):
556 r = 1
556 r = 1
557
557
558 checked = False
558 checked = False
559 if 'prompt' in _toollist(ui, tool, "check"):
559 if 'prompt' in _toollist(ui, tool, "check"):
560 checked = True
560 checked = True
561 if ui.promptchoice(_("was merge of '%s' successful (yn)?"
561 if ui.promptchoice(_("was merge of '%s' successful (yn)?"
562 "$$ &Yes $$ &No") % fd, 1):
562 "$$ &Yes $$ &No") % fd, 1):
563 r = 1
563 r = 1
564
564
565 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
565 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
566 'changed' in
566 'changed' in
567 _toollist(ui, tool, "check")):
567 _toollist(ui, tool, "check")):
568 if filecmp.cmp(a, back):
568 if filecmp.cmp(a, back):
569 if ui.promptchoice(_(" output file %s appears unchanged\n"
569 if ui.promptchoice(_(" output file %s appears unchanged\n"
570 "was merge successful (yn)?"
570 "was merge successful (yn)?"
571 "$$ &Yes $$ &No") % fd, 1):
571 "$$ &Yes $$ &No") % fd, 1):
572 r = 1
572 r = 1
573
573
574 if _toolbool(ui, tool, "fixeol"):
574 if _toolbool(ui, tool, "fixeol"):
575 _matcheol(a, back)
575 _matcheol(a, back)
576
576
577 return r
577 return r
578
578
579 def premerge(repo, mynode, orig, fcd, fco, fca, labels=None):
579 def premerge(repo, mynode, orig, fcd, fco, fca, labels=None):
580 return _filemerge(True, repo, mynode, orig, fcd, fco, fca, labels=labels)
580 return _filemerge(True, repo, mynode, orig, fcd, fco, fca, labels=labels)
581
581
582 def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
582 def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
583 return _filemerge(False, repo, mynode, orig, fcd, fco, fca, labels=labels)
583 return _filemerge(False, repo, mynode, orig, fcd, fco, fca, labels=labels)
584
584
585 # tell hggettext to extract docstrings from these functions:
585 # tell hggettext to extract docstrings from these functions:
586 i18nfunctions = internals.values()
586 i18nfunctions = internals.values()
@@ -1,1185 +1,1185
1 test merge-tools configuration - mostly exercising filemerge.py
1 test merge-tools configuration - mostly exercising filemerge.py
2
2
3 $ unset HGMERGE # make sure HGMERGE doesn't interfere with the test
3 $ unset HGMERGE # make sure HGMERGE doesn't interfere with the test
4 $ hg init
4 $ hg init
5
5
6 revision 0
6 revision 0
7
7
8 $ echo "revision 0" > f
8 $ echo "revision 0" > f
9 $ echo "space" >> f
9 $ echo "space" >> f
10 $ hg commit -Am "revision 0"
10 $ hg commit -Am "revision 0"
11 adding f
11 adding f
12
12
13 revision 1
13 revision 1
14
14
15 $ echo "revision 1" > f
15 $ echo "revision 1" > f
16 $ echo "space" >> f
16 $ echo "space" >> f
17 $ hg commit -Am "revision 1"
17 $ hg commit -Am "revision 1"
18 $ hg update 0 > /dev/null
18 $ hg update 0 > /dev/null
19
19
20 revision 2
20 revision 2
21
21
22 $ echo "revision 2" > f
22 $ echo "revision 2" > f
23 $ echo "space" >> f
23 $ echo "space" >> f
24 $ hg commit -Am "revision 2"
24 $ hg commit -Am "revision 2"
25 created new head
25 created new head
26 $ hg update 0 > /dev/null
26 $ hg update 0 > /dev/null
27
27
28 revision 3 - simple to merge
28 revision 3 - simple to merge
29
29
30 $ echo "revision 3" >> f
30 $ echo "revision 3" >> f
31 $ hg commit -Am "revision 3"
31 $ hg commit -Am "revision 3"
32 created new head
32 created new head
33
33
34 revision 4 - hard to merge
34 revision 4 - hard to merge
35
35
36 $ hg update 0 > /dev/null
36 $ hg update 0 > /dev/null
37 $ echo "revision 4" > f
37 $ echo "revision 4" > f
38 $ hg commit -Am "revision 4"
38 $ hg commit -Am "revision 4"
39 created new head
39 created new head
40
40
41 $ echo "[merge-tools]" > .hg/hgrc
41 $ echo "[merge-tools]" > .hg/hgrc
42
42
43 $ beforemerge() {
43 $ beforemerge() {
44 > cat .hg/hgrc
44 > cat .hg/hgrc
45 > echo "# hg update -C 1"
45 > echo "# hg update -C 1"
46 > hg update -C 1 > /dev/null
46 > hg update -C 1 > /dev/null
47 > }
47 > }
48 $ aftermerge() {
48 $ aftermerge() {
49 > echo "# cat f"
49 > echo "# cat f"
50 > cat f
50 > cat f
51 > echo "# hg stat"
51 > echo "# hg stat"
52 > hg stat
52 > hg stat
53 > echo "# hg resolve --list"
53 > echo "# hg resolve --list"
54 > hg resolve --list
54 > hg resolve --list
55 > rm -f f.orig
55 > rm -f f.orig
56 > }
56 > }
57
57
58 Tool selection
58 Tool selection
59
59
60 default is internal merge:
60 default is internal merge:
61
61
62 $ beforemerge
62 $ beforemerge
63 [merge-tools]
63 [merge-tools]
64 # hg update -C 1
64 # hg update -C 1
65
65
66 hg merge -r 2
66 hg merge -r 2
67 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
67 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
68 running from a devel copy, not a temp installation
68 running from a devel copy, not a temp installation
69
69
70 $ PATH="$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
70 $ PATH="$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
71 merging f
71 merging f
72 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
72 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
73 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
73 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
74 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
74 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
75 [1]
75 [1]
76 $ aftermerge
76 $ aftermerge
77 # cat f
77 # cat f
78 <<<<<<< local: ef83787e2614 - test: revision 1
78 <<<<<<< local: ef83787e2614 - test: revision 1
79 revision 1
79 revision 1
80 =======
80 =======
81 revision 2
81 revision 2
82 >>>>>>> other: 0185f4e0cf02 - test: revision 2
82 >>>>>>> other: 0185f4e0cf02 - test: revision 2
83 space
83 space
84 # hg stat
84 # hg stat
85 M f
85 M f
86 ? f.orig
86 ? f.orig
87 # hg resolve --list
87 # hg resolve --list
88 U f
88 U f
89
89
90 simplest hgrc using false for merge:
90 simplest hgrc using false for merge:
91
91
92 $ echo "false.whatever=" >> .hg/hgrc
92 $ echo "false.whatever=" >> .hg/hgrc
93 $ beforemerge
93 $ beforemerge
94 [merge-tools]
94 [merge-tools]
95 false.whatever=
95 false.whatever=
96 # hg update -C 1
96 # hg update -C 1
97 $ hg merge -r 2
97 $ hg merge -r 2
98 merging f
98 merging f
99 merging f failed!
99 merging f failed!
100 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
100 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
101 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
101 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
102 [1]
102 [1]
103 $ aftermerge
103 $ aftermerge
104 # cat f
104 # cat f
105 revision 1
105 revision 1
106 space
106 space
107 # hg stat
107 # hg stat
108 M f
108 M f
109 ? f.orig
109 ? f.orig
110 # hg resolve --list
110 # hg resolve --list
111 U f
111 U f
112
112
113 #if unix-permissions
113 #if unix-permissions
114
114
115 unexecutable file in $PATH shouldn't be found:
115 unexecutable file in $PATH shouldn't be found:
116
116
117 $ echo "echo fail" > false
117 $ echo "echo fail" > false
118 $ hg up -qC 1
118 $ hg up -qC 1
119 $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
119 $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
120 merging f
120 merging f
121 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
121 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
123 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
123 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
124 [1]
124 [1]
125 $ rm false
125 $ rm false
126
126
127 #endif
127 #endif
128
128
129 executable directory in $PATH shouldn't be found:
129 executable directory in $PATH shouldn't be found:
130
130
131 $ mkdir false
131 $ mkdir false
132 $ hg up -qC 1
132 $ hg up -qC 1
133 $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
133 $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
134 merging f
134 merging f
135 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
135 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
136 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
136 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
137 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
137 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
138 [1]
138 [1]
139 $ rmdir false
139 $ rmdir false
140
140
141 true with higher .priority gets precedence:
141 true with higher .priority gets precedence:
142
142
143 $ echo "true.priority=1" >> .hg/hgrc
143 $ echo "true.priority=1" >> .hg/hgrc
144 $ beforemerge
144 $ beforemerge
145 [merge-tools]
145 [merge-tools]
146 false.whatever=
146 false.whatever=
147 true.priority=1
147 true.priority=1
148 # hg update -C 1
148 # hg update -C 1
149 $ hg merge -r 2
149 $ hg merge -r 2
150 merging f
150 merging f
151 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
151 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
152 (branch merge, don't forget to commit)
152 (branch merge, don't forget to commit)
153 $ aftermerge
153 $ aftermerge
154 # cat f
154 # cat f
155 revision 1
155 revision 1
156 space
156 space
157 # hg stat
157 # hg stat
158 M f
158 M f
159 # hg resolve --list
159 # hg resolve --list
160 R f
160 R f
161
161
162 unless lowered on command line:
162 unless lowered on command line:
163
163
164 $ beforemerge
164 $ beforemerge
165 [merge-tools]
165 [merge-tools]
166 false.whatever=
166 false.whatever=
167 true.priority=1
167 true.priority=1
168 # hg update -C 1
168 # hg update -C 1
169 $ hg merge -r 2 --config merge-tools.true.priority=-7
169 $ hg merge -r 2 --config merge-tools.true.priority=-7
170 merging f
170 merging f
171 merging f failed!
171 merging f failed!
172 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
172 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
173 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
173 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
174 [1]
174 [1]
175 $ aftermerge
175 $ aftermerge
176 # cat f
176 # cat f
177 revision 1
177 revision 1
178 space
178 space
179 # hg stat
179 # hg stat
180 M f
180 M f
181 ? f.orig
181 ? f.orig
182 # hg resolve --list
182 # hg resolve --list
183 U f
183 U f
184
184
185 or false set higher on command line:
185 or false set higher on command line:
186
186
187 $ beforemerge
187 $ beforemerge
188 [merge-tools]
188 [merge-tools]
189 false.whatever=
189 false.whatever=
190 true.priority=1
190 true.priority=1
191 # hg update -C 1
191 # hg update -C 1
192 $ hg merge -r 2 --config merge-tools.false.priority=117
192 $ hg merge -r 2 --config merge-tools.false.priority=117
193 merging f
193 merging f
194 merging f failed!
194 merging f failed!
195 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
195 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
196 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
196 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
197 [1]
197 [1]
198 $ aftermerge
198 $ aftermerge
199 # cat f
199 # cat f
200 revision 1
200 revision 1
201 space
201 space
202 # hg stat
202 # hg stat
203 M f
203 M f
204 ? f.orig
204 ? f.orig
205 # hg resolve --list
205 # hg resolve --list
206 U f
206 U f
207
207
208 or true set to disabled:
208 or true set to disabled:
209 $ beforemerge
209 $ beforemerge
210 [merge-tools]
210 [merge-tools]
211 false.whatever=
211 false.whatever=
212 true.priority=1
212 true.priority=1
213 # hg update -C 1
213 # hg update -C 1
214 $ hg merge -r 2 --config merge-tools.true.disabled=yes
214 $ hg merge -r 2 --config merge-tools.true.disabled=yes
215 merging f
215 merging f
216 merging f failed!
216 merging f failed!
217 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
217 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
218 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
218 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
219 [1]
219 [1]
220 $ aftermerge
220 $ aftermerge
221 # cat f
221 # cat f
222 revision 1
222 revision 1
223 space
223 space
224 # hg stat
224 # hg stat
225 M f
225 M f
226 ? f.orig
226 ? f.orig
227 # hg resolve --list
227 # hg resolve --list
228 U f
228 U f
229
229
230 or true.executable not found in PATH:
230 or true.executable not found in PATH:
231
231
232 $ beforemerge
232 $ beforemerge
233 [merge-tools]
233 [merge-tools]
234 false.whatever=
234 false.whatever=
235 true.priority=1
235 true.priority=1
236 # hg update -C 1
236 # hg update -C 1
237 $ hg merge -r 2 --config merge-tools.true.executable=nonexistentmergetool
237 $ hg merge -r 2 --config merge-tools.true.executable=nonexistentmergetool
238 merging f
238 merging f
239 merging f failed!
239 merging f failed!
240 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
240 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
241 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
241 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
242 [1]
242 [1]
243 $ aftermerge
243 $ aftermerge
244 # cat f
244 # cat f
245 revision 1
245 revision 1
246 space
246 space
247 # hg stat
247 # hg stat
248 M f
248 M f
249 ? f.orig
249 ? f.orig
250 # hg resolve --list
250 # hg resolve --list
251 U f
251 U f
252
252
253 or true.executable with bogus path:
253 or true.executable with bogus path:
254
254
255 $ beforemerge
255 $ beforemerge
256 [merge-tools]
256 [merge-tools]
257 false.whatever=
257 false.whatever=
258 true.priority=1
258 true.priority=1
259 # hg update -C 1
259 # hg update -C 1
260 $ hg merge -r 2 --config merge-tools.true.executable=/nonexistent/mergetool
260 $ hg merge -r 2 --config merge-tools.true.executable=/nonexistent/mergetool
261 merging f
261 merging f
262 merging f failed!
262 merging f failed!
263 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
263 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
264 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
264 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
265 [1]
265 [1]
266 $ aftermerge
266 $ aftermerge
267 # cat f
267 # cat f
268 revision 1
268 revision 1
269 space
269 space
270 # hg stat
270 # hg stat
271 M f
271 M f
272 ? f.orig
272 ? f.orig
273 # hg resolve --list
273 # hg resolve --list
274 U f
274 U f
275
275
276 but true.executable set to cat found in PATH works:
276 but true.executable set to cat found in PATH works:
277
277
278 $ echo "true.executable=cat" >> .hg/hgrc
278 $ echo "true.executable=cat" >> .hg/hgrc
279 $ beforemerge
279 $ beforemerge
280 [merge-tools]
280 [merge-tools]
281 false.whatever=
281 false.whatever=
282 true.priority=1
282 true.priority=1
283 true.executable=cat
283 true.executable=cat
284 # hg update -C 1
284 # hg update -C 1
285 $ hg merge -r 2
285 $ hg merge -r 2
286 merging f
286 merging f
287 revision 1
287 revision 1
288 space
288 space
289 revision 0
289 revision 0
290 space
290 space
291 revision 2
291 revision 2
292 space
292 space
293 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
293 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
294 (branch merge, don't forget to commit)
294 (branch merge, don't forget to commit)
295 $ aftermerge
295 $ aftermerge
296 # cat f
296 # cat f
297 revision 1
297 revision 1
298 space
298 space
299 # hg stat
299 # hg stat
300 M f
300 M f
301 # hg resolve --list
301 # hg resolve --list
302 R f
302 R f
303
303
304 and true.executable set to cat with path works:
304 and true.executable set to cat with path works:
305
305
306 $ beforemerge
306 $ beforemerge
307 [merge-tools]
307 [merge-tools]
308 false.whatever=
308 false.whatever=
309 true.priority=1
309 true.priority=1
310 true.executable=cat
310 true.executable=cat
311 # hg update -C 1
311 # hg update -C 1
312 $ hg merge -r 2 --config merge-tools.true.executable=cat
312 $ hg merge -r 2 --config merge-tools.true.executable=cat
313 merging f
313 merging f
314 revision 1
314 revision 1
315 space
315 space
316 revision 0
316 revision 0
317 space
317 space
318 revision 2
318 revision 2
319 space
319 space
320 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
320 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
321 (branch merge, don't forget to commit)
321 (branch merge, don't forget to commit)
322 $ aftermerge
322 $ aftermerge
323 # cat f
323 # cat f
324 revision 1
324 revision 1
325 space
325 space
326 # hg stat
326 # hg stat
327 M f
327 M f
328 # hg resolve --list
328 # hg resolve --list
329 R f
329 R f
330
330
331 #if unix-permissions
331 #if unix-permissions
332
332
333 environment variables in true.executable are handled:
333 environment variables in true.executable are handled:
334
334
335 $ echo 'echo "custom merge tool"' > .hg/merge.sh
335 $ echo 'echo "custom merge tool"' > .hg/merge.sh
336 $ beforemerge
336 $ beforemerge
337 [merge-tools]
337 [merge-tools]
338 false.whatever=
338 false.whatever=
339 true.priority=1
339 true.priority=1
340 true.executable=cat
340 true.executable=cat
341 # hg update -C 1
341 # hg update -C 1
342 $ hg --config merge-tools.true.executable='sh' \
342 $ hg --config merge-tools.true.executable='sh' \
343 > --config merge-tools.true.args=.hg/merge.sh \
343 > --config merge-tools.true.args=.hg/merge.sh \
344 > merge -r 2
344 > merge -r 2
345 merging f
345 merging f
346 custom merge tool
346 custom merge tool
347 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
347 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
348 (branch merge, don't forget to commit)
348 (branch merge, don't forget to commit)
349 $ aftermerge
349 $ aftermerge
350 # cat f
350 # cat f
351 revision 1
351 revision 1
352 space
352 space
353 # hg stat
353 # hg stat
354 M f
354 M f
355 # hg resolve --list
355 # hg resolve --list
356 R f
356 R f
357
357
358 #endif
358 #endif
359
359
360 Tool selection and merge-patterns
360 Tool selection and merge-patterns
361
361
362 merge-patterns specifies new tool false:
362 merge-patterns specifies new tool false:
363
363
364 $ beforemerge
364 $ beforemerge
365 [merge-tools]
365 [merge-tools]
366 false.whatever=
366 false.whatever=
367 true.priority=1
367 true.priority=1
368 true.executable=cat
368 true.executable=cat
369 # hg update -C 1
369 # hg update -C 1
370 $ hg merge -r 2 --config merge-patterns.f=false
370 $ hg merge -r 2 --config merge-patterns.f=false
371 merging f
371 merging f
372 merging f failed!
372 merging f failed!
373 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
373 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
374 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
374 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
375 [1]
375 [1]
376 $ aftermerge
376 $ aftermerge
377 # cat f
377 # cat f
378 revision 1
378 revision 1
379 space
379 space
380 # hg stat
380 # hg stat
381 M f
381 M f
382 ? f.orig
382 ? f.orig
383 # hg resolve --list
383 # hg resolve --list
384 U f
384 U f
385
385
386 merge-patterns specifies executable not found in PATH and gets warning:
386 merge-patterns specifies executable not found in PATH and gets warning:
387
387
388 $ beforemerge
388 $ beforemerge
389 [merge-tools]
389 [merge-tools]
390 false.whatever=
390 false.whatever=
391 true.priority=1
391 true.priority=1
392 true.executable=cat
392 true.executable=cat
393 # hg update -C 1
393 # hg update -C 1
394 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool
394 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool
395 couldn't find merge tool true specified for f
395 couldn't find merge tool true specified for f
396 merging f
396 merging f
397 couldn't find merge tool true specified for f
397 couldn't find merge tool true specified for f
398 merging f failed!
398 merging f failed!
399 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
399 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
400 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
400 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
401 [1]
401 [1]
402 $ aftermerge
402 $ aftermerge
403 # cat f
403 # cat f
404 revision 1
404 revision 1
405 space
405 space
406 # hg stat
406 # hg stat
407 M f
407 M f
408 ? f.orig
408 ? f.orig
409 # hg resolve --list
409 # hg resolve --list
410 U f
410 U f
411
411
412 merge-patterns specifies executable with bogus path and gets warning:
412 merge-patterns specifies executable with bogus path and gets warning:
413
413
414 $ beforemerge
414 $ beforemerge
415 [merge-tools]
415 [merge-tools]
416 false.whatever=
416 false.whatever=
417 true.priority=1
417 true.priority=1
418 true.executable=cat
418 true.executable=cat
419 # hg update -C 1
419 # hg update -C 1
420 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexistent/mergetool
420 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexistent/mergetool
421 couldn't find merge tool true specified for f
421 couldn't find merge tool true specified for f
422 merging f
422 merging f
423 couldn't find merge tool true specified for f
423 couldn't find merge tool true specified for f
424 merging f failed!
424 merging f failed!
425 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
425 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
426 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
426 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
427 [1]
427 [1]
428 $ aftermerge
428 $ aftermerge
429 # cat f
429 # cat f
430 revision 1
430 revision 1
431 space
431 space
432 # hg stat
432 # hg stat
433 M f
433 M f
434 ? f.orig
434 ? f.orig
435 # hg resolve --list
435 # hg resolve --list
436 U f
436 U f
437
437
438 ui.merge overrules priority
438 ui.merge overrules priority
439
439
440 ui.merge specifies false:
440 ui.merge specifies false:
441
441
442 $ beforemerge
442 $ beforemerge
443 [merge-tools]
443 [merge-tools]
444 false.whatever=
444 false.whatever=
445 true.priority=1
445 true.priority=1
446 true.executable=cat
446 true.executable=cat
447 # hg update -C 1
447 # hg update -C 1
448 $ hg merge -r 2 --config ui.merge=false
448 $ hg merge -r 2 --config ui.merge=false
449 merging f
449 merging f
450 merging f failed!
450 merging f failed!
451 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
451 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
452 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
452 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
453 [1]
453 [1]
454 $ aftermerge
454 $ aftermerge
455 # cat f
455 # cat f
456 revision 1
456 revision 1
457 space
457 space
458 # hg stat
458 # hg stat
459 M f
459 M f
460 ? f.orig
460 ? f.orig
461 # hg resolve --list
461 # hg resolve --list
462 U f
462 U f
463
463
464 ui.merge specifies internal:fail:
464 ui.merge specifies internal:fail:
465
465
466 $ beforemerge
466 $ beforemerge
467 [merge-tools]
467 [merge-tools]
468 false.whatever=
468 false.whatever=
469 true.priority=1
469 true.priority=1
470 true.executable=cat
470 true.executable=cat
471 # hg update -C 1
471 # hg update -C 1
472 $ hg merge -r 2 --config ui.merge=internal:fail
472 $ hg merge -r 2 --config ui.merge=internal:fail
473 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
473 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
474 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
474 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
475 [1]
475 [1]
476 $ aftermerge
476 $ aftermerge
477 # cat f
477 # cat f
478 revision 1
478 revision 1
479 space
479 space
480 # hg stat
480 # hg stat
481 M f
481 M f
482 # hg resolve --list
482 # hg resolve --list
483 U f
483 U f
484
484
485 ui.merge specifies :local (without internal prefix):
485 ui.merge specifies :local (without internal prefix):
486
486
487 $ beforemerge
487 $ beforemerge
488 [merge-tools]
488 [merge-tools]
489 false.whatever=
489 false.whatever=
490 true.priority=1
490 true.priority=1
491 true.executable=cat
491 true.executable=cat
492 # hg update -C 1
492 # hg update -C 1
493 $ hg merge -r 2 --config ui.merge=:local
493 $ hg merge -r 2 --config ui.merge=:local
494 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
494 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
495 (branch merge, don't forget to commit)
495 (branch merge, don't forget to commit)
496 $ aftermerge
496 $ aftermerge
497 # cat f
497 # cat f
498 revision 1
498 revision 1
499 space
499 space
500 # hg stat
500 # hg stat
501 M f
501 M f
502 # hg resolve --list
502 # hg resolve --list
503 R f
503 R f
504
504
505 ui.merge specifies internal:other:
505 ui.merge specifies internal:other:
506
506
507 $ beforemerge
507 $ beforemerge
508 [merge-tools]
508 [merge-tools]
509 false.whatever=
509 false.whatever=
510 true.priority=1
510 true.priority=1
511 true.executable=cat
511 true.executable=cat
512 # hg update -C 1
512 # hg update -C 1
513 $ hg merge -r 2 --config ui.merge=internal:other
513 $ hg merge -r 2 --config ui.merge=internal:other
514 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
514 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
515 (branch merge, don't forget to commit)
515 (branch merge, don't forget to commit)
516 $ aftermerge
516 $ aftermerge
517 # cat f
517 # cat f
518 revision 2
518 revision 2
519 space
519 space
520 # hg stat
520 # hg stat
521 M f
521 M f
522 # hg resolve --list
522 # hg resolve --list
523 R f
523 R f
524
524
525 ui.merge specifies internal:prompt:
525 ui.merge specifies internal:prompt:
526
526
527 $ beforemerge
527 $ beforemerge
528 [merge-tools]
528 [merge-tools]
529 false.whatever=
529 false.whatever=
530 true.priority=1
530 true.priority=1
531 true.executable=cat
531 true.executable=cat
532 # hg update -C 1
532 # hg update -C 1
533 $ hg merge -r 2 --config ui.merge=internal:prompt
533 $ hg merge -r 2 --config ui.merge=internal:prompt
534 no tool found to merge f
534 no tool found to merge f
535 keep (l)ocal or take (o)ther? l
535 keep (l)ocal or take (o)ther? l
536 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
536 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
537 (branch merge, don't forget to commit)
537 (branch merge, don't forget to commit)
538 $ aftermerge
538 $ aftermerge
539 # cat f
539 # cat f
540 revision 1
540 revision 1
541 space
541 space
542 # hg stat
542 # hg stat
543 M f
543 M f
544 # hg resolve --list
544 # hg resolve --list
545 R f
545 R f
546
546
547 prompt with EOF
547 prompt with EOF
548
548
549 $ beforemerge
549 $ beforemerge
550 [merge-tools]
550 [merge-tools]
551 false.whatever=
551 false.whatever=
552 true.priority=1
552 true.priority=1
553 true.executable=cat
553 true.executable=cat
554 # hg update -C 1
554 # hg update -C 1
555 $ hg merge -r 2 --config ui.merge=internal:prompt --config ui.interactive=true
555 $ hg merge -r 2 --config ui.merge=internal:prompt --config ui.interactive=true
556 no tool found to merge f
556 no tool found to merge f
557 keep (l)ocal or take (o)ther?
557 keep (l)ocal or take (o)ther?
558 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
558 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
559 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
559 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
560 [1]
560 [1]
561 $ aftermerge
561 $ aftermerge
562 # cat f
562 # cat f
563 revision 1
563 revision 1
564 space
564 space
565 # hg stat
565 # hg stat
566 M f
566 M f
567 # hg resolve --list
567 # hg resolve --list
568 U f
568 U f
569 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
569 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
570 no tool found to merge f
570 no tool found to merge f
571 keep (l)ocal or take (o)ther?
571 keep (l)ocal or take (o)ther?
572 [1]
572 [1]
573 $ aftermerge
573 $ aftermerge
574 # cat f
574 # cat f
575 revision 1
575 revision 1
576 space
576 space
577 # hg stat
577 # hg stat
578 M f
578 M f
579 ? f.orig
579 ? f.orig
580 # hg resolve --list
580 # hg resolve --list
581 U f
581 U f
582 $ rm f
582 $ rm f
583 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
583 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
584 no tool found to merge f
584 no tool found to merge f
585 keep (l)ocal or take (o)ther?
585 keep (l)ocal or take (o)ther?
586 [1]
586 [1]
587 $ aftermerge
587 $ aftermerge
588 # cat f
588 # cat f
589 revision 1
589 revision 1
590 space
590 space
591 # hg stat
591 # hg stat
592 M f
592 M f
593 # hg resolve --list
593 # hg resolve --list
594 U f
594 U f
595 $ hg resolve --all --config ui.merge=internal:prompt
595 $ hg resolve --all --config ui.merge=internal:prompt
596 no tool found to merge f
596 no tool found to merge f
597 keep (l)ocal or take (o)ther? l
597 keep (l)ocal or take (o)ther? l
598 (no more unresolved files)
598 (no more unresolved files)
599 $ aftermerge
599 $ aftermerge
600 # cat f
600 # cat f
601 revision 1
601 revision 1
602 space
602 space
603 # hg stat
603 # hg stat
604 M f
604 M f
605 ? f.orig
605 ? f.orig
606 # hg resolve --list
606 # hg resolve --list
607 R f
607 R f
608
608
609 ui.merge specifies internal:dump:
609 ui.merge specifies internal:dump:
610
610
611 $ beforemerge
611 $ beforemerge
612 [merge-tools]
612 [merge-tools]
613 false.whatever=
613 false.whatever=
614 true.priority=1
614 true.priority=1
615 true.executable=cat
615 true.executable=cat
616 # hg update -C 1
616 # hg update -C 1
617 $ hg merge -r 2 --config ui.merge=internal:dump
617 $ hg merge -r 2 --config ui.merge=internal:dump
618 merging f
618 merging f
619 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
619 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
620 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
620 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
621 [1]
621 [1]
622 $ aftermerge
622 $ aftermerge
623 # cat f
623 # cat f
624 revision 1
624 revision 1
625 space
625 space
626 # hg stat
626 # hg stat
627 M f
627 M f
628 ? f.base
628 ? f.base
629 ? f.local
629 ? f.local
630 ? f.orig
630 ? f.orig
631 ? f.other
631 ? f.other
632 # hg resolve --list
632 # hg resolve --list
633 U f
633 U f
634
634
635 f.base:
635 f.base:
636
636
637 $ cat f.base
637 $ cat f.base
638 revision 0
638 revision 0
639 space
639 space
640
640
641 f.local:
641 f.local:
642
642
643 $ cat f.local
643 $ cat f.local
644 revision 1
644 revision 1
645 space
645 space
646
646
647 f.other:
647 f.other:
648
648
649 $ cat f.other
649 $ cat f.other
650 revision 2
650 revision 2
651 space
651 space
652 $ rm f.base f.local f.other
652 $ rm f.base f.local f.other
653
653
654 ui.merge specifies internal:other but is overruled by pattern for false:
654 ui.merge specifies internal:other but is overruled by pattern for false:
655
655
656 $ beforemerge
656 $ beforemerge
657 [merge-tools]
657 [merge-tools]
658 false.whatever=
658 false.whatever=
659 true.priority=1
659 true.priority=1
660 true.executable=cat
660 true.executable=cat
661 # hg update -C 1
661 # hg update -C 1
662 $ hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
662 $ hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
663 merging f
663 merging f
664 merging f failed!
664 merging f failed!
665 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
665 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
666 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
666 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
667 [1]
667 [1]
668 $ aftermerge
668 $ aftermerge
669 # cat f
669 # cat f
670 revision 1
670 revision 1
671 space
671 space
672 # hg stat
672 # hg stat
673 M f
673 M f
674 ? f.orig
674 ? f.orig
675 # hg resolve --list
675 # hg resolve --list
676 U f
676 U f
677
677
678 Premerge
678 Premerge
679
679
680 ui.merge specifies internal:other but is overruled by --tool=false
680 ui.merge specifies internal:other but is overruled by --tool=false
681
681
682 $ beforemerge
682 $ beforemerge
683 [merge-tools]
683 [merge-tools]
684 false.whatever=
684 false.whatever=
685 true.priority=1
685 true.priority=1
686 true.executable=cat
686 true.executable=cat
687 # hg update -C 1
687 # hg update -C 1
688 $ hg merge -r 2 --config ui.merge=internal:other --tool=false
688 $ hg merge -r 2 --config ui.merge=internal:other --tool=false
689 merging f
689 merging f
690 merging f failed!
690 merging f failed!
691 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
691 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
692 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
692 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
693 [1]
693 [1]
694 $ aftermerge
694 $ aftermerge
695 # cat f
695 # cat f
696 revision 1
696 revision 1
697 space
697 space
698 # hg stat
698 # hg stat
699 M f
699 M f
700 ? f.orig
700 ? f.orig
701 # hg resolve --list
701 # hg resolve --list
702 U f
702 U f
703
703
704 HGMERGE specifies internal:other but is overruled by --tool=false
704 HGMERGE specifies internal:other but is overruled by --tool=false
705
705
706 $ HGMERGE=internal:other ; export HGMERGE
706 $ HGMERGE=internal:other ; export HGMERGE
707 $ beforemerge
707 $ beforemerge
708 [merge-tools]
708 [merge-tools]
709 false.whatever=
709 false.whatever=
710 true.priority=1
710 true.priority=1
711 true.executable=cat
711 true.executable=cat
712 # hg update -C 1
712 # hg update -C 1
713 $ hg merge -r 2 --tool=false
713 $ hg merge -r 2 --tool=false
714 merging f
714 merging f
715 merging f failed!
715 merging f failed!
716 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
716 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
717 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
717 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
718 [1]
718 [1]
719 $ aftermerge
719 $ aftermerge
720 # cat f
720 # cat f
721 revision 1
721 revision 1
722 space
722 space
723 # hg stat
723 # hg stat
724 M f
724 M f
725 ? f.orig
725 ? f.orig
726 # hg resolve --list
726 # hg resolve --list
727 U f
727 U f
728
728
729 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
729 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
730
730
731 update is a merge ...
731 update is a merge ...
732
732
733 (this also tests that files reverted with '--rev REV' are treated as
733 (this also tests that files reverted with '--rev REV' are treated as
734 "modified", even if none of mode, size and timestamp of them isn't
734 "modified", even if none of mode, size and timestamp of them isn't
735 changed on the filesystem (see also issue4583))
735 changed on the filesystem (see also issue4583))
736
736
737 $ cat >> $HGRCPATH <<EOF
737 $ cat >> $HGRCPATH <<EOF
738 > [fakedirstatewritetime]
738 > [fakedirstatewritetime]
739 > # emulate invoking dirstate.write() via repo.status()
739 > # emulate invoking dirstate.write() via repo.status()
740 > # at 2000-01-01 00:00
740 > # at 2000-01-01 00:00
741 > fakenow = 200001010000
741 > fakenow = 200001010000
742 > EOF
742 > EOF
743
743
744 $ beforemerge
744 $ beforemerge
745 [merge-tools]
745 [merge-tools]
746 false.whatever=
746 false.whatever=
747 true.priority=1
747 true.priority=1
748 true.executable=cat
748 true.executable=cat
749 # hg update -C 1
749 # hg update -C 1
750 $ hg update -q 0
750 $ hg update -q 0
751 $ f -s f
751 $ f -s f
752 f: size=17
752 f: size=17
753 $ touch -t 200001010000 f
753 $ touch -t 200001010000 f
754 $ hg debugrebuildstate
754 $ hg debugrebuildstate
755 $ cat >> $HGRCPATH <<EOF
755 $ cat >> $HGRCPATH <<EOF
756 > [extensions]
756 > [extensions]
757 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
757 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
758 > EOF
758 > EOF
759 $ hg revert -q -r 1 .
759 $ hg revert -q -r 1 .
760 $ cat >> $HGRCPATH <<EOF
760 $ cat >> $HGRCPATH <<EOF
761 > [extensions]
761 > [extensions]
762 > fakedirstatewritetime = !
762 > fakedirstatewritetime = !
763 > EOF
763 > EOF
764 $ f -s f
764 $ f -s f
765 f: size=17
765 f: size=17
766 $ touch -t 200001010000 f
766 $ touch -t 200001010000 f
767 $ hg status f
767 $ hg status f
768 M f
768 M f
769 $ hg update -r 2
769 $ hg update -r 2
770 merging f
770 merging f
771 revision 1
771 revision 1
772 space
772 space
773 revision 0
773 revision 0
774 space
774 space
775 revision 2
775 revision 2
776 space
776 space
777 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
777 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
778 $ aftermerge
778 $ aftermerge
779 # cat f
779 # cat f
780 revision 1
780 revision 1
781 space
781 space
782 # hg stat
782 # hg stat
783 M f
783 M f
784 # hg resolve --list
784 # hg resolve --list
785 R f
785 R f
786
786
787 update should also have --tool
787 update should also have --tool
788
788
789 $ beforemerge
789 $ beforemerge
790 [merge-tools]
790 [merge-tools]
791 false.whatever=
791 false.whatever=
792 true.priority=1
792 true.priority=1
793 true.executable=cat
793 true.executable=cat
794 # hg update -C 1
794 # hg update -C 1
795 $ hg update -q 0
795 $ hg update -q 0
796 $ f -s f
796 $ f -s f
797 f: size=17
797 f: size=17
798 $ touch -t 200001010000 f
798 $ touch -t 200001010000 f
799 $ hg debugrebuildstate
799 $ hg debugrebuildstate
800 $ cat >> $HGRCPATH <<EOF
800 $ cat >> $HGRCPATH <<EOF
801 > [extensions]
801 > [extensions]
802 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
802 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
803 > EOF
803 > EOF
804 $ hg revert -q -r 1 .
804 $ hg revert -q -r 1 .
805 $ cat >> $HGRCPATH <<EOF
805 $ cat >> $HGRCPATH <<EOF
806 > [extensions]
806 > [extensions]
807 > fakedirstatewritetime = !
807 > fakedirstatewritetime = !
808 > EOF
808 > EOF
809 $ f -s f
809 $ f -s f
810 f: size=17
810 f: size=17
811 $ touch -t 200001010000 f
811 $ touch -t 200001010000 f
812 $ hg status f
812 $ hg status f
813 M f
813 M f
814 $ hg update -r 2 --tool false
814 $ hg update -r 2 --tool false
815 merging f
815 merging f
816 merging f failed!
816 merging f failed!
817 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
817 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
818 use 'hg resolve' to retry unresolved file merges
818 use 'hg resolve' to retry unresolved file merges
819 [1]
819 [1]
820 $ aftermerge
820 $ aftermerge
821 # cat f
821 # cat f
822 revision 1
822 revision 1
823 space
823 space
824 # hg stat
824 # hg stat
825 M f
825 M f
826 ? f.orig
826 ? f.orig
827 # hg resolve --list
827 # hg resolve --list
828 U f
828 U f
829
829
830 Default is silent simplemerge:
830 Default is silent simplemerge:
831
831
832 $ beforemerge
832 $ beforemerge
833 [merge-tools]
833 [merge-tools]
834 false.whatever=
834 false.whatever=
835 true.priority=1
835 true.priority=1
836 true.executable=cat
836 true.executable=cat
837 # hg update -C 1
837 # hg update -C 1
838 $ hg merge -r 3
838 $ hg merge -r 3
839 merging f
839 merging f
840 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
840 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
841 (branch merge, don't forget to commit)
841 (branch merge, don't forget to commit)
842 $ aftermerge
842 $ aftermerge
843 # cat f
843 # cat f
844 revision 1
844 revision 1
845 space
845 space
846 revision 3
846 revision 3
847 # hg stat
847 # hg stat
848 M f
848 M f
849 # hg resolve --list
849 # hg resolve --list
850 R f
850 R f
851
851
852 .premerge=True is same:
852 .premerge=True is same:
853
853
854 $ beforemerge
854 $ beforemerge
855 [merge-tools]
855 [merge-tools]
856 false.whatever=
856 false.whatever=
857 true.priority=1
857 true.priority=1
858 true.executable=cat
858 true.executable=cat
859 # hg update -C 1
859 # hg update -C 1
860 $ hg merge -r 3 --config merge-tools.true.premerge=True
860 $ hg merge -r 3 --config merge-tools.true.premerge=True
861 merging f
861 merging f
862 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
862 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
863 (branch merge, don't forget to commit)
863 (branch merge, don't forget to commit)
864 $ aftermerge
864 $ aftermerge
865 # cat f
865 # cat f
866 revision 1
866 revision 1
867 space
867 space
868 revision 3
868 revision 3
869 # hg stat
869 # hg stat
870 M f
870 M f
871 # hg resolve --list
871 # hg resolve --list
872 R f
872 R f
873
873
874 .premerge=False executes merge-tool:
874 .premerge=False executes merge-tool:
875
875
876 $ beforemerge
876 $ beforemerge
877 [merge-tools]
877 [merge-tools]
878 false.whatever=
878 false.whatever=
879 true.priority=1
879 true.priority=1
880 true.executable=cat
880 true.executable=cat
881 # hg update -C 1
881 # hg update -C 1
882 $ hg merge -r 3 --config merge-tools.true.premerge=False
882 $ hg merge -r 3 --config merge-tools.true.premerge=False
883 merging f
883 merging f
884 revision 1
884 revision 1
885 space
885 space
886 revision 0
886 revision 0
887 space
887 space
888 revision 0
888 revision 0
889 space
889 space
890 revision 3
890 revision 3
891 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
891 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
892 (branch merge, don't forget to commit)
892 (branch merge, don't forget to commit)
893 $ aftermerge
893 $ aftermerge
894 # cat f
894 # cat f
895 revision 1
895 revision 1
896 space
896 space
897 # hg stat
897 # hg stat
898 M f
898 M f
899 # hg resolve --list
899 # hg resolve --list
900 R f
900 R f
901
901
902 premerge=keep keeps conflict markers in:
902 premerge=keep keeps conflict markers in:
903
903
904 $ beforemerge
904 $ beforemerge
905 [merge-tools]
905 [merge-tools]
906 false.whatever=
906 false.whatever=
907 true.priority=1
907 true.priority=1
908 true.executable=cat
908 true.executable=cat
909 # hg update -C 1
909 # hg update -C 1
910 $ hg merge -r 4 --config merge-tools.true.premerge=keep
910 $ hg merge -r 4 --config merge-tools.true.premerge=keep
911 merging f
911 merging f
912 <<<<<<< local: ef83787e2614 - test: revision 1
912 <<<<<<< local: ef83787e2614 - test: revision 1
913 revision 1
913 revision 1
914 space
914 space
915 =======
915 =======
916 revision 4
916 revision 4
917 >>>>>>> other: 81448d39c9a0 - test: revision 4
917 >>>>>>> other: 81448d39c9a0 - test: revision 4
918 revision 0
918 revision 0
919 space
919 space
920 revision 4
920 revision 4
921 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
921 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
922 (branch merge, don't forget to commit)
922 (branch merge, don't forget to commit)
923 $ aftermerge
923 $ aftermerge
924 # cat f
924 # cat f
925 <<<<<<< local: ef83787e2614 - test: revision 1
925 <<<<<<< local: ef83787e2614 - test: revision 1
926 revision 1
926 revision 1
927 space
927 space
928 =======
928 =======
929 revision 4
929 revision 4
930 >>>>>>> other: 81448d39c9a0 - test: revision 4
930 >>>>>>> other: 81448d39c9a0 - test: revision 4
931 # hg stat
931 # hg stat
932 M f
932 M f
933 # hg resolve --list
933 # hg resolve --list
934 R f
934 R f
935
935
936 premerge=keep-merge3 keeps conflict markers with base content:
936 premerge=keep-merge3 keeps conflict markers with base content:
937
937
938 $ beforemerge
938 $ beforemerge
939 [merge-tools]
939 [merge-tools]
940 false.whatever=
940 false.whatever=
941 true.priority=1
941 true.priority=1
942 true.executable=cat
942 true.executable=cat
943 # hg update -C 1
943 # hg update -C 1
944 $ hg merge -r 4 --config merge-tools.true.premerge=keep-merge3
944 $ hg merge -r 4 --config merge-tools.true.premerge=keep-merge3
945 merging f
945 merging f
946 <<<<<<< local: ef83787e2614 - test: revision 1
946 <<<<<<< local: ef83787e2614 - test: revision 1
947 revision 1
947 revision 1
948 space
948 space
949 ||||||| base
949 ||||||| base
950 revision 0
950 revision 0
951 space
951 space
952 =======
952 =======
953 revision 4
953 revision 4
954 >>>>>>> other: 81448d39c9a0 - test: revision 4
954 >>>>>>> other: 81448d39c9a0 - test: revision 4
955 revision 0
955 revision 0
956 space
956 space
957 revision 4
957 revision 4
958 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
958 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
959 (branch merge, don't forget to commit)
959 (branch merge, don't forget to commit)
960 $ aftermerge
960 $ aftermerge
961 # cat f
961 # cat f
962 <<<<<<< local: ef83787e2614 - test: revision 1
962 <<<<<<< local: ef83787e2614 - test: revision 1
963 revision 1
963 revision 1
964 space
964 space
965 ||||||| base
965 ||||||| base
966 revision 0
966 revision 0
967 space
967 space
968 =======
968 =======
969 revision 4
969 revision 4
970 >>>>>>> other: 81448d39c9a0 - test: revision 4
970 >>>>>>> other: 81448d39c9a0 - test: revision 4
971 # hg stat
971 # hg stat
972 M f
972 M f
973 # hg resolve --list
973 # hg resolve --list
974 R f
974 R f
975
975
976
976
977 Tool execution
977 Tool execution
978
978
979 set tools.args explicit to include $base $local $other $output:
979 set tools.args explicit to include $base $local $other $output:
980
980
981 $ beforemerge
981 $ beforemerge
982 [merge-tools]
982 [merge-tools]
983 false.whatever=
983 false.whatever=
984 true.priority=1
984 true.priority=1
985 true.executable=cat
985 true.executable=cat
986 # hg update -C 1
986 # hg update -C 1
987 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
987 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
988 > | sed 's,==> .* <==,==> ... <==,g'
988 > | sed 's,==> .* <==,==> ... <==,g'
989 merging f
989 merging f
990 ==> ... <==
990 ==> ... <==
991 revision 0
991 revision 0
992 space
992 space
993
993
994 ==> ... <==
994 ==> ... <==
995 revision 1
995 revision 1
996 space
996 space
997
997
998 ==> ... <==
998 ==> ... <==
999 revision 2
999 revision 2
1000 space
1000 space
1001
1001
1002 ==> ... <==
1002 ==> ... <==
1003 revision 1
1003 revision 1
1004 space
1004 space
1005 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1005 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1006 (branch merge, don't forget to commit)
1006 (branch merge, don't forget to commit)
1007 $ aftermerge
1007 $ aftermerge
1008 # cat f
1008 # cat f
1009 revision 1
1009 revision 1
1010 space
1010 space
1011 # hg stat
1011 # hg stat
1012 M f
1012 M f
1013 # hg resolve --list
1013 # hg resolve --list
1014 R f
1014 R f
1015
1015
1016 Merge with "echo mergeresult > $local":
1016 Merge with "echo mergeresult > $local":
1017
1017
1018 $ beforemerge
1018 $ beforemerge
1019 [merge-tools]
1019 [merge-tools]
1020 false.whatever=
1020 false.whatever=
1021 true.priority=1
1021 true.priority=1
1022 true.executable=cat
1022 true.executable=cat
1023 # hg update -C 1
1023 # hg update -C 1
1024 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
1024 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
1025 merging f
1025 merging f
1026 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1026 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1027 (branch merge, don't forget to commit)
1027 (branch merge, don't forget to commit)
1028 $ aftermerge
1028 $ aftermerge
1029 # cat f
1029 # cat f
1030 mergeresult
1030 mergeresult
1031 # hg stat
1031 # hg stat
1032 M f
1032 M f
1033 # hg resolve --list
1033 # hg resolve --list
1034 R f
1034 R f
1035
1035
1036 - and $local is the file f:
1036 - and $local is the file f:
1037
1037
1038 $ beforemerge
1038 $ beforemerge
1039 [merge-tools]
1039 [merge-tools]
1040 false.whatever=
1040 false.whatever=
1041 true.priority=1
1041 true.priority=1
1042 true.executable=cat
1042 true.executable=cat
1043 # hg update -C 1
1043 # hg update -C 1
1044 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
1044 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
1045 merging f
1045 merging f
1046 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1046 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1047 (branch merge, don't forget to commit)
1047 (branch merge, don't forget to commit)
1048 $ aftermerge
1048 $ aftermerge
1049 # cat f
1049 # cat f
1050 mergeresult
1050 mergeresult
1051 # hg stat
1051 # hg stat
1052 M f
1052 M f
1053 # hg resolve --list
1053 # hg resolve --list
1054 R f
1054 R f
1055
1055
1056 Merge with "echo mergeresult > $output" - the variable is a bit magic:
1056 Merge with "echo mergeresult > $output" - the variable is a bit magic:
1057
1057
1058 $ beforemerge
1058 $ beforemerge
1059 [merge-tools]
1059 [merge-tools]
1060 false.whatever=
1060 false.whatever=
1061 true.priority=1
1061 true.priority=1
1062 true.executable=cat
1062 true.executable=cat
1063 # hg update -C 1
1063 # hg update -C 1
1064 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
1064 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
1065 merging f
1065 merging f
1066 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1066 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1067 (branch merge, don't forget to commit)
1067 (branch merge, don't forget to commit)
1068 $ aftermerge
1068 $ aftermerge
1069 # cat f
1069 # cat f
1070 mergeresult
1070 mergeresult
1071 # hg stat
1071 # hg stat
1072 M f
1072 M f
1073 # hg resolve --list
1073 # hg resolve --list
1074 R f
1074 R f
1075
1075
1076 Merge using tool with a path that must be quoted:
1076 Merge using tool with a path that must be quoted:
1077
1077
1078 $ beforemerge
1078 $ beforemerge
1079 [merge-tools]
1079 [merge-tools]
1080 false.whatever=
1080 false.whatever=
1081 true.priority=1
1081 true.priority=1
1082 true.executable=cat
1082 true.executable=cat
1083 # hg update -C 1
1083 # hg update -C 1
1084 $ cat <<EOF > 'my merge tool'
1084 $ cat <<EOF > 'my merge tool'
1085 > cat "\$1" "\$2" "\$3" > "\$4"
1085 > cat "\$1" "\$2" "\$3" > "\$4"
1086 > EOF
1086 > EOF
1087 $ hg --config merge-tools.true.executable='sh' \
1087 $ hg --config merge-tools.true.executable='sh' \
1088 > --config merge-tools.true.args='"./my merge tool" $base $local $other $output' \
1088 > --config merge-tools.true.args='"./my merge tool" $base $local $other $output' \
1089 > merge -r 2
1089 > merge -r 2
1090 merging f
1090 merging f
1091 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1091 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1092 (branch merge, don't forget to commit)
1092 (branch merge, don't forget to commit)
1093 $ rm -f 'my merge tool'
1093 $ rm -f 'my merge tool'
1094 $ aftermerge
1094 $ aftermerge
1095 # cat f
1095 # cat f
1096 revision 0
1096 revision 0
1097 space
1097 space
1098 revision 1
1098 revision 1
1099 space
1099 space
1100 revision 2
1100 revision 2
1101 space
1101 space
1102 # hg stat
1102 # hg stat
1103 M f
1103 M f
1104 # hg resolve --list
1104 # hg resolve --list
1105 R f
1105 R f
1106
1106
1107 Issue3581: Merging a filename that needs to be quoted
1107 Issue3581: Merging a filename that needs to be quoted
1108 (This test doesn't work on Windows filesystems even on Linux, so check
1108 (This test doesn't work on Windows filesystems even on Linux, so check
1109 for Unix-like permission)
1109 for Unix-like permission)
1110
1110
1111 #if unix-permissions
1111 #if unix-permissions
1112 $ beforemerge
1112 $ beforemerge
1113 [merge-tools]
1113 [merge-tools]
1114 false.whatever=
1114 false.whatever=
1115 true.priority=1
1115 true.priority=1
1116 true.executable=cat
1116 true.executable=cat
1117 # hg update -C 1
1117 # hg update -C 1
1118 $ echo "revision 5" > '"; exit 1; echo "'
1118 $ echo "revision 5" > '"; exit 1; echo "'
1119 $ hg commit -Am "revision 5"
1119 $ hg commit -Am "revision 5"
1120 adding "; exit 1; echo "
1120 adding "; exit 1; echo "
1121 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1121 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1122 $ hg update -C 1 > /dev/null
1122 $ hg update -C 1 > /dev/null
1123 $ echo "revision 6" > '"; exit 1; echo "'
1123 $ echo "revision 6" > '"; exit 1; echo "'
1124 $ hg commit -Am "revision 6"
1124 $ hg commit -Am "revision 6"
1125 adding "; exit 1; echo "
1125 adding "; exit 1; echo "
1126 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1126 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1127 created new head
1127 created new head
1128 $ hg merge --config merge-tools.true.executable="true" -r 5
1128 $ hg merge --config merge-tools.true.executable="true" -r 5
1129 merging "; exit 1; echo "
1129 merging "; exit 1; echo "
1130 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1130 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1131 (branch merge, don't forget to commit)
1131 (branch merge, don't forget to commit)
1132 $ hg update -C 1 > /dev/null
1132 $ hg update -C 1 > /dev/null
1133 #endif
1133 #endif
1134
1134
1135 Merge post-processing
1135 Merge post-processing
1136
1136
1137 cat is a bad merge-tool and doesn't change:
1137 cat is a bad merge-tool and doesn't change:
1138
1138
1139 $ beforemerge
1139 $ beforemerge
1140 [merge-tools]
1140 [merge-tools]
1141 false.whatever=
1141 false.whatever=
1142 true.priority=1
1142 true.priority=1
1143 true.executable=cat
1143 true.executable=cat
1144 # hg update -C 1
1144 # hg update -C 1
1145 $ hg merge -y -r 2 --config merge-tools.true.checkchanged=1
1145 $ hg merge -y -r 2 --config merge-tools.true.checkchanged=1
1146 merging f
1146 merging f
1147 revision 1
1147 revision 1
1148 space
1148 space
1149 revision 0
1149 revision 0
1150 space
1150 space
1151 revision 2
1151 revision 2
1152 space
1152 space
1153 output file f appears unchanged
1153 output file f appears unchanged
1154 was merge successful (yn)? n
1154 was merge successful (yn)? n
1155 merging f failed!
1155 merging f failed!
1156 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1156 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1157 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1157 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1158 [1]
1158 [1]
1159 $ aftermerge
1159 $ aftermerge
1160 # cat f
1160 # cat f
1161 revision 1
1161 revision 1
1162 space
1162 space
1163 # hg stat
1163 # hg stat
1164 M f
1164 M f
1165 ? f.orig
1165 ? f.orig
1166 # hg resolve --list
1166 # hg resolve --list
1167 U f
1167 U f
1168
1168
1169 #if symlink
1169 #if symlink
1170
1170
1171 internal merge cannot handle symlinks and shouldn't try:
1171 internal merge cannot handle symlinks and shouldn't try:
1172
1172
1173 $ hg update -q -C 1
1173 $ hg update -q -C 1
1174 $ rm f
1174 $ rm f
1175 $ ln -s symlink f
1175 $ ln -s symlink f
1176 $ hg commit -qm 'f is symlink'
1176 $ hg commit -qm 'f is symlink'
1177 $ hg merge -r 2 --tool internal:merge
1177 $ hg merge -r 2 --tool internal:merge
1178 merging f
1178 merging f
1179 warning: internal :merge cannot merge symlinks for f
1179 warning: internal :merge cannot merge symlinks for f
1180 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
1180 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
1181 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1181 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1182 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1182 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1183 [1]
1183 [1]
1184
1184
1185 #endif
1185 #endif
@@ -1,439 +1,439
1 #require symlink execbit
1 #require symlink execbit
2
2
3 $ tellmeabout() {
3 $ tellmeabout() {
4 > if [ -h $1 ]; then
4 > if [ -h $1 ]; then
5 > echo $1 is a symlink:
5 > echo $1 is a symlink:
6 > $TESTDIR/readlink.py $1
6 > $TESTDIR/readlink.py $1
7 > elif [ -x $1 ]; then
7 > elif [ -x $1 ]; then
8 > echo $1 is an executable file with content:
8 > echo $1 is an executable file with content:
9 > cat $1
9 > cat $1
10 > else
10 > else
11 > echo $1 is a plain file with content:
11 > echo $1 is a plain file with content:
12 > cat $1
12 > cat $1
13 > fi
13 > fi
14 > }
14 > }
15
15
16 $ hg init test1
16 $ hg init test1
17 $ cd test1
17 $ cd test1
18
18
19 $ echo a > a
19 $ echo a > a
20 $ hg ci -Aqmadd
20 $ hg ci -Aqmadd
21 $ chmod +x a
21 $ chmod +x a
22 $ hg ci -mexecutable
22 $ hg ci -mexecutable
23
23
24 $ hg up -q 0
24 $ hg up -q 0
25 $ rm a
25 $ rm a
26 $ ln -s symlink a
26 $ ln -s symlink a
27 $ hg ci -msymlink
27 $ hg ci -msymlink
28 created new head
28 created new head
29
29
30 Symlink is local parent, executable is other:
30 Symlink is local parent, executable is other:
31
31
32 $ hg merge --debug
32 $ hg merge --debug
33 searching for copies back to rev 1
33 searching for copies back to rev 1
34 resolving manifests
34 resolving manifests
35 branchmerge: True, force: False, partial: False
35 branchmerge: True, force: False, partial: False
36 ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
36 ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
37 preserving a for resolve of a
37 preserving a for resolve of a
38 a: versions differ -> m (premerge)
38 a: versions differ -> m (premerge)
39 picked tool ':merge' for a (binary False symlink True)
39 picked tool ':merge' for a (binary False symlink True)
40 merging a
40 merging a
41 my a@521a1e40188f+ other a@3574f3e69b1c ancestor a@c334dc3be0da
41 my a@521a1e40188f+ other a@3574f3e69b1c ancestor a@c334dc3be0da
42 warning: internal :merge cannot merge symlinks for a
42 warning: internal :merge cannot merge symlinks for a
43 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
43 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
44 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
44 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
45 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
45 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
46 [1]
46 [1]
47
47
48 $ tellmeabout a
48 $ tellmeabout a
49 a is a symlink:
49 a is a symlink:
50 a -> symlink
50 a -> symlink
51 $ hg resolve a --tool internal:other
51 $ hg resolve a --tool internal:other
52 (no more unresolved files)
52 (no more unresolved files)
53 $ tellmeabout a
53 $ tellmeabout a
54 a is an executable file with content:
54 a is an executable file with content:
55 a
55 a
56 $ hg st
56 $ hg st
57 M a
57 M a
58 ? a.orig
58 ? a.orig
59
59
60 Symlink is other parent, executable is local:
60 Symlink is other parent, executable is local:
61
61
62 $ hg update -C 1
62 $ hg update -C 1
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64
64
65 $ hg merge --debug --tool :union
65 $ hg merge --debug --tool :union
66 searching for copies back to rev 1
66 searching for copies back to rev 1
67 resolving manifests
67 resolving manifests
68 branchmerge: True, force: False, partial: False
68 branchmerge: True, force: False, partial: False
69 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
69 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
70 preserving a for resolve of a
70 preserving a for resolve of a
71 a: versions differ -> m (premerge)
71 a: versions differ -> m (premerge)
72 picked tool ':union' for a (binary False symlink True)
72 picked tool ':union' for a (binary False symlink True)
73 merging a
73 merging a
74 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
74 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
75 warning: internal :union cannot merge symlinks for a
75 warning: internal :union cannot merge symlinks for a
76 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
76 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
77 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
77 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
78 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
78 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
79 [1]
79 [1]
80
80
81 $ tellmeabout a
81 $ tellmeabout a
82 a is an executable file with content:
82 a is an executable file with content:
83 a
83 a
84
84
85 $ hg update -C 1
85 $ hg update -C 1
86 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
87
87
88 $ hg merge --debug --tool :merge3
88 $ hg merge --debug --tool :merge3
89 searching for copies back to rev 1
89 searching for copies back to rev 1
90 resolving manifests
90 resolving manifests
91 branchmerge: True, force: False, partial: False
91 branchmerge: True, force: False, partial: False
92 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
92 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
93 preserving a for resolve of a
93 preserving a for resolve of a
94 a: versions differ -> m (premerge)
94 a: versions differ -> m (premerge)
95 picked tool ':merge3' for a (binary False symlink True)
95 picked tool ':merge3' for a (binary False symlink True)
96 merging a
96 merging a
97 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
97 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
98 warning: internal :merge3 cannot merge symlinks for a
98 warning: internal :merge3 cannot merge symlinks for a
99 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
99 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
100 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
100 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
101 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
101 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
102 [1]
102 [1]
103
103
104 $ tellmeabout a
104 $ tellmeabout a
105 a is an executable file with content:
105 a is an executable file with content:
106 a
106 a
107
107
108 $ hg update -C 1
108 $ hg update -C 1
109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110
110
111 $ hg merge --debug --tool :merge-local
111 $ hg merge --debug --tool :merge-local
112 searching for copies back to rev 1
112 searching for copies back to rev 1
113 resolving manifests
113 resolving manifests
114 branchmerge: True, force: False, partial: False
114 branchmerge: True, force: False, partial: False
115 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
115 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
116 preserving a for resolve of a
116 preserving a for resolve of a
117 a: versions differ -> m (premerge)
117 a: versions differ -> m (premerge)
118 picked tool ':merge-local' for a (binary False symlink True)
118 picked tool ':merge-local' for a (binary False symlink True)
119 merging a
119 merging a
120 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
120 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
121 warning: internal :merge-local cannot merge symlinks for a
121 warning: internal :merge-local cannot merge symlinks for a
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
123 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
123 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
124 [1]
124 [1]
125
125
126 $ tellmeabout a
126 $ tellmeabout a
127 a is an executable file with content:
127 a is an executable file with content:
128 a
128 a
129
129
130 $ hg update -C 1
130 $ hg update -C 1
131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
132
132
133 $ hg merge --debug --tool :merge-other
133 $ hg merge --debug --tool :merge-other
134 searching for copies back to rev 1
134 searching for copies back to rev 1
135 resolving manifests
135 resolving manifests
136 branchmerge: True, force: False, partial: False
136 branchmerge: True, force: False, partial: False
137 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
137 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
138 preserving a for resolve of a
138 preserving a for resolve of a
139 a: versions differ -> m (premerge)
139 a: versions differ -> m (premerge)
140 picked tool ':merge-other' for a (binary False symlink True)
140 picked tool ':merge-other' for a (binary False symlink True)
141 merging a
141 merging a
142 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
142 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
143 warning: internal :merge-other cannot merge symlinks for a
143 warning: internal :merge-other cannot merge symlinks for a
144 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
144 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
145 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
145 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
146 [1]
146 [1]
147
147
148 $ tellmeabout a
148 $ tellmeabout a
149 a is an executable file with content:
149 a is an executable file with content:
150 a
150 a
151
151
152 Update to link without local change should get us a symlink (issue3316):
152 Update to link without local change should get us a symlink (issue3316):
153
153
154 $ hg up -C 0
154 $ hg up -C 0
155 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 $ hg up
156 $ hg up
157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 $ hg st
158 $ hg st
159 ? a.orig
159 ? a.orig
160
160
161 Update to link with local change should cause a merge prompt (issue3200):
161 Update to link with local change should cause a merge prompt (issue3200):
162
162
163 $ hg up -Cq 0
163 $ hg up -Cq 0
164 $ echo data > a
164 $ echo data > a
165 $ HGMERGE= hg up -y --debug
165 $ HGMERGE= hg up -y --debug
166 searching for copies back to rev 2
166 searching for copies back to rev 2
167 resolving manifests
167 resolving manifests
168 branchmerge: False, force: False, partial: False
168 branchmerge: False, force: False, partial: False
169 ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
169 ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
170 preserving a for resolve of a
170 preserving a for resolve of a
171 a: versions differ -> m (premerge)
171 a: versions differ -> m (premerge)
172 (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
172 (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
173 picked tool ':prompt' for a (binary False symlink True)
173 picked tool ':prompt' for a (binary False symlink True)
174 no tool found to merge a
174 no tool found to merge a
175 keep (l)ocal or take (o)ther? l
175 keep (l)ocal or take (o)ther? l
176 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
176 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
177 $ hg diff --git
177 $ hg diff --git
178 diff --git a/a b/a
178 diff --git a/a b/a
179 old mode 120000
179 old mode 120000
180 new mode 100644
180 new mode 100644
181 --- a/a
181 --- a/a
182 +++ b/a
182 +++ b/a
183 @@ -1,1 +1,1 @@
183 @@ -1,1 +1,1 @@
184 -symlink
184 -symlink
185 \ No newline at end of file
185 \ No newline at end of file
186 +data
186 +data
187
187
188
188
189 Test only 'l' change - happens rarely, except when recovering from situations
189 Test only 'l' change - happens rarely, except when recovering from situations
190 where that was what happened.
190 where that was what happened.
191
191
192 $ hg init test2
192 $ hg init test2
193 $ cd test2
193 $ cd test2
194 $ printf base > f
194 $ printf base > f
195 $ hg ci -Aqm0
195 $ hg ci -Aqm0
196 $ echo file > f
196 $ echo file > f
197 $ echo content >> f
197 $ echo content >> f
198 $ hg ci -qm1
198 $ hg ci -qm1
199 $ hg up -qr0
199 $ hg up -qr0
200 $ rm f
200 $ rm f
201 $ ln -s base f
201 $ ln -s base f
202 $ hg ci -qm2
202 $ hg ci -qm2
203 $ hg merge
203 $ hg merge
204 merging f
204 merging f
205 warning: internal :merge cannot merge symlinks for f
205 warning: internal :merge cannot merge symlinks for f
206 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
206 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
207 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
207 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
208 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
208 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
209 [1]
209 [1]
210 $ tellmeabout f
210 $ tellmeabout f
211 f is a symlink:
211 f is a symlink:
212 f -> base
212 f -> base
213
213
214 $ hg up -Cqr1
214 $ hg up -Cqr1
215 $ hg merge
215 $ hg merge
216 merging f
216 merging f
217 warning: internal :merge cannot merge symlinks for f
217 warning: internal :merge cannot merge symlinks for f
218 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
218 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
219 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
219 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
220 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
220 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
221 [1]
221 [1]
222 $ tellmeabout f
222 $ tellmeabout f
223 f is a plain file with content:
223 f is a plain file with content:
224 file
224 file
225 content
225 content
226
226
227 $ cd ..
227 $ cd ..
228
228
229 Test removed 'x' flag merged with change to symlink
229 Test removed 'x' flag merged with change to symlink
230
230
231 $ hg init test3
231 $ hg init test3
232 $ cd test3
232 $ cd test3
233 $ echo f > f
233 $ echo f > f
234 $ chmod +x f
234 $ chmod +x f
235 $ hg ci -Aqm0
235 $ hg ci -Aqm0
236 $ chmod -x f
236 $ chmod -x f
237 $ hg ci -qm1
237 $ hg ci -qm1
238 $ hg up -qr0
238 $ hg up -qr0
239 $ rm f
239 $ rm f
240 $ ln -s dangling f
240 $ ln -s dangling f
241 $ hg ci -qm2
241 $ hg ci -qm2
242 $ hg merge
242 $ hg merge
243 merging f
243 merging f
244 warning: internal :merge cannot merge symlinks for f
244 warning: internal :merge cannot merge symlinks for f
245 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
245 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
246 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
246 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
247 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
247 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
248 [1]
248 [1]
249 $ tellmeabout f
249 $ tellmeabout f
250 f is a symlink:
250 f is a symlink:
251 f -> dangling
251 f -> dangling
252
252
253 $ hg up -Cqr1
253 $ hg up -Cqr1
254 $ hg merge
254 $ hg merge
255 merging f
255 merging f
256 warning: internal :merge cannot merge symlinks for f
256 warning: internal :merge cannot merge symlinks for f
257 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
257 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
258 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
258 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
259 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
259 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
260 [1]
260 [1]
261 $ tellmeabout f
261 $ tellmeabout f
262 f is a plain file with content:
262 f is a plain file with content:
263 f
263 f
264
264
265 Test removed 'x' flag merged with content change - both ways
265 Test removed 'x' flag merged with content change - both ways
266
266
267 $ hg up -Cqr0
267 $ hg up -Cqr0
268 $ echo change > f
268 $ echo change > f
269 $ hg ci -qm3
269 $ hg ci -qm3
270 $ hg merge -r1
270 $ hg merge -r1
271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
272 (branch merge, don't forget to commit)
272 (branch merge, don't forget to commit)
273 $ tellmeabout f
273 $ tellmeabout f
274 f is a plain file with content:
274 f is a plain file with content:
275 change
275 change
276
276
277 $ hg up -qCr1
277 $ hg up -qCr1
278 $ hg merge -r3
278 $ hg merge -r3
279 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 (branch merge, don't forget to commit)
280 (branch merge, don't forget to commit)
281 $ tellmeabout f
281 $ tellmeabout f
282 f is a plain file with content:
282 f is a plain file with content:
283 change
283 change
284
284
285 $ cd ..
285 $ cd ..
286
286
287 Test merge with no common ancestor:
287 Test merge with no common ancestor:
288 a: just different
288 a: just different
289 b: x vs -, different (cannot calculate x, cannot ask merge tool)
289 b: x vs -, different (cannot calculate x, cannot ask merge tool)
290 c: x vs -, same (cannot calculate x, merge tool is no good)
290 c: x vs -, same (cannot calculate x, merge tool is no good)
291 d: x vs l, different
291 d: x vs l, different
292 e: x vs l, same
292 e: x vs l, same
293 f: - vs l, different
293 f: - vs l, different
294 g: - vs l, same
294 g: - vs l, same
295 h: l vs l, different
295 h: l vs l, different
296 (where same means the filelog entry is shared and there thus is an ancestor!)
296 (where same means the filelog entry is shared and there thus is an ancestor!)
297
297
298 $ hg init test4
298 $ hg init test4
299 $ cd test4
299 $ cd test4
300 $ echo 0 > 0
300 $ echo 0 > 0
301 $ hg ci -Aqm0
301 $ hg ci -Aqm0
302
302
303 $ echo 1 > a
303 $ echo 1 > a
304 $ echo 1 > b
304 $ echo 1 > b
305 $ chmod +x b
305 $ chmod +x b
306 $ echo x > c
306 $ echo x > c
307 $ chmod +x c
307 $ chmod +x c
308 $ echo 1 > d
308 $ echo 1 > d
309 $ chmod +x d
309 $ chmod +x d
310 $ printf x > e
310 $ printf x > e
311 $ chmod +x e
311 $ chmod +x e
312 $ echo 1 > f
312 $ echo 1 > f
313 $ printf x > g
313 $ printf x > g
314 $ ln -s 1 h
314 $ ln -s 1 h
315 $ hg ci -qAm1
315 $ hg ci -qAm1
316
316
317 $ hg up -qr0
317 $ hg up -qr0
318 $ echo 2 > a
318 $ echo 2 > a
319 $ echo 2 > b
319 $ echo 2 > b
320 $ echo x > c
320 $ echo x > c
321 $ ln -s 2 d
321 $ ln -s 2 d
322 $ ln -s x e
322 $ ln -s x e
323 $ ln -s 2 f
323 $ ln -s 2 f
324 $ ln -s x g
324 $ ln -s x g
325 $ ln -s 2 h
325 $ ln -s 2 h
326 $ hg ci -Aqm2
326 $ hg ci -Aqm2
327
327
328 $ hg merge
328 $ hg merge
329 merging a
329 merging a
330 warning: cannot merge flags for b
330 warning: cannot merge flags for b
331 merging b
331 merging b
332 warning: cannot merge flags for c
332 warning: cannot merge flags for c
333 merging d
333 merging d
334 warning: internal :merge cannot merge symlinks for d
334 warning: internal :merge cannot merge symlinks for d
335 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
335 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
336 merging f
336 merging f
337 warning: internal :merge cannot merge symlinks for f
337 warning: internal :merge cannot merge symlinks for f
338 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
338 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
339 merging h
339 merging h
340 warning: internal :merge cannot merge symlinks for h
340 warning: internal :merge cannot merge symlinks for h
341 warning: conflicts while merging h! (edit, then use 'hg resolve --mark')
341 warning: conflicts while merging h! (edit, then use 'hg resolve --mark')
342 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
342 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
343 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
343 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
344 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
344 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
345 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
345 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
346 [1]
346 [1]
347 $ hg resolve -l
347 $ hg resolve -l
348 U a
348 U a
349 U b
349 U b
350 U d
350 U d
351 U f
351 U f
352 U h
352 U h
353 $ tellmeabout a
353 $ tellmeabout a
354 a is a plain file with content:
354 a is a plain file with content:
355 <<<<<<< local: 0139c5610547 - test: 2
355 <<<<<<< local: 0139c5610547 - test: 2
356 2
356 2
357 =======
357 =======
358 1
358 1
359 >>>>>>> other: 97e29675e796 - test: 1
359 >>>>>>> other: 97e29675e796 - test: 1
360 $ tellmeabout b
360 $ tellmeabout b
361 b is a plain file with content:
361 b is a plain file with content:
362 <<<<<<< local: 0139c5610547 - test: 2
362 <<<<<<< local: 0139c5610547 - test: 2
363 2
363 2
364 =======
364 =======
365 1
365 1
366 >>>>>>> other: 97e29675e796 - test: 1
366 >>>>>>> other: 97e29675e796 - test: 1
367 $ tellmeabout c
367 $ tellmeabout c
368 c is a plain file with content:
368 c is a plain file with content:
369 x
369 x
370 $ tellmeabout d
370 $ tellmeabout d
371 d is a symlink:
371 d is a symlink:
372 d -> 2
372 d -> 2
373 $ tellmeabout e
373 $ tellmeabout e
374 e is a symlink:
374 e is a symlink:
375 e -> x
375 e -> x
376 $ tellmeabout f
376 $ tellmeabout f
377 f is a symlink:
377 f is a symlink:
378 f -> 2
378 f -> 2
379 $ tellmeabout g
379 $ tellmeabout g
380 g is a symlink:
380 g is a symlink:
381 g -> x
381 g -> x
382 $ tellmeabout h
382 $ tellmeabout h
383 h is a symlink:
383 h is a symlink:
384 h -> 2
384 h -> 2
385
385
386 $ hg up -Cqr1
386 $ hg up -Cqr1
387 $ hg merge
387 $ hg merge
388 merging a
388 merging a
389 warning: cannot merge flags for b
389 warning: cannot merge flags for b
390 merging b
390 merging b
391 warning: cannot merge flags for c
391 warning: cannot merge flags for c
392 merging d
392 merging d
393 warning: internal :merge cannot merge symlinks for d
393 warning: internal :merge cannot merge symlinks for d
394 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
394 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
395 merging f
395 merging f
396 warning: internal :merge cannot merge symlinks for f
396 warning: internal :merge cannot merge symlinks for f
397 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
397 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
398 merging h
398 merging h
399 warning: internal :merge cannot merge symlinks for h
399 warning: internal :merge cannot merge symlinks for h
400 warning: conflicts while merging h! (edit, then use 'hg resolve --mark')
400 warning: conflicts while merging h! (edit, then use 'hg resolve --mark')
401 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
401 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
402 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
402 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
403 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
403 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
404 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
404 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
405 [1]
405 [1]
406 $ tellmeabout a
406 $ tellmeabout a
407 a is a plain file with content:
407 a is a plain file with content:
408 <<<<<<< local: 97e29675e796 - test: 1
408 <<<<<<< local: 97e29675e796 - test: 1
409 1
409 1
410 =======
410 =======
411 2
411 2
412 >>>>>>> other: 0139c5610547 - test: 2
412 >>>>>>> other: 0139c5610547 - test: 2
413 $ tellmeabout b
413 $ tellmeabout b
414 b is an executable file with content:
414 b is an executable file with content:
415 <<<<<<< local: 97e29675e796 - test: 1
415 <<<<<<< local: 97e29675e796 - test: 1
416 1
416 1
417 =======
417 =======
418 2
418 2
419 >>>>>>> other: 0139c5610547 - test: 2
419 >>>>>>> other: 0139c5610547 - test: 2
420 $ tellmeabout c
420 $ tellmeabout c
421 c is an executable file with content:
421 c is an executable file with content:
422 x
422 x
423 $ tellmeabout d
423 $ tellmeabout d
424 d is an executable file with content:
424 d is an executable file with content:
425 1
425 1
426 $ tellmeabout e
426 $ tellmeabout e
427 e is an executable file with content:
427 e is an executable file with content:
428 x (no-eol)
428 x (no-eol)
429 $ tellmeabout f
429 $ tellmeabout f
430 f is a plain file with content:
430 f is a plain file with content:
431 1
431 1
432 $ tellmeabout g
432 $ tellmeabout g
433 g is a plain file with content:
433 g is a plain file with content:
434 x (no-eol)
434 x (no-eol)
435 $ tellmeabout h
435 $ tellmeabout h
436 h is a symlink:
436 h is a symlink:
437 h -> 1
437 h -> 1
438
438
439 $ cd ..
439 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now