##// END OF EJS Templates
filemerge: switch the default name for internal tools from internal:x to :x
Mads Kiilerich -
r22707:38e0363d default
parent child Browse files
Show More
@@ -1,471 +1,471 b''
1 # filemerge.py - file-level merge handling for Mercurial
1 # filemerge.py - file-level merge handling for Mercurial
2 #
2 #
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import short
8 from node import short
9 from i18n import _
9 from i18n import _
10 import util, simplemerge, match, error, templater, templatekw
10 import util, simplemerge, match, error, templater, templatekw
11 import os, tempfile, re, filecmp
11 import os, tempfile, re, filecmp
12 import tagmerge
12 import tagmerge
13
13
14 def _toolstr(ui, tool, part, default=""):
14 def _toolstr(ui, tool, part, default=""):
15 return ui.config("merge-tools", tool + "." + part, default)
15 return ui.config("merge-tools", tool + "." + part, default)
16
16
17 def _toolbool(ui, tool, part, default=False):
17 def _toolbool(ui, tool, part, default=False):
18 return ui.configbool("merge-tools", tool + "." + part, default)
18 return ui.configbool("merge-tools", tool + "." + part, default)
19
19
20 def _toollist(ui, tool, part, default=[]):
20 def _toollist(ui, tool, part, default=[]):
21 return ui.configlist("merge-tools", tool + "." + part, default)
21 return ui.configlist("merge-tools", tool + "." + part, default)
22
22
23 internals = {}
23 internals = {}
24
24
25 def internaltool(name, trymerge, onfailure=None):
25 def internaltool(name, trymerge, onfailure=None):
26 '''return a decorator for populating internal merge tool table'''
26 '''return a decorator for populating internal merge tool table'''
27 def decorator(func):
27 def decorator(func):
28 fullname = 'internal:' + name
28 fullname = ':' + name
29 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
29 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
30 internals[fullname] = func
30 internals[fullname] = func
31 internals[':' + name] = func
31 internals['internal:' + name] = func
32 func.trymerge = trymerge
32 func.trymerge = trymerge
33 func.onfailure = onfailure
33 func.onfailure = onfailure
34 return func
34 return func
35 return decorator
35 return decorator
36
36
37 def _findtool(ui, tool):
37 def _findtool(ui, tool):
38 if tool in internals:
38 if tool in internals:
39 return tool
39 return tool
40 for kn in ("regkey", "regkeyalt"):
40 for kn in ("regkey", "regkeyalt"):
41 k = _toolstr(ui, tool, kn)
41 k = _toolstr(ui, tool, kn)
42 if not k:
42 if not k:
43 continue
43 continue
44 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
44 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
45 if p:
45 if p:
46 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
46 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
47 if p:
47 if p:
48 return p
48 return p
49 exe = _toolstr(ui, tool, "executable", tool)
49 exe = _toolstr(ui, tool, "executable", tool)
50 return util.findexe(util.expandpath(exe))
50 return util.findexe(util.expandpath(exe))
51
51
52 def _picktool(repo, ui, path, binary, symlink):
52 def _picktool(repo, ui, path, binary, symlink):
53 def check(tool, pat, symlink, binary):
53 def check(tool, pat, symlink, binary):
54 tmsg = tool
54 tmsg = tool
55 if pat:
55 if pat:
56 tmsg += " specified for " + pat
56 tmsg += " specified for " + pat
57 if not _findtool(ui, tool):
57 if not _findtool(ui, tool):
58 if pat: # explicitly requested tool deserves a warning
58 if pat: # explicitly requested tool deserves a warning
59 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
59 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
60 else: # configured but non-existing tools are more silent
60 else: # configured but non-existing tools are more silent
61 ui.note(_("couldn't find merge tool %s\n") % tmsg)
61 ui.note(_("couldn't find merge tool %s\n") % tmsg)
62 elif symlink and not _toolbool(ui, tool, "symlink"):
62 elif symlink and not _toolbool(ui, tool, "symlink"):
63 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
63 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
64 elif binary and not _toolbool(ui, tool, "binary"):
64 elif binary and not _toolbool(ui, tool, "binary"):
65 ui.warn(_("tool %s can't handle binary\n") % tmsg)
65 ui.warn(_("tool %s can't handle binary\n") % tmsg)
66 elif not util.gui() and _toolbool(ui, tool, "gui"):
66 elif not util.gui() and _toolbool(ui, tool, "gui"):
67 ui.warn(_("tool %s requires a GUI\n") % tmsg)
67 ui.warn(_("tool %s requires a GUI\n") % tmsg)
68 else:
68 else:
69 return True
69 return True
70 return False
70 return False
71
71
72 # forcemerge comes from command line arguments, highest priority
72 # forcemerge comes from command line arguments, highest priority
73 force = ui.config('ui', 'forcemerge')
73 force = ui.config('ui', 'forcemerge')
74 if force:
74 if force:
75 toolpath = _findtool(ui, force)
75 toolpath = _findtool(ui, force)
76 if toolpath:
76 if toolpath:
77 return (force, util.shellquote(toolpath))
77 return (force, util.shellquote(toolpath))
78 else:
78 else:
79 # mimic HGMERGE if given tool not found
79 # mimic HGMERGE if given tool not found
80 return (force, force)
80 return (force, force)
81
81
82 # HGMERGE takes next precedence
82 # HGMERGE takes next precedence
83 hgmerge = os.environ.get("HGMERGE")
83 hgmerge = os.environ.get("HGMERGE")
84 if hgmerge:
84 if hgmerge:
85 return (hgmerge, hgmerge)
85 return (hgmerge, hgmerge)
86
86
87 # then patterns
87 # then patterns
88 for pat, tool in ui.configitems("merge-patterns"):
88 for pat, tool in ui.configitems("merge-patterns"):
89 mf = match.match(repo.root, '', [pat])
89 mf = match.match(repo.root, '', [pat])
90 if mf(path) and check(tool, pat, symlink, False):
90 if mf(path) and check(tool, pat, symlink, False):
91 toolpath = _findtool(ui, tool)
91 toolpath = _findtool(ui, tool)
92 return (tool, util.shellquote(toolpath))
92 return (tool, util.shellquote(toolpath))
93
93
94 # then merge tools
94 # then merge tools
95 tools = {}
95 tools = {}
96 for k, v in ui.configitems("merge-tools"):
96 for k, v in ui.configitems("merge-tools"):
97 t = k.split('.')[0]
97 t = k.split('.')[0]
98 if t not in tools:
98 if t not in tools:
99 tools[t] = int(_toolstr(ui, t, "priority", "0"))
99 tools[t] = int(_toolstr(ui, t, "priority", "0"))
100 names = tools.keys()
100 names = tools.keys()
101 tools = sorted([(-p, t) for t, p in tools.items()])
101 tools = sorted([(-p, t) for t, p in tools.items()])
102 uimerge = ui.config("ui", "merge")
102 uimerge = ui.config("ui", "merge")
103 if uimerge:
103 if uimerge:
104 if uimerge not in names:
104 if uimerge not in names:
105 return (uimerge, uimerge)
105 return (uimerge, uimerge)
106 tools.insert(0, (None, uimerge)) # highest priority
106 tools.insert(0, (None, uimerge)) # highest priority
107 tools.append((None, "hgmerge")) # the old default, if found
107 tools.append((None, "hgmerge")) # the old default, if found
108 for p, t in tools:
108 for p, t in tools:
109 if check(t, None, symlink, binary):
109 if check(t, None, symlink, binary):
110 toolpath = _findtool(ui, t)
110 toolpath = _findtool(ui, t)
111 return (t, util.shellquote(toolpath))
111 return (t, util.shellquote(toolpath))
112
112
113 # internal merge or prompt as last resort
113 # internal merge or prompt as last resort
114 if symlink or binary:
114 if symlink or binary:
115 return "internal:prompt", None
115 return ":prompt", None
116 return "internal:merge", None
116 return ":merge", None
117
117
118 def _eoltype(data):
118 def _eoltype(data):
119 "Guess the EOL type of a file"
119 "Guess the EOL type of a file"
120 if '\0' in data: # binary
120 if '\0' in data: # binary
121 return None
121 return None
122 if '\r\n' in data: # Windows
122 if '\r\n' in data: # Windows
123 return '\r\n'
123 return '\r\n'
124 if '\r' in data: # Old Mac
124 if '\r' in data: # Old Mac
125 return '\r'
125 return '\r'
126 if '\n' in data: # UNIX
126 if '\n' in data: # UNIX
127 return '\n'
127 return '\n'
128 return None # unknown
128 return None # unknown
129
129
130 def _matcheol(file, origfile):
130 def _matcheol(file, origfile):
131 "Convert EOL markers in a file to match origfile"
131 "Convert EOL markers in a file to match origfile"
132 tostyle = _eoltype(util.readfile(origfile))
132 tostyle = _eoltype(util.readfile(origfile))
133 if tostyle:
133 if tostyle:
134 data = util.readfile(file)
134 data = util.readfile(file)
135 style = _eoltype(data)
135 style = _eoltype(data)
136 if style:
136 if style:
137 newdata = data.replace(style, tostyle)
137 newdata = data.replace(style, tostyle)
138 if newdata != data:
138 if newdata != data:
139 util.writefile(file, newdata)
139 util.writefile(file, newdata)
140
140
141 @internaltool('prompt', False)
141 @internaltool('prompt', False)
142 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
142 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
143 """Asks the user which of the local or the other version to keep as
143 """Asks the user which of the local or the other version to keep as
144 the merged version."""
144 the merged version."""
145 ui = repo.ui
145 ui = repo.ui
146 fd = fcd.path()
146 fd = fcd.path()
147
147
148 if ui.promptchoice(_(" no tool found to merge %s\n"
148 if ui.promptchoice(_(" no tool found to merge %s\n"
149 "keep (l)ocal or take (o)ther?"
149 "keep (l)ocal or take (o)ther?"
150 "$$ &Local $$ &Other") % fd, 0):
150 "$$ &Local $$ &Other") % fd, 0):
151 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
151 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
152 else:
152 else:
153 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
153 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
154
154
155 @internaltool('local', False)
155 @internaltool('local', False)
156 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
156 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
157 """Uses the local version of files as the merged version."""
157 """Uses the local version of files as the merged version."""
158 return 0
158 return 0
159
159
160 @internaltool('other', False)
160 @internaltool('other', False)
161 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
161 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
162 """Uses the other version of files as the merged version."""
162 """Uses the other version of files as the merged version."""
163 repo.wwrite(fcd.path(), fco.data(), fco.flags())
163 repo.wwrite(fcd.path(), fco.data(), fco.flags())
164 return 0
164 return 0
165
165
166 @internaltool('fail', False)
166 @internaltool('fail', False)
167 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
167 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
168 """
168 """
169 Rather than attempting to merge files that were modified on both
169 Rather than attempting to merge files that were modified on both
170 branches, it marks them as unresolved. The resolve command must be
170 branches, it marks them as unresolved. The resolve command must be
171 used to resolve these conflicts."""
171 used to resolve these conflicts."""
172 return 1
172 return 1
173
173
174 def _premerge(repo, toolconf, files, labels=None):
174 def _premerge(repo, toolconf, files, labels=None):
175 tool, toolpath, binary, symlink = toolconf
175 tool, toolpath, binary, symlink = toolconf
176 if symlink:
176 if symlink:
177 return 1
177 return 1
178 a, b, c, back = files
178 a, b, c, back = files
179
179
180 ui = repo.ui
180 ui = repo.ui
181
181
182 validkeep = ['keep', 'keep-merge3']
182 validkeep = ['keep', 'keep-merge3']
183
183
184 # do we attempt to simplemerge first?
184 # do we attempt to simplemerge first?
185 try:
185 try:
186 premerge = _toolbool(ui, tool, "premerge", not binary)
186 premerge = _toolbool(ui, tool, "premerge", not binary)
187 except error.ConfigError:
187 except error.ConfigError:
188 premerge = _toolstr(ui, tool, "premerge").lower()
188 premerge = _toolstr(ui, tool, "premerge").lower()
189 if premerge not in validkeep:
189 if premerge not in validkeep:
190 _valid = ', '.join(["'" + v + "'" for v in validkeep])
190 _valid = ', '.join(["'" + v + "'" for v in validkeep])
191 raise error.ConfigError(_("%s.premerge not valid "
191 raise error.ConfigError(_("%s.premerge not valid "
192 "('%s' is neither boolean nor %s)") %
192 "('%s' is neither boolean nor %s)") %
193 (tool, premerge, _valid))
193 (tool, premerge, _valid))
194
194
195 if premerge:
195 if premerge:
196 if premerge == 'keep-merge3':
196 if premerge == 'keep-merge3':
197 if not labels:
197 if not labels:
198 labels = _defaultconflictlabels
198 labels = _defaultconflictlabels
199 if len(labels) < 3:
199 if len(labels) < 3:
200 labels.append('base')
200 labels.append('base')
201 r = simplemerge.simplemerge(ui, a, b, c, quiet=True, label=labels)
201 r = simplemerge.simplemerge(ui, a, b, c, quiet=True, label=labels)
202 if not r:
202 if not r:
203 ui.debug(" premerge successful\n")
203 ui.debug(" premerge successful\n")
204 return 0
204 return 0
205 if premerge not in validkeep:
205 if premerge not in validkeep:
206 util.copyfile(back, a) # restore from backup and try again
206 util.copyfile(back, a) # restore from backup and try again
207 return 1 # continue merging
207 return 1 # continue merging
208
208
209 @internaltool('merge', True,
209 @internaltool('merge', True,
210 _("merging %s incomplete! "
210 _("merging %s incomplete! "
211 "(edit conflicts, then use 'hg resolve --mark')\n"))
211 "(edit conflicts, then use 'hg resolve --mark')\n"))
212 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
212 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
213 """
213 """
214 Uses the internal non-interactive simple merge algorithm for merging
214 Uses the internal non-interactive simple merge algorithm for merging
215 files. It will fail if there are any conflicts and leave markers in
215 files. It will fail if there are any conflicts and leave markers in
216 the partially merged file. Markers will have two sections, one for each side
216 the partially merged file. Markers will have two sections, one for each side
217 of merge."""
217 of merge."""
218 tool, toolpath, binary, symlink = toolconf
218 tool, toolpath, binary, symlink = toolconf
219 if symlink:
219 if symlink:
220 repo.ui.warn(_('warning: internal:merge cannot merge symlinks '
220 repo.ui.warn(_('warning: internal :merge cannot merge symlinks '
221 'for %s\n') % fcd.path())
221 'for %s\n') % fcd.path())
222 return False, 1
222 return False, 1
223 r = _premerge(repo, toolconf, files, labels=labels)
223 r = _premerge(repo, toolconf, files, labels=labels)
224 if r:
224 if r:
225 a, b, c, back = files
225 a, b, c, back = files
226
226
227 ui = repo.ui
227 ui = repo.ui
228
228
229 r = simplemerge.simplemerge(ui, a, b, c, label=labels)
229 r = simplemerge.simplemerge(ui, a, b, c, label=labels)
230 return True, r
230 return True, r
231 return False, 0
231 return False, 0
232
232
233 @internaltool('merge3', True,
233 @internaltool('merge3', True,
234 _("merging %s incomplete! "
234 _("merging %s incomplete! "
235 "(edit conflicts, then use 'hg resolve --mark')\n"))
235 "(edit conflicts, then use 'hg resolve --mark')\n"))
236 def _imerge3(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
236 def _imerge3(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
237 """
237 """
238 Uses the internal non-interactive simple merge algorithm for merging
238 Uses the internal non-interactive simple merge algorithm for merging
239 files. It will fail if there are any conflicts and leave markers in
239 files. It will fail if there are any conflicts and leave markers in
240 the partially merged file. Marker will have three sections, one from each
240 the partially merged file. Marker will have three sections, one from each
241 side of the merge and one for the base content."""
241 side of the merge and one for the base content."""
242 if not labels:
242 if not labels:
243 labels = _defaultconflictlabels
243 labels = _defaultconflictlabels
244 if len(labels) < 3:
244 if len(labels) < 3:
245 labels.append('base')
245 labels.append('base')
246 return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels)
246 return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels)
247
247
248 @internaltool('tagmerge', True,
248 @internaltool('tagmerge', True,
249 _("automatic tag merging of %s failed! "
249 _("automatic tag merging of %s failed! "
250 "(use 'hg resolve --tool internal:merge' or another merge "
250 "(use 'hg resolve --tool :merge' or another merge "
251 "tool of your choice)\n"))
251 "tool of your choice)\n"))
252 def _itagmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
252 def _itagmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
253 """
253 """
254 Uses the internal tag merge algorithm (experimental).
254 Uses the internal tag merge algorithm (experimental).
255 """
255 """
256 return tagmerge.merge(repo, fcd, fco, fca)
256 return tagmerge.merge(repo, fcd, fco, fca)
257
257
258 @internaltool('dump', True)
258 @internaltool('dump', True)
259 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
259 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
260 """
260 """
261 Creates three versions of the files to merge, containing the
261 Creates three versions of the files to merge, containing the
262 contents of local, other and base. These files can then be used to
262 contents of local, other and base. These files can then be used to
263 perform a merge manually. If the file to be merged is named
263 perform a merge manually. If the file to be merged is named
264 ``a.txt``, these files will accordingly be named ``a.txt.local``,
264 ``a.txt``, these files will accordingly be named ``a.txt.local``,
265 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
265 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
266 same directory as ``a.txt``."""
266 same directory as ``a.txt``."""
267 r = _premerge(repo, toolconf, files, labels=labels)
267 r = _premerge(repo, toolconf, files, labels=labels)
268 if r:
268 if r:
269 a, b, c, back = files
269 a, b, c, back = files
270
270
271 fd = fcd.path()
271 fd = fcd.path()
272
272
273 util.copyfile(a, a + ".local")
273 util.copyfile(a, a + ".local")
274 repo.wwrite(fd + ".other", fco.data(), fco.flags())
274 repo.wwrite(fd + ".other", fco.data(), fco.flags())
275 repo.wwrite(fd + ".base", fca.data(), fca.flags())
275 repo.wwrite(fd + ".base", fca.data(), fca.flags())
276 return False, r
276 return False, r
277
277
278 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
278 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
279 r = _premerge(repo, toolconf, files, labels=labels)
279 r = _premerge(repo, toolconf, files, labels=labels)
280 if r:
280 if r:
281 tool, toolpath, binary, symlink = toolconf
281 tool, toolpath, binary, symlink = toolconf
282 a, b, c, back = files
282 a, b, c, back = files
283 out = ""
283 out = ""
284 env = {'HG_FILE': fcd.path(),
284 env = {'HG_FILE': fcd.path(),
285 'HG_MY_NODE': short(mynode),
285 'HG_MY_NODE': short(mynode),
286 'HG_OTHER_NODE': str(fco.changectx()),
286 'HG_OTHER_NODE': str(fco.changectx()),
287 'HG_BASE_NODE': str(fca.changectx()),
287 'HG_BASE_NODE': str(fca.changectx()),
288 'HG_MY_ISLINK': 'l' in fcd.flags(),
288 'HG_MY_ISLINK': 'l' in fcd.flags(),
289 'HG_OTHER_ISLINK': 'l' in fco.flags(),
289 'HG_OTHER_ISLINK': 'l' in fco.flags(),
290 'HG_BASE_ISLINK': 'l' in fca.flags(),
290 'HG_BASE_ISLINK': 'l' in fca.flags(),
291 }
291 }
292
292
293 ui = repo.ui
293 ui = repo.ui
294
294
295 args = _toolstr(ui, tool, "args", '$local $base $other')
295 args = _toolstr(ui, tool, "args", '$local $base $other')
296 if "$output" in args:
296 if "$output" in args:
297 out, a = a, back # read input from backup, write to original
297 out, a = a, back # read input from backup, write to original
298 replace = {'local': a, 'base': b, 'other': c, 'output': out}
298 replace = {'local': a, 'base': b, 'other': c, 'output': out}
299 args = util.interpolate(r'\$', replace, args,
299 args = util.interpolate(r'\$', replace, args,
300 lambda s: util.shellquote(util.localpath(s)))
300 lambda s: util.shellquote(util.localpath(s)))
301 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
301 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
302 out=ui.fout)
302 out=ui.fout)
303 return True, r
303 return True, r
304 return False, 0
304 return False, 0
305
305
306 def _formatconflictmarker(repo, ctx, template, label, pad):
306 def _formatconflictmarker(repo, ctx, template, label, pad):
307 """Applies the given template to the ctx, prefixed by the label.
307 """Applies the given template to the ctx, prefixed by the label.
308
308
309 Pad is the minimum width of the label prefix, so that multiple markers
309 Pad is the minimum width of the label prefix, so that multiple markers
310 can have aligned templated parts.
310 can have aligned templated parts.
311 """
311 """
312 if ctx.node() is None:
312 if ctx.node() is None:
313 ctx = ctx.p1()
313 ctx = ctx.p1()
314
314
315 props = templatekw.keywords.copy()
315 props = templatekw.keywords.copy()
316 props['templ'] = template
316 props['templ'] = template
317 props['ctx'] = ctx
317 props['ctx'] = ctx
318 props['repo'] = repo
318 props['repo'] = repo
319 templateresult = template('conflictmarker', **props)
319 templateresult = template('conflictmarker', **props)
320
320
321 label = ('%s:' % label).ljust(pad + 1)
321 label = ('%s:' % label).ljust(pad + 1)
322 mark = '%s %s' % (label, templater.stringify(templateresult))
322 mark = '%s %s' % (label, templater.stringify(templateresult))
323
323
324 if mark:
324 if mark:
325 mark = mark.splitlines()[0] # split for safety
325 mark = mark.splitlines()[0] # split for safety
326
326
327 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ')
327 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ')
328 return util.ellipsis(mark, 80 - 8)
328 return util.ellipsis(mark, 80 - 8)
329
329
330 _defaultconflictmarker = ('{node|short} ' +
330 _defaultconflictmarker = ('{node|short} ' +
331 '{ifeq(tags, "tip", "", "{tags} ")}' +
331 '{ifeq(tags, "tip", "", "{tags} ")}' +
332 '{if(bookmarks, "{bookmarks} ")}' +
332 '{if(bookmarks, "{bookmarks} ")}' +
333 '{ifeq(branch, "default", "", "{branch} ")}' +
333 '{ifeq(branch, "default", "", "{branch} ")}' +
334 '- {author|user}: {desc|firstline}')
334 '- {author|user}: {desc|firstline}')
335
335
336 _defaultconflictlabels = ['local', 'other']
336 _defaultconflictlabels = ['local', 'other']
337
337
338 def _formatlabels(repo, fcd, fco, fca, labels):
338 def _formatlabels(repo, fcd, fco, fca, labels):
339 """Formats the given labels using the conflict marker template.
339 """Formats the given labels using the conflict marker template.
340
340
341 Returns a list of formatted labels.
341 Returns a list of formatted labels.
342 """
342 """
343 cd = fcd.changectx()
343 cd = fcd.changectx()
344 co = fco.changectx()
344 co = fco.changectx()
345 ca = fca.changectx()
345 ca = fca.changectx()
346
346
347 ui = repo.ui
347 ui = repo.ui
348 template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker)
348 template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker)
349 template = templater.parsestring(template, quoted=False)
349 template = templater.parsestring(template, quoted=False)
350 tmpl = templater.templater(None, cache={'conflictmarker': template})
350 tmpl = templater.templater(None, cache={'conflictmarker': template})
351
351
352 pad = max(len(l) for l in labels)
352 pad = max(len(l) for l in labels)
353
353
354 newlabels = [_formatconflictmarker(repo, cd, tmpl, labels[0], pad),
354 newlabels = [_formatconflictmarker(repo, cd, tmpl, labels[0], pad),
355 _formatconflictmarker(repo, co, tmpl, labels[1], pad)]
355 _formatconflictmarker(repo, co, tmpl, labels[1], pad)]
356 if len(labels) > 2:
356 if len(labels) > 2:
357 newlabels.append(_formatconflictmarker(repo, ca, tmpl, labels[2], pad))
357 newlabels.append(_formatconflictmarker(repo, ca, tmpl, labels[2], pad))
358 return newlabels
358 return newlabels
359
359
360 def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
360 def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
361 """perform a 3-way merge in the working directory
361 """perform a 3-way merge in the working directory
362
362
363 mynode = parent node before merge
363 mynode = parent node before merge
364 orig = original local filename before merge
364 orig = original local filename before merge
365 fco = other file context
365 fco = other file context
366 fca = ancestor file context
366 fca = ancestor file context
367 fcd = local file context for current/destination file
367 fcd = local file context for current/destination file
368 """
368 """
369
369
370 def temp(prefix, ctx):
370 def temp(prefix, ctx):
371 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
371 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
372 (fd, name) = tempfile.mkstemp(prefix=pre)
372 (fd, name) = tempfile.mkstemp(prefix=pre)
373 data = repo.wwritedata(ctx.path(), ctx.data())
373 data = repo.wwritedata(ctx.path(), ctx.data())
374 f = os.fdopen(fd, "wb")
374 f = os.fdopen(fd, "wb")
375 f.write(data)
375 f.write(data)
376 f.close()
376 f.close()
377 return name
377 return name
378
378
379 if not fco.cmp(fcd): # files identical?
379 if not fco.cmp(fcd): # files identical?
380 return None
380 return None
381
381
382 ui = repo.ui
382 ui = repo.ui
383 fd = fcd.path()
383 fd = fcd.path()
384 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
384 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
385 symlink = 'l' in fcd.flags() + fco.flags()
385 symlink = 'l' in fcd.flags() + fco.flags()
386 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
386 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
387 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
387 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
388 (tool, fd, binary, symlink))
388 (tool, fd, binary, symlink))
389
389
390 if tool in internals:
390 if tool in internals:
391 func = internals[tool]
391 func = internals[tool]
392 trymerge = func.trymerge
392 trymerge = func.trymerge
393 onfailure = func.onfailure
393 onfailure = func.onfailure
394 else:
394 else:
395 func = _xmerge
395 func = _xmerge
396 trymerge = True
396 trymerge = True
397 onfailure = _("merging %s failed!\n")
397 onfailure = _("merging %s failed!\n")
398
398
399 toolconf = tool, toolpath, binary, symlink
399 toolconf = tool, toolpath, binary, symlink
400
400
401 if not trymerge:
401 if not trymerge:
402 return func(repo, mynode, orig, fcd, fco, fca, toolconf)
402 return func(repo, mynode, orig, fcd, fco, fca, toolconf)
403
403
404 a = repo.wjoin(fd)
404 a = repo.wjoin(fd)
405 b = temp("base", fca)
405 b = temp("base", fca)
406 c = temp("other", fco)
406 c = temp("other", fco)
407 back = a + ".orig"
407 back = a + ".orig"
408 util.copyfile(a, back)
408 util.copyfile(a, back)
409
409
410 if orig != fco.path():
410 if orig != fco.path():
411 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
411 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
412 else:
412 else:
413 ui.status(_("merging %s\n") % fd)
413 ui.status(_("merging %s\n") % fd)
414
414
415 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
415 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
416
416
417 markerstyle = ui.config('ui', 'mergemarkers', 'basic')
417 markerstyle = ui.config('ui', 'mergemarkers', 'basic')
418 if not labels:
418 if not labels:
419 labels = _defaultconflictlabels
419 labels = _defaultconflictlabels
420 if markerstyle != 'basic':
420 if markerstyle != 'basic':
421 labels = _formatlabels(repo, fcd, fco, fca, labels)
421 labels = _formatlabels(repo, fcd, fco, fca, labels)
422
422
423 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
423 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
424 (a, b, c, back), labels=labels)
424 (a, b, c, back), labels=labels)
425 if not needcheck:
425 if not needcheck:
426 if r:
426 if r:
427 if onfailure:
427 if onfailure:
428 ui.warn(onfailure % fd)
428 ui.warn(onfailure % fd)
429 else:
429 else:
430 util.unlink(back)
430 util.unlink(back)
431
431
432 util.unlink(b)
432 util.unlink(b)
433 util.unlink(c)
433 util.unlink(c)
434 return r
434 return r
435
435
436 if not r and (_toolbool(ui, tool, "checkconflicts") or
436 if not r and (_toolbool(ui, tool, "checkconflicts") or
437 'conflicts' in _toollist(ui, tool, "check")):
437 'conflicts' in _toollist(ui, tool, "check")):
438 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
438 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
439 re.MULTILINE):
439 re.MULTILINE):
440 r = 1
440 r = 1
441
441
442 checked = False
442 checked = False
443 if 'prompt' in _toollist(ui, tool, "check"):
443 if 'prompt' in _toollist(ui, tool, "check"):
444 checked = True
444 checked = True
445 if ui.promptchoice(_("was merge of '%s' successful (yn)?"
445 if ui.promptchoice(_("was merge of '%s' successful (yn)?"
446 "$$ &Yes $$ &No") % fd, 1):
446 "$$ &Yes $$ &No") % fd, 1):
447 r = 1
447 r = 1
448
448
449 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
449 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
450 'changed' in _toollist(ui, tool, "check")):
450 'changed' in _toollist(ui, tool, "check")):
451 if filecmp.cmp(a, back):
451 if filecmp.cmp(a, back):
452 if ui.promptchoice(_(" output file %s appears unchanged\n"
452 if ui.promptchoice(_(" output file %s appears unchanged\n"
453 "was merge successful (yn)?"
453 "was merge successful (yn)?"
454 "$$ &Yes $$ &No") % fd, 1):
454 "$$ &Yes $$ &No") % fd, 1):
455 r = 1
455 r = 1
456
456
457 if _toolbool(ui, tool, "fixeol"):
457 if _toolbool(ui, tool, "fixeol"):
458 _matcheol(a, back)
458 _matcheol(a, back)
459
459
460 if r:
460 if r:
461 if onfailure:
461 if onfailure:
462 ui.warn(onfailure % fd)
462 ui.warn(onfailure % fd)
463 else:
463 else:
464 util.unlink(back)
464 util.unlink(back)
465
465
466 util.unlink(b)
466 util.unlink(b)
467 util.unlink(c)
467 util.unlink(c)
468 return r
468 return r
469
469
470 # tell hggettext to extract docstrings from these functions:
470 # tell hggettext to extract docstrings from these functions:
471 i18nfunctions = internals.values()
471 i18nfunctions = internals.values()
@@ -1,85 +1,85 b''
1 To merge files Mercurial uses merge tools.
1 To merge files Mercurial uses merge tools.
2
2
3 A merge tool combines two different versions of a file into a merged
3 A merge tool combines two different versions of a file into a merged
4 file. Merge tools are given the two files and the greatest common
4 file. Merge tools are given the two files and the greatest common
5 ancestor of the two file versions, so they can determine the changes
5 ancestor of the two file versions, so they can determine the changes
6 made on both branches.
6 made on both branches.
7
7
8 Merge tools are used both for :hg:`resolve`, :hg:`merge`, :hg:`update`,
8 Merge tools are used both for :hg:`resolve`, :hg:`merge`, :hg:`update`,
9 :hg:`backout` and in several extensions.
9 :hg:`backout` and in several extensions.
10
10
11 Usually, the merge tool tries to automatically reconcile the files by
11 Usually, the merge tool tries to automatically reconcile the files by
12 combining all non-overlapping changes that occurred separately in
12 combining all non-overlapping changes that occurred separately in
13 the two different evolutions of the same initial base file. Furthermore, some
13 the two different evolutions of the same initial base file. Furthermore, some
14 interactive merge programs make it easier to manually resolve
14 interactive merge programs make it easier to manually resolve
15 conflicting merges, either in a graphical way, or by inserting some
15 conflicting merges, either in a graphical way, or by inserting some
16 conflict markers. Mercurial does not include any interactive merge
16 conflict markers. Mercurial does not include any interactive merge
17 programs but relies on external tools for that.
17 programs but relies on external tools for that.
18
18
19 Available merge tools
19 Available merge tools
20 =====================
20 =====================
21
21
22 External merge tools and their properties are configured in the
22 External merge tools and their properties are configured in the
23 merge-tools configuration section - see hgrc(5) - but they can often just
23 merge-tools configuration section - see hgrc(5) - but they can often just
24 be named by their executable.
24 be named by their executable.
25
25
26 A merge tool is generally usable if its executable can be found on the
26 A merge tool is generally usable if its executable can be found on the
27 system and if it can handle the merge. The executable is found if it
27 system and if it can handle the merge. The executable is found if it
28 is an absolute or relative executable path or the name of an
28 is an absolute or relative executable path or the name of an
29 application in the executable search path. The tool is assumed to be
29 application in the executable search path. The tool is assumed to be
30 able to handle the merge if it can handle symlinks if the file is a
30 able to handle the merge if it can handle symlinks if the file is a
31 symlink, if it can handle binary files if the file is binary, and if a
31 symlink, if it can handle binary files if the file is binary, and if a
32 GUI is available if the tool requires a GUI.
32 GUI is available if the tool requires a GUI.
33
33
34 There are some internal merge tools which can be used. The internal
34 There are some internal merge tools which can be used. The internal
35 merge tools are:
35 merge tools are:
36
36
37 .. internaltoolsmarker
37 .. internaltoolsmarker
38
38
39 Internal tools are always available and do not require a GUI but will by default
39 Internal tools are always available and do not require a GUI but will by default
40 not handle symlinks or binary files.
40 not handle symlinks or binary files.
41
41
42 Choosing a merge tool
42 Choosing a merge tool
43 =====================
43 =====================
44
44
45 Mercurial uses these rules when deciding which merge tool to use:
45 Mercurial uses these rules when deciding which merge tool to use:
46
46
47 1. If a tool has been specified with the --tool option to merge or resolve, it
47 1. If a tool has been specified with the --tool option to merge or resolve, it
48 is used. If it is the name of a tool in the merge-tools configuration, its
48 is used. If it is the name of a tool in the merge-tools configuration, its
49 configuration is used. Otherwise the specified tool must be executable by
49 configuration is used. Otherwise the specified tool must be executable by
50 the shell.
50 the shell.
51
51
52 2. If the ``HGMERGE`` environment variable is present, its value is used and
52 2. If the ``HGMERGE`` environment variable is present, its value is used and
53 must be executable by the shell.
53 must be executable by the shell.
54
54
55 3. If the filename of the file to be merged matches any of the patterns in the
55 3. If the filename of the file to be merged matches any of the patterns in the
56 merge-patterns configuration section, the first usable merge tool
56 merge-patterns configuration section, the first usable merge tool
57 corresponding to a matching pattern is used. Here, binary capabilities of the
57 corresponding to a matching pattern is used. Here, binary capabilities of the
58 merge tool are not considered.
58 merge tool are not considered.
59
59
60 4. If ui.merge is set it will be considered next. If the value is not the name
60 4. If ui.merge is set it will be considered next. If the value is not the name
61 of a configured tool, the specified value is used and must be executable by
61 of a configured tool, the specified value is used and must be executable by
62 the shell. Otherwise the named tool is used if it is usable.
62 the shell. Otherwise the named tool is used if it is usable.
63
63
64 5. If any usable merge tools are present in the merge-tools configuration
64 5. If any usable merge tools are present in the merge-tools configuration
65 section, the one with the highest priority is used.
65 section, the one with the highest priority is used.
66
66
67 6. If a program named ``hgmerge`` can be found on the system, it is used - but
67 6. If a program named ``hgmerge`` can be found on the system, it is used - but
68 it will by default not be used for symlinks and binary files.
68 it will by default not be used for symlinks and binary files.
69
69
70 7. If the file to be merged is not binary and is not a symlink, then
70 7. If the file to be merged is not binary and is not a symlink, then
71 ``internal:merge`` is used.
71 internal ``:merge`` is used.
72
72
73 8. The merge of the file fails and must be resolved before commit.
73 8. The merge of the file fails and must be resolved before commit.
74
74
75 .. note::
75 .. note::
76
76
77 After selecting a merge program, Mercurial will by default attempt
77 After selecting a merge program, Mercurial will by default attempt
78 to merge the files using a simple merge algorithm first. Only if it doesn't
78 to merge the files using a simple merge algorithm first. Only if it doesn't
79 succeed because of conflicting changes Mercurial will actually execute the
79 succeed because of conflicting changes Mercurial will actually execute the
80 merge program. Whether to use the simple merge algorithm first can be
80 merge program. Whether to use the simple merge algorithm first can be
81 controlled by the premerge setting of the merge tool. Premerge is enabled by
81 controlled by the premerge setting of the merge tool. Premerge is enabled by
82 default unless the file is binary or a symlink.
82 default unless the file is binary or a symlink.
83
83
84 See the merge-tools and ui sections of hgrc(5) for details on the
84 See the merge-tools and ui sections of hgrc(5) for details on the
85 configuration of merge tools.
85 configuration of merge tools.
@@ -1,979 +1,979 b''
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 > rm -f f.orig
53 > rm -f f.orig
54 > }
54 > }
55
55
56 Tool selection
56 Tool selection
57
57
58 default is internal merge:
58 default is internal merge:
59
59
60 $ beforemerge
60 $ beforemerge
61 [merge-tools]
61 [merge-tools]
62 # hg update -C 1
62 # hg update -C 1
63
63
64 hg merge -r 2
64 hg merge -r 2
65 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
65 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
66 running from a devel copy, not a temp installation
66 running from a devel copy, not a temp installation
67
67
68 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
68 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
69 merging f
69 merging f
70 warning: conflicts during merge.
70 warning: conflicts during merge.
71 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
71 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
72 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
72 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
73 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
73 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
74 [1]
74 [1]
75 $ aftermerge
75 $ aftermerge
76 # cat f
76 # cat f
77 <<<<<<< local: ef83787e2614 - test: revision 1
77 <<<<<<< local: ef83787e2614 - test: revision 1
78 revision 1
78 revision 1
79 =======
79 =======
80 revision 2
80 revision 2
81 >>>>>>> other: 0185f4e0cf02 - test: revision 2
81 >>>>>>> other: 0185f4e0cf02 - test: revision 2
82 space
82 space
83 # hg stat
83 # hg stat
84 M f
84 M f
85 ? f.orig
85 ? f.orig
86
86
87 simplest hgrc using false for merge:
87 simplest hgrc using false for merge:
88
88
89 $ echo "false.whatever=" >> .hg/hgrc
89 $ echo "false.whatever=" >> .hg/hgrc
90 $ beforemerge
90 $ beforemerge
91 [merge-tools]
91 [merge-tools]
92 false.whatever=
92 false.whatever=
93 # hg update -C 1
93 # hg update -C 1
94 $ hg merge -r 2
94 $ hg merge -r 2
95 merging f
95 merging f
96 merging f failed!
96 merging f failed!
97 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
97 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
98 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
98 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
99 [1]
99 [1]
100 $ aftermerge
100 $ aftermerge
101 # cat f
101 # cat f
102 revision 1
102 revision 1
103 space
103 space
104 # hg stat
104 # hg stat
105 M f
105 M f
106 ? f.orig
106 ? f.orig
107
107
108 unexecutable file in $PATH shouldn't be found:
108 unexecutable file in $PATH shouldn't be found:
109
109
110 $ touch false
110 $ touch false
111 $ hg up -qC 1
111 $ hg up -qC 1
112 $ PATH="`pwd`:$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
112 $ PATH="`pwd`:$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
113 merging f
113 merging f
114 warning: conflicts during merge.
114 warning: conflicts during merge.
115 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
115 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
116 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
116 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
117 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
117 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
118 [1]
118 [1]
119 $ rm false
119 $ rm false
120
120
121 executable directory in $PATH shouldn't be found:
121 executable directory in $PATH shouldn't be found:
122
122
123 $ mkdir false
123 $ mkdir false
124 $ hg up -qC 1
124 $ hg up -qC 1
125 $ PATH="`pwd`:$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
125 $ PATH="`pwd`:$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
126 merging f
126 merging f
127 warning: conflicts during merge.
127 warning: conflicts during merge.
128 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
128 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
129 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
129 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
130 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
130 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
131 [1]
131 [1]
132 $ rmdir false
132 $ rmdir false
133
133
134 true with higher .priority gets precedence:
134 true with higher .priority gets precedence:
135
135
136 $ echo "true.priority=1" >> .hg/hgrc
136 $ echo "true.priority=1" >> .hg/hgrc
137 $ beforemerge
137 $ beforemerge
138 [merge-tools]
138 [merge-tools]
139 false.whatever=
139 false.whatever=
140 true.priority=1
140 true.priority=1
141 # hg update -C 1
141 # hg update -C 1
142 $ hg merge -r 2
142 $ hg merge -r 2
143 merging f
143 merging f
144 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
144 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
145 (branch merge, don't forget to commit)
145 (branch merge, don't forget to commit)
146 $ aftermerge
146 $ aftermerge
147 # cat f
147 # cat f
148 revision 1
148 revision 1
149 space
149 space
150 # hg stat
150 # hg stat
151 M f
151 M f
152
152
153 unless lowered on command line:
153 unless lowered on command line:
154
154
155 $ beforemerge
155 $ beforemerge
156 [merge-tools]
156 [merge-tools]
157 false.whatever=
157 false.whatever=
158 true.priority=1
158 true.priority=1
159 # hg update -C 1
159 # hg update -C 1
160 $ hg merge -r 2 --config merge-tools.true.priority=-7
160 $ hg merge -r 2 --config merge-tools.true.priority=-7
161 merging f
161 merging f
162 merging f failed!
162 merging f failed!
163 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
163 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
164 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
164 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
165 [1]
165 [1]
166 $ aftermerge
166 $ aftermerge
167 # cat f
167 # cat f
168 revision 1
168 revision 1
169 space
169 space
170 # hg stat
170 # hg stat
171 M f
171 M f
172 ? f.orig
172 ? f.orig
173
173
174 or false set higher on command line:
174 or false set higher on command line:
175
175
176 $ beforemerge
176 $ beforemerge
177 [merge-tools]
177 [merge-tools]
178 false.whatever=
178 false.whatever=
179 true.priority=1
179 true.priority=1
180 # hg update -C 1
180 # hg update -C 1
181 $ hg merge -r 2 --config merge-tools.false.priority=117
181 $ hg merge -r 2 --config merge-tools.false.priority=117
182 merging f
182 merging f
183 merging f failed!
183 merging f failed!
184 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
184 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
185 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
185 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
186 [1]
186 [1]
187 $ aftermerge
187 $ aftermerge
188 # cat f
188 # cat f
189 revision 1
189 revision 1
190 space
190 space
191 # hg stat
191 # hg stat
192 M f
192 M f
193 ? f.orig
193 ? f.orig
194
194
195 or true.executable not found in PATH:
195 or true.executable not found in PATH:
196
196
197 $ beforemerge
197 $ beforemerge
198 [merge-tools]
198 [merge-tools]
199 false.whatever=
199 false.whatever=
200 true.priority=1
200 true.priority=1
201 # hg update -C 1
201 # hg update -C 1
202 $ hg merge -r 2 --config merge-tools.true.executable=nonexistentmergetool
202 $ hg merge -r 2 --config merge-tools.true.executable=nonexistentmergetool
203 merging f
203 merging f
204 merging f failed!
204 merging f failed!
205 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
205 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
206 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
206 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
207 [1]
207 [1]
208 $ aftermerge
208 $ aftermerge
209 # cat f
209 # cat f
210 revision 1
210 revision 1
211 space
211 space
212 # hg stat
212 # hg stat
213 M f
213 M f
214 ? f.orig
214 ? f.orig
215
215
216 or true.executable with bogus path:
216 or true.executable with bogus path:
217
217
218 $ beforemerge
218 $ beforemerge
219 [merge-tools]
219 [merge-tools]
220 false.whatever=
220 false.whatever=
221 true.priority=1
221 true.priority=1
222 # hg update -C 1
222 # hg update -C 1
223 $ hg merge -r 2 --config merge-tools.true.executable=/nonexistent/mergetool
223 $ hg merge -r 2 --config merge-tools.true.executable=/nonexistent/mergetool
224 merging f
224 merging f
225 merging f failed!
225 merging f failed!
226 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
226 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
227 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
227 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
228 [1]
228 [1]
229 $ aftermerge
229 $ aftermerge
230 # cat f
230 # cat f
231 revision 1
231 revision 1
232 space
232 space
233 # hg stat
233 # hg stat
234 M f
234 M f
235 ? f.orig
235 ? f.orig
236
236
237 but true.executable set to cat found in PATH works:
237 but true.executable set to cat found in PATH works:
238
238
239 $ echo "true.executable=cat" >> .hg/hgrc
239 $ echo "true.executable=cat" >> .hg/hgrc
240 $ beforemerge
240 $ beforemerge
241 [merge-tools]
241 [merge-tools]
242 false.whatever=
242 false.whatever=
243 true.priority=1
243 true.priority=1
244 true.executable=cat
244 true.executable=cat
245 # hg update -C 1
245 # hg update -C 1
246 $ hg merge -r 2
246 $ hg merge -r 2
247 merging f
247 merging f
248 revision 1
248 revision 1
249 space
249 space
250 revision 0
250 revision 0
251 space
251 space
252 revision 2
252 revision 2
253 space
253 space
254 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
254 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
255 (branch merge, don't forget to commit)
255 (branch merge, don't forget to commit)
256 $ aftermerge
256 $ aftermerge
257 # cat f
257 # cat f
258 revision 1
258 revision 1
259 space
259 space
260 # hg stat
260 # hg stat
261 M f
261 M f
262
262
263 and true.executable set to cat with path works:
263 and true.executable set to cat with path works:
264
264
265 $ beforemerge
265 $ beforemerge
266 [merge-tools]
266 [merge-tools]
267 false.whatever=
267 false.whatever=
268 true.priority=1
268 true.priority=1
269 true.executable=cat
269 true.executable=cat
270 # hg update -C 1
270 # hg update -C 1
271 $ hg merge -r 2 --config merge-tools.true.executable=cat
271 $ hg merge -r 2 --config merge-tools.true.executable=cat
272 merging f
272 merging f
273 revision 1
273 revision 1
274 space
274 space
275 revision 0
275 revision 0
276 space
276 space
277 revision 2
277 revision 2
278 space
278 space
279 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
279 0 files updated, 1 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 $ aftermerge
281 $ aftermerge
282 # cat f
282 # cat f
283 revision 1
283 revision 1
284 space
284 space
285 # hg stat
285 # hg stat
286 M f
286 M f
287
287
288 #if unix-permissions
288 #if unix-permissions
289
289
290 environment variables in true.executable are handled:
290 environment variables in true.executable are handled:
291
291
292 $ echo 'echo "custom merge tool"' > .hg/merge.sh
292 $ echo 'echo "custom merge tool"' > .hg/merge.sh
293 $ beforemerge
293 $ beforemerge
294 [merge-tools]
294 [merge-tools]
295 false.whatever=
295 false.whatever=
296 true.priority=1
296 true.priority=1
297 true.executable=cat
297 true.executable=cat
298 # hg update -C 1
298 # hg update -C 1
299 $ hg --config merge-tools.true.executable='sh' \
299 $ hg --config merge-tools.true.executable='sh' \
300 > --config merge-tools.true.args=.hg/merge.sh \
300 > --config merge-tools.true.args=.hg/merge.sh \
301 > merge -r 2
301 > merge -r 2
302 merging f
302 merging f
303 custom merge tool
303 custom merge tool
304 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
304 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
305 (branch merge, don't forget to commit)
305 (branch merge, don't forget to commit)
306 $ aftermerge
306 $ aftermerge
307 # cat f
307 # cat f
308 revision 1
308 revision 1
309 space
309 space
310 # hg stat
310 # hg stat
311 M f
311 M f
312
312
313 #endif
313 #endif
314
314
315 Tool selection and merge-patterns
315 Tool selection and merge-patterns
316
316
317 merge-patterns specifies new tool false:
317 merge-patterns specifies new tool false:
318
318
319 $ beforemerge
319 $ beforemerge
320 [merge-tools]
320 [merge-tools]
321 false.whatever=
321 false.whatever=
322 true.priority=1
322 true.priority=1
323 true.executable=cat
323 true.executable=cat
324 # hg update -C 1
324 # hg update -C 1
325 $ hg merge -r 2 --config merge-patterns.f=false
325 $ hg merge -r 2 --config merge-patterns.f=false
326 merging f
326 merging f
327 merging f failed!
327 merging f failed!
328 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
328 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
329 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
329 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
330 [1]
330 [1]
331 $ aftermerge
331 $ aftermerge
332 # cat f
332 # cat f
333 revision 1
333 revision 1
334 space
334 space
335 # hg stat
335 # hg stat
336 M f
336 M f
337 ? f.orig
337 ? f.orig
338
338
339 merge-patterns specifies executable not found in PATH and gets warning:
339 merge-patterns specifies executable not found in PATH and gets warning:
340
340
341 $ beforemerge
341 $ beforemerge
342 [merge-tools]
342 [merge-tools]
343 false.whatever=
343 false.whatever=
344 true.priority=1
344 true.priority=1
345 true.executable=cat
345 true.executable=cat
346 # hg update -C 1
346 # hg update -C 1
347 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool
347 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool
348 couldn't find merge tool true specified for f
348 couldn't find merge tool true specified for f
349 merging f
349 merging f
350 merging f failed!
350 merging f failed!
351 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
351 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
352 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
352 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
353 [1]
353 [1]
354 $ aftermerge
354 $ aftermerge
355 # cat f
355 # cat f
356 revision 1
356 revision 1
357 space
357 space
358 # hg stat
358 # hg stat
359 M f
359 M f
360 ? f.orig
360 ? f.orig
361
361
362 merge-patterns specifies executable with bogus path and gets warning:
362 merge-patterns specifies executable with bogus path and gets warning:
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=true --config merge-tools.true.executable=/nonexistent/mergetool
370 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexistent/mergetool
371 couldn't find merge tool true specified for f
371 couldn't find merge tool true specified for f
372 merging f
372 merging f
373 merging f failed!
373 merging f failed!
374 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
374 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
375 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
375 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
376 [1]
376 [1]
377 $ aftermerge
377 $ aftermerge
378 # cat f
378 # cat f
379 revision 1
379 revision 1
380 space
380 space
381 # hg stat
381 # hg stat
382 M f
382 M f
383 ? f.orig
383 ? f.orig
384
384
385 ui.merge overrules priority
385 ui.merge overrules priority
386
386
387 ui.merge specifies false:
387 ui.merge specifies false:
388
388
389 $ beforemerge
389 $ beforemerge
390 [merge-tools]
390 [merge-tools]
391 false.whatever=
391 false.whatever=
392 true.priority=1
392 true.priority=1
393 true.executable=cat
393 true.executable=cat
394 # hg update -C 1
394 # hg update -C 1
395 $ hg merge -r 2 --config ui.merge=false
395 $ hg merge -r 2 --config ui.merge=false
396 merging f
396 merging f
397 merging f failed!
397 merging f failed!
398 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
398 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
399 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
399 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
400 [1]
400 [1]
401 $ aftermerge
401 $ aftermerge
402 # cat f
402 # cat f
403 revision 1
403 revision 1
404 space
404 space
405 # hg stat
405 # hg stat
406 M f
406 M f
407 ? f.orig
407 ? f.orig
408
408
409 ui.merge specifies internal:fail:
409 ui.merge specifies internal:fail:
410
410
411 $ beforemerge
411 $ beforemerge
412 [merge-tools]
412 [merge-tools]
413 false.whatever=
413 false.whatever=
414 true.priority=1
414 true.priority=1
415 true.executable=cat
415 true.executable=cat
416 # hg update -C 1
416 # hg update -C 1
417 $ hg merge -r 2 --config ui.merge=internal:fail
417 $ hg merge -r 2 --config ui.merge=internal:fail
418 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
418 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
419 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
419 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
420 [1]
420 [1]
421 $ aftermerge
421 $ aftermerge
422 # cat f
422 # cat f
423 revision 1
423 revision 1
424 space
424 space
425 # hg stat
425 # hg stat
426 M f
426 M f
427
427
428 ui.merge specifies :local (without internal prefix):
428 ui.merge specifies :local (without internal prefix):
429
429
430 $ beforemerge
430 $ beforemerge
431 [merge-tools]
431 [merge-tools]
432 false.whatever=
432 false.whatever=
433 true.priority=1
433 true.priority=1
434 true.executable=cat
434 true.executable=cat
435 # hg update -C 1
435 # hg update -C 1
436 $ hg merge -r 2 --config ui.merge=:local
436 $ hg merge -r 2 --config ui.merge=:local
437 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
437 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
438 (branch merge, don't forget to commit)
438 (branch merge, don't forget to commit)
439 $ aftermerge
439 $ aftermerge
440 # cat f
440 # cat f
441 revision 1
441 revision 1
442 space
442 space
443 # hg stat
443 # hg stat
444 M f
444 M f
445
445
446 ui.merge specifies internal:other:
446 ui.merge specifies internal:other:
447
447
448 $ beforemerge
448 $ beforemerge
449 [merge-tools]
449 [merge-tools]
450 false.whatever=
450 false.whatever=
451 true.priority=1
451 true.priority=1
452 true.executable=cat
452 true.executable=cat
453 # hg update -C 1
453 # hg update -C 1
454 $ hg merge -r 2 --config ui.merge=internal:other
454 $ hg merge -r 2 --config ui.merge=internal:other
455 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
455 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
456 (branch merge, don't forget to commit)
456 (branch merge, don't forget to commit)
457 $ aftermerge
457 $ aftermerge
458 # cat f
458 # cat f
459 revision 2
459 revision 2
460 space
460 space
461 # hg stat
461 # hg stat
462 M f
462 M f
463
463
464 ui.merge specifies internal:prompt:
464 ui.merge specifies internal:prompt:
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:prompt
472 $ hg merge -r 2 --config ui.merge=internal:prompt
473 no tool found to merge f
473 no tool found to merge f
474 keep (l)ocal or take (o)ther? l
474 keep (l)ocal or take (o)ther? l
475 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
475 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
476 (branch merge, don't forget to commit)
476 (branch merge, don't forget to commit)
477 $ aftermerge
477 $ aftermerge
478 # cat f
478 # cat f
479 revision 1
479 revision 1
480 space
480 space
481 # hg stat
481 # hg stat
482 M f
482 M f
483
483
484 ui.merge specifies internal:dump:
484 ui.merge specifies internal:dump:
485
485
486 $ beforemerge
486 $ beforemerge
487 [merge-tools]
487 [merge-tools]
488 false.whatever=
488 false.whatever=
489 true.priority=1
489 true.priority=1
490 true.executable=cat
490 true.executable=cat
491 # hg update -C 1
491 # hg update -C 1
492 $ hg merge -r 2 --config ui.merge=internal:dump
492 $ hg merge -r 2 --config ui.merge=internal:dump
493 merging f
493 merging f
494 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
494 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
495 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
495 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
496 [1]
496 [1]
497 $ aftermerge
497 $ aftermerge
498 # cat f
498 # cat f
499 revision 1
499 revision 1
500 space
500 space
501 # hg stat
501 # hg stat
502 M f
502 M f
503 ? f.base
503 ? f.base
504 ? f.local
504 ? f.local
505 ? f.orig
505 ? f.orig
506 ? f.other
506 ? f.other
507
507
508 f.base:
508 f.base:
509
509
510 $ cat f.base
510 $ cat f.base
511 revision 0
511 revision 0
512 space
512 space
513
513
514 f.local:
514 f.local:
515
515
516 $ cat f.local
516 $ cat f.local
517 revision 1
517 revision 1
518 space
518 space
519
519
520 f.other:
520 f.other:
521
521
522 $ cat f.other
522 $ cat f.other
523 revision 2
523 revision 2
524 space
524 space
525 $ rm f.base f.local f.other
525 $ rm f.base f.local f.other
526
526
527 ui.merge specifies internal:other but is overruled by pattern for false:
527 ui.merge specifies internal:other but is overruled by pattern for false:
528
528
529 $ beforemerge
529 $ beforemerge
530 [merge-tools]
530 [merge-tools]
531 false.whatever=
531 false.whatever=
532 true.priority=1
532 true.priority=1
533 true.executable=cat
533 true.executable=cat
534 # hg update -C 1
534 # hg update -C 1
535 $ hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
535 $ hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
536 merging f
536 merging f
537 merging f failed!
537 merging f failed!
538 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
538 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
539 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
539 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
540 [1]
540 [1]
541 $ aftermerge
541 $ aftermerge
542 # cat f
542 # cat f
543 revision 1
543 revision 1
544 space
544 space
545 # hg stat
545 # hg stat
546 M f
546 M f
547 ? f.orig
547 ? f.orig
548
548
549 Premerge
549 Premerge
550
550
551 ui.merge specifies internal:other but is overruled by --tool=false
551 ui.merge specifies internal:other but is overruled by --tool=false
552
552
553 $ beforemerge
553 $ beforemerge
554 [merge-tools]
554 [merge-tools]
555 false.whatever=
555 false.whatever=
556 true.priority=1
556 true.priority=1
557 true.executable=cat
557 true.executable=cat
558 # hg update -C 1
558 # hg update -C 1
559 $ hg merge -r 2 --config ui.merge=internal:other --tool=false
559 $ hg merge -r 2 --config ui.merge=internal:other --tool=false
560 merging f
560 merging f
561 merging f failed!
561 merging f failed!
562 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
562 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
563 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
563 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
564 [1]
564 [1]
565 $ aftermerge
565 $ aftermerge
566 # cat f
566 # cat f
567 revision 1
567 revision 1
568 space
568 space
569 # hg stat
569 # hg stat
570 M f
570 M f
571 ? f.orig
571 ? f.orig
572
572
573 HGMERGE specifies internal:other but is overruled by --tool=false
573 HGMERGE specifies internal:other but is overruled by --tool=false
574
574
575 $ HGMERGE=internal:other ; export HGMERGE
575 $ HGMERGE=internal:other ; export HGMERGE
576 $ beforemerge
576 $ beforemerge
577 [merge-tools]
577 [merge-tools]
578 false.whatever=
578 false.whatever=
579 true.priority=1
579 true.priority=1
580 true.executable=cat
580 true.executable=cat
581 # hg update -C 1
581 # hg update -C 1
582 $ hg merge -r 2 --tool=false
582 $ hg merge -r 2 --tool=false
583 merging f
583 merging f
584 merging f failed!
584 merging f failed!
585 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
585 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
586 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
586 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
587 [1]
587 [1]
588 $ aftermerge
588 $ aftermerge
589 # cat f
589 # cat f
590 revision 1
590 revision 1
591 space
591 space
592 # hg stat
592 # hg stat
593 M f
593 M f
594 ? f.orig
594 ? f.orig
595
595
596 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
596 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
597
597
598 update is a merge ...
598 update is a merge ...
599
599
600 $ beforemerge
600 $ beforemerge
601 [merge-tools]
601 [merge-tools]
602 false.whatever=
602 false.whatever=
603 true.priority=1
603 true.priority=1
604 true.executable=cat
604 true.executable=cat
605 # hg update -C 1
605 # hg update -C 1
606 $ hg debugsetparent 0
606 $ hg debugsetparent 0
607 $ hg update -r 2
607 $ hg update -r 2
608 merging f
608 merging f
609 revision 1
609 revision 1
610 space
610 space
611 revision 0
611 revision 0
612 space
612 space
613 revision 2
613 revision 2
614 space
614 space
615 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
615 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
616 $ aftermerge
616 $ aftermerge
617 # cat f
617 # cat f
618 revision 1
618 revision 1
619 space
619 space
620 # hg stat
620 # hg stat
621 M f
621 M f
622
622
623 update should also have --tool
623 update should also have --tool
624
624
625 $ beforemerge
625 $ beforemerge
626 [merge-tools]
626 [merge-tools]
627 false.whatever=
627 false.whatever=
628 true.priority=1
628 true.priority=1
629 true.executable=cat
629 true.executable=cat
630 # hg update -C 1
630 # hg update -C 1
631 $ hg debugsetparent 0
631 $ hg debugsetparent 0
632 $ hg update -r 2 --tool false
632 $ hg update -r 2 --tool false
633 merging f
633 merging f
634 merging f failed!
634 merging f failed!
635 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
635 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
636 use 'hg resolve' to retry unresolved file merges
636 use 'hg resolve' to retry unresolved file merges
637 [1]
637 [1]
638 $ aftermerge
638 $ aftermerge
639 # cat f
639 # cat f
640 revision 1
640 revision 1
641 space
641 space
642 # hg stat
642 # hg stat
643 M f
643 M f
644 ? f.orig
644 ? f.orig
645
645
646 Default is silent simplemerge:
646 Default is silent simplemerge:
647
647
648 $ beforemerge
648 $ beforemerge
649 [merge-tools]
649 [merge-tools]
650 false.whatever=
650 false.whatever=
651 true.priority=1
651 true.priority=1
652 true.executable=cat
652 true.executable=cat
653 # hg update -C 1
653 # hg update -C 1
654 $ hg merge -r 3
654 $ hg merge -r 3
655 merging f
655 merging f
656 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
656 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
657 (branch merge, don't forget to commit)
657 (branch merge, don't forget to commit)
658 $ aftermerge
658 $ aftermerge
659 # cat f
659 # cat f
660 revision 1
660 revision 1
661 space
661 space
662 revision 3
662 revision 3
663 # hg stat
663 # hg stat
664 M f
664 M f
665
665
666 .premerge=True is same:
666 .premerge=True is same:
667
667
668 $ beforemerge
668 $ beforemerge
669 [merge-tools]
669 [merge-tools]
670 false.whatever=
670 false.whatever=
671 true.priority=1
671 true.priority=1
672 true.executable=cat
672 true.executable=cat
673 # hg update -C 1
673 # hg update -C 1
674 $ hg merge -r 3 --config merge-tools.true.premerge=True
674 $ hg merge -r 3 --config merge-tools.true.premerge=True
675 merging f
675 merging f
676 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
676 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
677 (branch merge, don't forget to commit)
677 (branch merge, don't forget to commit)
678 $ aftermerge
678 $ aftermerge
679 # cat f
679 # cat f
680 revision 1
680 revision 1
681 space
681 space
682 revision 3
682 revision 3
683 # hg stat
683 # hg stat
684 M f
684 M f
685
685
686 .premerge=False executes merge-tool:
686 .premerge=False executes merge-tool:
687
687
688 $ beforemerge
688 $ beforemerge
689 [merge-tools]
689 [merge-tools]
690 false.whatever=
690 false.whatever=
691 true.priority=1
691 true.priority=1
692 true.executable=cat
692 true.executable=cat
693 # hg update -C 1
693 # hg update -C 1
694 $ hg merge -r 3 --config merge-tools.true.premerge=False
694 $ hg merge -r 3 --config merge-tools.true.premerge=False
695 merging f
695 merging f
696 revision 1
696 revision 1
697 space
697 space
698 revision 0
698 revision 0
699 space
699 space
700 revision 0
700 revision 0
701 space
701 space
702 revision 3
702 revision 3
703 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
703 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
704 (branch merge, don't forget to commit)
704 (branch merge, don't forget to commit)
705 $ aftermerge
705 $ aftermerge
706 # cat f
706 # cat f
707 revision 1
707 revision 1
708 space
708 space
709 # hg stat
709 # hg stat
710 M f
710 M f
711
711
712 premerge=keep keeps conflict markers in:
712 premerge=keep keeps conflict markers in:
713
713
714 $ beforemerge
714 $ beforemerge
715 [merge-tools]
715 [merge-tools]
716 false.whatever=
716 false.whatever=
717 true.priority=1
717 true.priority=1
718 true.executable=cat
718 true.executable=cat
719 # hg update -C 1
719 # hg update -C 1
720 $ hg merge -r 4 --config merge-tools.true.premerge=keep
720 $ hg merge -r 4 --config merge-tools.true.premerge=keep
721 merging f
721 merging f
722 <<<<<<< local: ef83787e2614 - test: revision 1
722 <<<<<<< local: ef83787e2614 - test: revision 1
723 revision 1
723 revision 1
724 space
724 space
725 =======
725 =======
726 revision 4
726 revision 4
727 >>>>>>> other: 81448d39c9a0 - test: revision 4
727 >>>>>>> other: 81448d39c9a0 - test: revision 4
728 revision 0
728 revision 0
729 space
729 space
730 revision 4
730 revision 4
731 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
731 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
732 (branch merge, don't forget to commit)
732 (branch merge, don't forget to commit)
733 $ aftermerge
733 $ aftermerge
734 # cat f
734 # cat f
735 <<<<<<< local: ef83787e2614 - test: revision 1
735 <<<<<<< local: ef83787e2614 - test: revision 1
736 revision 1
736 revision 1
737 space
737 space
738 =======
738 =======
739 revision 4
739 revision 4
740 >>>>>>> other: 81448d39c9a0 - test: revision 4
740 >>>>>>> other: 81448d39c9a0 - test: revision 4
741 # hg stat
741 # hg stat
742 M f
742 M f
743
743
744 premerge=keep-merge3 keeps conflict markers with base content:
744 premerge=keep-merge3 keeps conflict markers with base content:
745
745
746 $ beforemerge
746 $ beforemerge
747 [merge-tools]
747 [merge-tools]
748 false.whatever=
748 false.whatever=
749 true.priority=1
749 true.priority=1
750 true.executable=cat
750 true.executable=cat
751 # hg update -C 1
751 # hg update -C 1
752 $ hg merge -r 4 --config merge-tools.true.premerge=keep-merge3
752 $ hg merge -r 4 --config merge-tools.true.premerge=keep-merge3
753 merging f
753 merging f
754 <<<<<<< local: ef83787e2614 - test: revision 1
754 <<<<<<< local: ef83787e2614 - test: revision 1
755 revision 1
755 revision 1
756 space
756 space
757 ||||||| base
757 ||||||| base
758 revision 0
758 revision 0
759 space
759 space
760 =======
760 =======
761 revision 4
761 revision 4
762 >>>>>>> other: 81448d39c9a0 - test: revision 4
762 >>>>>>> other: 81448d39c9a0 - test: revision 4
763 revision 0
763 revision 0
764 space
764 space
765 revision 4
765 revision 4
766 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
766 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
767 (branch merge, don't forget to commit)
767 (branch merge, don't forget to commit)
768 $ aftermerge
768 $ aftermerge
769 # cat f
769 # cat f
770 <<<<<<< local: ef83787e2614 - test: revision 1
770 <<<<<<< local: ef83787e2614 - test: revision 1
771 revision 1
771 revision 1
772 space
772 space
773 ||||||| base
773 ||||||| base
774 revision 0
774 revision 0
775 space
775 space
776 =======
776 =======
777 revision 4
777 revision 4
778 >>>>>>> other: 81448d39c9a0 - test: revision 4
778 >>>>>>> other: 81448d39c9a0 - test: revision 4
779 # hg stat
779 # hg stat
780 M f
780 M f
781
781
782
782
783 Tool execution
783 Tool execution
784
784
785 set tools.args explicit to include $base $local $other $output:
785 set tools.args explicit to include $base $local $other $output:
786
786
787 $ beforemerge
787 $ beforemerge
788 [merge-tools]
788 [merge-tools]
789 false.whatever=
789 false.whatever=
790 true.priority=1
790 true.priority=1
791 true.executable=cat
791 true.executable=cat
792 # hg update -C 1
792 # hg update -C 1
793 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
793 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
794 > | sed 's,==> .* <==,==> ... <==,g'
794 > | sed 's,==> .* <==,==> ... <==,g'
795 merging f
795 merging f
796 ==> ... <==
796 ==> ... <==
797 revision 0
797 revision 0
798 space
798 space
799
799
800 ==> ... <==
800 ==> ... <==
801 revision 1
801 revision 1
802 space
802 space
803
803
804 ==> ... <==
804 ==> ... <==
805 revision 2
805 revision 2
806 space
806 space
807
807
808 ==> ... <==
808 ==> ... <==
809 revision 1
809 revision 1
810 space
810 space
811 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
811 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
812 (branch merge, don't forget to commit)
812 (branch merge, don't forget to commit)
813 $ aftermerge
813 $ aftermerge
814 # cat f
814 # cat f
815 revision 1
815 revision 1
816 space
816 space
817 # hg stat
817 # hg stat
818 M f
818 M f
819
819
820 Merge with "echo mergeresult > $local":
820 Merge with "echo mergeresult > $local":
821
821
822 $ beforemerge
822 $ beforemerge
823 [merge-tools]
823 [merge-tools]
824 false.whatever=
824 false.whatever=
825 true.priority=1
825 true.priority=1
826 true.executable=cat
826 true.executable=cat
827 # hg update -C 1
827 # hg update -C 1
828 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
828 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
829 merging f
829 merging f
830 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
830 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
831 (branch merge, don't forget to commit)
831 (branch merge, don't forget to commit)
832 $ aftermerge
832 $ aftermerge
833 # cat f
833 # cat f
834 mergeresult
834 mergeresult
835 # hg stat
835 # hg stat
836 M f
836 M f
837
837
838 - and $local is the file f:
838 - and $local is the file f:
839
839
840 $ beforemerge
840 $ beforemerge
841 [merge-tools]
841 [merge-tools]
842 false.whatever=
842 false.whatever=
843 true.priority=1
843 true.priority=1
844 true.executable=cat
844 true.executable=cat
845 # hg update -C 1
845 # hg update -C 1
846 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
846 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
847 merging f
847 merging f
848 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
848 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
849 (branch merge, don't forget to commit)
849 (branch merge, don't forget to commit)
850 $ aftermerge
850 $ aftermerge
851 # cat f
851 # cat f
852 mergeresult
852 mergeresult
853 # hg stat
853 # hg stat
854 M f
854 M f
855
855
856 Merge with "echo mergeresult > $output" - the variable is a bit magic:
856 Merge with "echo mergeresult > $output" - the variable is a bit magic:
857
857
858 $ beforemerge
858 $ beforemerge
859 [merge-tools]
859 [merge-tools]
860 false.whatever=
860 false.whatever=
861 true.priority=1
861 true.priority=1
862 true.executable=cat
862 true.executable=cat
863 # hg update -C 1
863 # hg update -C 1
864 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
864 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
865 merging f
865 merging f
866 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
866 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
867 (branch merge, don't forget to commit)
867 (branch merge, don't forget to commit)
868 $ aftermerge
868 $ aftermerge
869 # cat f
869 # cat f
870 mergeresult
870 mergeresult
871 # hg stat
871 # hg stat
872 M f
872 M f
873
873
874 Merge using tool with a path that must be quoted:
874 Merge using tool with a path that must be quoted:
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 $ cat <<EOF > 'my merge tool'
882 $ cat <<EOF > 'my merge tool'
883 > cat "\$1" "\$2" "\$3" > "\$4"
883 > cat "\$1" "\$2" "\$3" > "\$4"
884 > EOF
884 > EOF
885 $ hg --config merge-tools.true.executable='sh' \
885 $ hg --config merge-tools.true.executable='sh' \
886 > --config merge-tools.true.args='"./my merge tool" $base $local $other $output' \
886 > --config merge-tools.true.args='"./my merge tool" $base $local $other $output' \
887 > merge -r 2
887 > merge -r 2
888 merging f
888 merging f
889 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
889 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
890 (branch merge, don't forget to commit)
890 (branch merge, don't forget to commit)
891 $ rm -f 'my merge tool'
891 $ rm -f 'my merge tool'
892 $ aftermerge
892 $ aftermerge
893 # cat f
893 # cat f
894 revision 0
894 revision 0
895 space
895 space
896 revision 1
896 revision 1
897 space
897 space
898 revision 2
898 revision 2
899 space
899 space
900 # hg stat
900 # hg stat
901 M f
901 M f
902
902
903 Issue3581: Merging a filename that needs to be quoted
903 Issue3581: Merging a filename that needs to be quoted
904 (This test doesn't work on Windows filesystems even on Linux, so check
904 (This test doesn't work on Windows filesystems even on Linux, so check
905 for Unix-like permission)
905 for Unix-like permission)
906
906
907 #if unix-permissions
907 #if unix-permissions
908 $ beforemerge
908 $ beforemerge
909 [merge-tools]
909 [merge-tools]
910 false.whatever=
910 false.whatever=
911 true.priority=1
911 true.priority=1
912 true.executable=cat
912 true.executable=cat
913 # hg update -C 1
913 # hg update -C 1
914 $ echo "revision 5" > '"; exit 1; echo "'
914 $ echo "revision 5" > '"; exit 1; echo "'
915 $ hg commit -Am "revision 5"
915 $ hg commit -Am "revision 5"
916 adding "; exit 1; echo "
916 adding "; exit 1; echo "
917 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
917 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
918 $ hg update -C 1 > /dev/null
918 $ hg update -C 1 > /dev/null
919 $ echo "revision 6" > '"; exit 1; echo "'
919 $ echo "revision 6" > '"; exit 1; echo "'
920 $ hg commit -Am "revision 6"
920 $ hg commit -Am "revision 6"
921 adding "; exit 1; echo "
921 adding "; exit 1; echo "
922 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
922 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
923 created new head
923 created new head
924 $ hg merge --config merge-tools.true.executable="true" -r 5
924 $ hg merge --config merge-tools.true.executable="true" -r 5
925 merging "; exit 1; echo "
925 merging "; exit 1; echo "
926 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
926 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
927 (branch merge, don't forget to commit)
927 (branch merge, don't forget to commit)
928 $ hg update -C 1 > /dev/null
928 $ hg update -C 1 > /dev/null
929 #endif
929 #endif
930
930
931 Merge post-processing
931 Merge post-processing
932
932
933 cat is a bad merge-tool and doesn't change:
933 cat is a bad merge-tool and doesn't change:
934
934
935 $ beforemerge
935 $ beforemerge
936 [merge-tools]
936 [merge-tools]
937 false.whatever=
937 false.whatever=
938 true.priority=1
938 true.priority=1
939 true.executable=cat
939 true.executable=cat
940 # hg update -C 1
940 # hg update -C 1
941 $ hg merge -y -r 2 --config merge-tools.true.checkchanged=1
941 $ hg merge -y -r 2 --config merge-tools.true.checkchanged=1
942 merging f
942 merging f
943 revision 1
943 revision 1
944 space
944 space
945 revision 0
945 revision 0
946 space
946 space
947 revision 2
947 revision 2
948 space
948 space
949 output file f appears unchanged
949 output file f appears unchanged
950 was merge successful (yn)? n
950 was merge successful (yn)? n
951 merging f failed!
951 merging f failed!
952 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
952 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
953 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
953 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
954 [1]
954 [1]
955 $ aftermerge
955 $ aftermerge
956 # cat f
956 # cat f
957 revision 1
957 revision 1
958 space
958 space
959 # hg stat
959 # hg stat
960 M f
960 M f
961 ? f.orig
961 ? f.orig
962
962
963 #if symlink
963 #if symlink
964
964
965 internal merge cannot handle symlinks and shouldn't try:
965 internal merge cannot handle symlinks and shouldn't try:
966
966
967 $ hg update -q -C 1
967 $ hg update -q -C 1
968 $ rm f
968 $ rm f
969 $ ln -s symlink f
969 $ ln -s symlink f
970 $ hg commit -qm 'f is symlink'
970 $ hg commit -qm 'f is symlink'
971 $ hg merge -r 2 --tool internal:merge
971 $ hg merge -r 2 --tool internal:merge
972 merging f
972 merging f
973 warning: internal:merge cannot merge symlinks for f
973 warning: internal :merge cannot merge symlinks for f
974 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
974 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
975 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
975 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
976 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
976 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
977 [1]
977 [1]
978
978
979 #endif
979 #endif
@@ -1,379 +1,379 b''
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
38 a: versions differ -> m
39 updating: a 1/1 files (100.00%)
39 updating: a 1/1 files (100.00%)
40 picked tool 'internal:merge' for a (binary False symlink True)
40 picked tool 'internal:merge' for a (binary False symlink True)
41 merging a
41 merging a
42 my a@521a1e40188f+ other a@3574f3e69b1c ancestor a@c334dc3be0da
42 my a@521a1e40188f+ other a@3574f3e69b1c ancestor a@c334dc3be0da
43 warning: internal:merge cannot merge symlinks for a
43 warning: internal :merge cannot merge symlinks for a
44 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
44 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
45 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
45 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
46 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
46 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
47 [1]
47 [1]
48
48
49 $ tellmeabout a
49 $ tellmeabout a
50 a is a symlink:
50 a is a symlink:
51 a -> symlink
51 a -> symlink
52 $ hg resolve a --tool internal:other
52 $ hg resolve a --tool internal:other
53 (no more unresolved files)
53 (no more unresolved files)
54 $ tellmeabout a
54 $ tellmeabout a
55 a is an executable file with content:
55 a is an executable file with content:
56 a
56 a
57 $ hg st
57 $ hg st
58 M a
58 M a
59 ? a.orig
59 ? a.orig
60
60
61 Symlink is other parent, executable is local:
61 Symlink is other parent, executable is local:
62
62
63 $ hg update -C 1
63 $ hg update -C 1
64 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
65
65
66 $ hg merge --debug
66 $ hg merge --debug
67 searching for copies back to rev 1
67 searching for copies back to rev 1
68 resolving manifests
68 resolving manifests
69 branchmerge: True, force: False, partial: False
69 branchmerge: True, force: False, partial: False
70 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
70 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
71 preserving a for resolve of a
71 preserving a for resolve of a
72 a: versions differ -> m
72 a: versions differ -> m
73 updating: a 1/1 files (100.00%)
73 updating: a 1/1 files (100.00%)
74 picked tool 'internal:merge' for a (binary False symlink True)
74 picked tool 'internal:merge' for a (binary False symlink True)
75 merging a
75 merging a
76 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
76 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
77 warning: internal:merge cannot merge symlinks for a
77 warning: internal :merge cannot merge symlinks for a
78 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
78 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
79 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
79 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
80 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
80 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
81 [1]
81 [1]
82
82
83 $ tellmeabout a
83 $ tellmeabout a
84 a is an executable file with content:
84 a is an executable file with content:
85 a
85 a
86
86
87 Update to link without local change should get us a symlink (issue3316):
87 Update to link without local change should get us a symlink (issue3316):
88
88
89 $ hg up -C 0
89 $ hg up -C 0
90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 $ hg up
91 $ hg up
92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 $ hg st
93 $ hg st
94 ? a.orig
94 ? a.orig
95
95
96 Update to link with local change should cause a merge prompt (issue3200):
96 Update to link with local change should cause a merge prompt (issue3200):
97
97
98 $ hg up -Cq 0
98 $ hg up -Cq 0
99 $ echo data > a
99 $ echo data > a
100 $ HGMERGE= hg up -y --debug
100 $ HGMERGE= hg up -y --debug
101 searching for copies back to rev 2
101 searching for copies back to rev 2
102 resolving manifests
102 resolving manifests
103 branchmerge: False, force: False, partial: False
103 branchmerge: False, force: False, partial: False
104 ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
104 ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
105 preserving a for resolve of a
105 preserving a for resolve of a
106 a: versions differ -> m
106 a: versions differ -> m
107 updating: a 1/1 files (100.00%)
107 updating: a 1/1 files (100.00%)
108 (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
108 (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
109 picked tool 'internal:prompt' for a (binary False symlink True)
109 picked tool ':prompt' for a (binary False symlink True)
110 no tool found to merge a
110 no tool found to merge a
111 keep (l)ocal or take (o)ther? l
111 keep (l)ocal or take (o)ther? l
112 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
112 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
113 $ hg diff --git
113 $ hg diff --git
114 diff --git a/a b/a
114 diff --git a/a b/a
115 old mode 120000
115 old mode 120000
116 new mode 100644
116 new mode 100644
117 --- a/a
117 --- a/a
118 +++ b/a
118 +++ b/a
119 @@ -1,1 +1,1 @@
119 @@ -1,1 +1,1 @@
120 -symlink
120 -symlink
121 \ No newline at end of file
121 \ No newline at end of file
122 +data
122 +data
123
123
124
124
125 Test only 'l' change - happens rarely, except when recovering from situations
125 Test only 'l' change - happens rarely, except when recovering from situations
126 where that was what happened.
126 where that was what happened.
127
127
128 $ hg init test2
128 $ hg init test2
129 $ cd test2
129 $ cd test2
130 $ printf base > f
130 $ printf base > f
131 $ hg ci -Aqm0
131 $ hg ci -Aqm0
132 $ echo file > f
132 $ echo file > f
133 $ echo content >> f
133 $ echo content >> f
134 $ hg ci -qm1
134 $ hg ci -qm1
135 $ hg up -qr0
135 $ hg up -qr0
136 $ rm f
136 $ rm f
137 $ ln -s base f
137 $ ln -s base f
138 $ hg ci -qm2
138 $ hg ci -qm2
139 $ hg merge
139 $ hg merge
140 merging f
140 merging f
141 warning: internal:merge cannot merge symlinks for f
141 warning: internal :merge cannot merge symlinks for f
142 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
142 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
143 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
143 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
144 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
144 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
145 [1]
145 [1]
146 $ tellmeabout f
146 $ tellmeabout f
147 f is a symlink:
147 f is a symlink:
148 f -> base
148 f -> base
149
149
150 $ hg up -Cqr1
150 $ hg up -Cqr1
151 $ hg merge
151 $ hg merge
152 merging f
152 merging f
153 warning: internal:merge cannot merge symlinks for f
153 warning: internal :merge cannot merge symlinks for f
154 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
154 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
155 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
155 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
156 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
156 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
157 [1]
157 [1]
158 $ tellmeabout f
158 $ tellmeabout f
159 f is a plain file with content:
159 f is a plain file with content:
160 file
160 file
161 content
161 content
162
162
163 $ cd ..
163 $ cd ..
164
164
165 Test removed 'x' flag merged with change to symlink
165 Test removed 'x' flag merged with change to symlink
166
166
167 $ hg init test3
167 $ hg init test3
168 $ cd test3
168 $ cd test3
169 $ echo f > f
169 $ echo f > f
170 $ chmod +x f
170 $ chmod +x f
171 $ hg ci -Aqm0
171 $ hg ci -Aqm0
172 $ chmod -x f
172 $ chmod -x f
173 $ hg ci -qm1
173 $ hg ci -qm1
174 $ hg up -qr0
174 $ hg up -qr0
175 $ rm f
175 $ rm f
176 $ ln -s dangling f
176 $ ln -s dangling f
177 $ hg ci -qm2
177 $ hg ci -qm2
178 $ hg merge
178 $ hg merge
179 merging f
179 merging f
180 warning: internal:merge cannot merge symlinks for f
180 warning: internal :merge cannot merge symlinks for f
181 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
181 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
182 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
182 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
183 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
183 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
184 [1]
184 [1]
185 $ tellmeabout f
185 $ tellmeabout f
186 f is a symlink:
186 f is a symlink:
187 f -> dangling
187 f -> dangling
188
188
189 $ hg up -Cqr1
189 $ hg up -Cqr1
190 $ hg merge
190 $ hg merge
191 merging f
191 merging f
192 warning: internal:merge cannot merge symlinks for f
192 warning: internal :merge cannot merge symlinks for f
193 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
193 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
194 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
194 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
195 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
195 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
196 [1]
196 [1]
197 $ tellmeabout f
197 $ tellmeabout f
198 f is a plain file with content:
198 f is a plain file with content:
199 f
199 f
200
200
201 Test removed 'x' flag merged with content change - both ways
201 Test removed 'x' flag merged with content change - both ways
202
202
203 $ hg up -Cqr0
203 $ hg up -Cqr0
204 $ echo change > f
204 $ echo change > f
205 $ hg ci -qm3
205 $ hg ci -qm3
206 $ hg merge -r1
206 $ hg merge -r1
207 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
208 (branch merge, don't forget to commit)
208 (branch merge, don't forget to commit)
209 $ tellmeabout f
209 $ tellmeabout f
210 f is a plain file with content:
210 f is a plain file with content:
211 change
211 change
212
212
213 $ hg up -qCr1
213 $ hg up -qCr1
214 $ hg merge -r3
214 $ hg merge -r3
215 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 (branch merge, don't forget to commit)
216 (branch merge, don't forget to commit)
217 $ tellmeabout f
217 $ tellmeabout f
218 f is a plain file with content:
218 f is a plain file with content:
219 change
219 change
220
220
221 $ cd ..
221 $ cd ..
222
222
223 Test merge with no common ancestor:
223 Test merge with no common ancestor:
224 a: just different
224 a: just different
225 b: x vs -, different (cannot calculate x, cannot ask merge tool)
225 b: x vs -, different (cannot calculate x, cannot ask merge tool)
226 c: x vs -, same (cannot calculate x, merge tool is no good)
226 c: x vs -, same (cannot calculate x, merge tool is no good)
227 d: x vs l, different
227 d: x vs l, different
228 e: x vs l, same
228 e: x vs l, same
229 f: - vs l, different
229 f: - vs l, different
230 g: - vs l, same
230 g: - vs l, same
231 h: l vs l, different
231 h: l vs l, different
232 (where same means the filelog entry is shared and there thus is an ancestor!)
232 (where same means the filelog entry is shared and there thus is an ancestor!)
233
233
234 $ hg init test4
234 $ hg init test4
235 $ cd test4
235 $ cd test4
236 $ echo 0 > 0
236 $ echo 0 > 0
237 $ hg ci -Aqm0
237 $ hg ci -Aqm0
238
238
239 $ echo 1 > a
239 $ echo 1 > a
240 $ echo 1 > b
240 $ echo 1 > b
241 $ chmod +x b
241 $ chmod +x b
242 $ echo x > c
242 $ echo x > c
243 $ chmod +x c
243 $ chmod +x c
244 $ echo 1 > d
244 $ echo 1 > d
245 $ chmod +x d
245 $ chmod +x d
246 $ printf x > e
246 $ printf x > e
247 $ chmod +x e
247 $ chmod +x e
248 $ echo 1 > f
248 $ echo 1 > f
249 $ printf x > g
249 $ printf x > g
250 $ ln -s 1 h
250 $ ln -s 1 h
251 $ hg ci -qAm1
251 $ hg ci -qAm1
252
252
253 $ hg up -qr0
253 $ hg up -qr0
254 $ echo 2 > a
254 $ echo 2 > a
255 $ echo 2 > b
255 $ echo 2 > b
256 $ echo x > c
256 $ echo x > c
257 $ ln -s 2 d
257 $ ln -s 2 d
258 $ ln -s x e
258 $ ln -s x e
259 $ ln -s 2 f
259 $ ln -s 2 f
260 $ ln -s x g
260 $ ln -s x g
261 $ ln -s 2 h
261 $ ln -s 2 h
262 $ hg ci -Aqm2
262 $ hg ci -Aqm2
263
263
264 $ hg merge
264 $ hg merge
265 merging a
265 merging a
266 warning: conflicts during merge.
266 warning: conflicts during merge.
267 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
267 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
268 warning: cannot merge flags for b
268 warning: cannot merge flags for b
269 merging b
269 merging b
270 warning: conflicts during merge.
270 warning: conflicts during merge.
271 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
271 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
272 warning: cannot merge flags for c
272 warning: cannot merge flags for c
273 merging d
273 merging d
274 warning: internal:merge cannot merge symlinks for d
274 warning: internal :merge cannot merge symlinks for d
275 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
275 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
276 merging f
276 merging f
277 warning: internal:merge cannot merge symlinks for f
277 warning: internal :merge cannot merge symlinks for f
278 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
278 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
279 merging h
279 merging h
280 warning: internal:merge cannot merge symlinks for h
280 warning: internal :merge cannot merge symlinks for h
281 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
281 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
282 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
282 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
283 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
283 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
284 [1]
284 [1]
285 $ hg resolve -l
285 $ hg resolve -l
286 U a
286 U a
287 U b
287 U b
288 U d
288 U d
289 U f
289 U f
290 U h
290 U h
291 $ tellmeabout a
291 $ tellmeabout a
292 a is a plain file with content:
292 a is a plain file with content:
293 <<<<<<< local: 0139c5610547 - test: 2
293 <<<<<<< local: 0139c5610547 - test: 2
294 2
294 2
295 =======
295 =======
296 1
296 1
297 >>>>>>> other: 97e29675e796 - test: 1
297 >>>>>>> other: 97e29675e796 - test: 1
298 $ tellmeabout b
298 $ tellmeabout b
299 b is a plain file with content:
299 b is a plain file with content:
300 <<<<<<< local: 0139c5610547 - test: 2
300 <<<<<<< local: 0139c5610547 - test: 2
301 2
301 2
302 =======
302 =======
303 1
303 1
304 >>>>>>> other: 97e29675e796 - test: 1
304 >>>>>>> other: 97e29675e796 - test: 1
305 $ tellmeabout c
305 $ tellmeabout c
306 c is a plain file with content:
306 c is a plain file with content:
307 x
307 x
308 $ tellmeabout d
308 $ tellmeabout d
309 d is a symlink:
309 d is a symlink:
310 d -> 2
310 d -> 2
311 $ tellmeabout e
311 $ tellmeabout e
312 e is a symlink:
312 e is a symlink:
313 e -> x
313 e -> x
314 $ tellmeabout f
314 $ tellmeabout f
315 f is a symlink:
315 f is a symlink:
316 f -> 2
316 f -> 2
317 $ tellmeabout g
317 $ tellmeabout g
318 g is a symlink:
318 g is a symlink:
319 g -> x
319 g -> x
320 $ tellmeabout h
320 $ tellmeabout h
321 h is a symlink:
321 h is a symlink:
322 h -> 2
322 h -> 2
323
323
324 $ hg up -Cqr1
324 $ hg up -Cqr1
325 $ hg merge
325 $ hg merge
326 merging a
326 merging a
327 warning: conflicts during merge.
327 warning: conflicts during merge.
328 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
328 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
329 warning: cannot merge flags for b
329 warning: cannot merge flags for b
330 merging b
330 merging b
331 warning: conflicts during merge.
331 warning: conflicts during merge.
332 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
332 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
333 warning: cannot merge flags for c
333 warning: cannot merge flags for c
334 merging d
334 merging d
335 warning: internal:merge cannot merge symlinks for d
335 warning: internal :merge cannot merge symlinks for d
336 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
336 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
337 merging f
337 merging f
338 warning: internal:merge cannot merge symlinks for f
338 warning: internal :merge cannot merge symlinks for f
339 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
339 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
340 merging h
340 merging h
341 warning: internal:merge cannot merge symlinks for h
341 warning: internal :merge cannot merge symlinks for h
342 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
342 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
343 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
343 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
344 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
344 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
345 [1]
345 [1]
346 $ tellmeabout a
346 $ tellmeabout a
347 a is a plain file with content:
347 a is a plain file with content:
348 <<<<<<< local: 97e29675e796 - test: 1
348 <<<<<<< local: 97e29675e796 - test: 1
349 1
349 1
350 =======
350 =======
351 2
351 2
352 >>>>>>> other: 0139c5610547 - test: 2
352 >>>>>>> other: 0139c5610547 - test: 2
353 $ tellmeabout b
353 $ tellmeabout b
354 b is an executable file with content:
354 b is an executable file with content:
355 <<<<<<< local: 97e29675e796 - test: 1
355 <<<<<<< local: 97e29675e796 - test: 1
356 1
356 1
357 =======
357 =======
358 2
358 2
359 >>>>>>> other: 0139c5610547 - test: 2
359 >>>>>>> other: 0139c5610547 - test: 2
360 $ tellmeabout c
360 $ tellmeabout c
361 c is an executable file with content:
361 c is an executable file with content:
362 x
362 x
363 $ tellmeabout d
363 $ tellmeabout d
364 d is an executable file with content:
364 d is an executable file with content:
365 1
365 1
366 $ tellmeabout e
366 $ tellmeabout e
367 e is an executable file with content:
367 e is an executable file with content:
368 x (no-eol)
368 x (no-eol)
369 $ tellmeabout f
369 $ tellmeabout f
370 f is a plain file with content:
370 f is a plain file with content:
371 1
371 1
372 $ tellmeabout g
372 $ tellmeabout g
373 g is a plain file with content:
373 g is a plain file with content:
374 x (no-eol)
374 x (no-eol)
375 $ tellmeabout h
375 $ tellmeabout h
376 h is a symlink:
376 h is a symlink:
377 h -> 1
377 h -> 1
378
378
379 $ cd ..
379 $ cd ..
@@ -1,606 +1,606 b''
1 $ hg init test
1 $ hg init test
2 $ cd test
2 $ cd test
3
3
4 $ echo a > a
4 $ echo a > a
5 $ hg add a
5 $ hg add a
6 $ hg commit -m "test"
6 $ hg commit -m "test"
7 $ hg history
7 $ hg history
8 changeset: 0:acb14030fe0a
8 changeset: 0:acb14030fe0a
9 tag: tip
9 tag: tip
10 user: test
10 user: test
11 date: Thu Jan 01 00:00:00 1970 +0000
11 date: Thu Jan 01 00:00:00 1970 +0000
12 summary: test
12 summary: test
13
13
14
14
15 $ hg tag ' '
15 $ hg tag ' '
16 abort: tag names cannot consist entirely of whitespace
16 abort: tag names cannot consist entirely of whitespace
17 [255]
17 [255]
18
18
19 (this tests also that editor is not invoked, if '--edit' is not
19 (this tests also that editor is not invoked, if '--edit' is not
20 specified)
20 specified)
21
21
22 $ HGEDITOR=cat hg tag "bleah"
22 $ HGEDITOR=cat hg tag "bleah"
23 $ hg history
23 $ hg history
24 changeset: 1:d4f0d2909abc
24 changeset: 1:d4f0d2909abc
25 tag: tip
25 tag: tip
26 user: test
26 user: test
27 date: Thu Jan 01 00:00:00 1970 +0000
27 date: Thu Jan 01 00:00:00 1970 +0000
28 summary: Added tag bleah for changeset acb14030fe0a
28 summary: Added tag bleah for changeset acb14030fe0a
29
29
30 changeset: 0:acb14030fe0a
30 changeset: 0:acb14030fe0a
31 tag: bleah
31 tag: bleah
32 user: test
32 user: test
33 date: Thu Jan 01 00:00:00 1970 +0000
33 date: Thu Jan 01 00:00:00 1970 +0000
34 summary: test
34 summary: test
35
35
36
36
37 $ echo foo >> .hgtags
37 $ echo foo >> .hgtags
38 $ hg tag "bleah2"
38 $ hg tag "bleah2"
39 abort: working copy of .hgtags is changed
39 abort: working copy of .hgtags is changed
40 (please commit .hgtags manually)
40 (please commit .hgtags manually)
41 [255]
41 [255]
42
42
43 $ hg revert .hgtags
43 $ hg revert .hgtags
44 $ hg tag -r 0 x y z y y z
44 $ hg tag -r 0 x y z y y z
45 abort: tag names must be unique
45 abort: tag names must be unique
46 [255]
46 [255]
47 $ hg tag tap nada dot tip
47 $ hg tag tap nada dot tip
48 abort: the name 'tip' is reserved
48 abort: the name 'tip' is reserved
49 [255]
49 [255]
50 $ hg tag .
50 $ hg tag .
51 abort: the name '.' is reserved
51 abort: the name '.' is reserved
52 [255]
52 [255]
53 $ hg tag null
53 $ hg tag null
54 abort: the name 'null' is reserved
54 abort: the name 'null' is reserved
55 [255]
55 [255]
56 $ hg tag "bleah"
56 $ hg tag "bleah"
57 abort: tag 'bleah' already exists (use -f to force)
57 abort: tag 'bleah' already exists (use -f to force)
58 [255]
58 [255]
59 $ hg tag "blecch" "bleah"
59 $ hg tag "blecch" "bleah"
60 abort: tag 'bleah' already exists (use -f to force)
60 abort: tag 'bleah' already exists (use -f to force)
61 [255]
61 [255]
62
62
63 $ hg tag --remove "blecch"
63 $ hg tag --remove "blecch"
64 abort: tag 'blecch' does not exist
64 abort: tag 'blecch' does not exist
65 [255]
65 [255]
66 $ hg tag --remove "bleah" "blecch" "blough"
66 $ hg tag --remove "bleah" "blecch" "blough"
67 abort: tag 'blecch' does not exist
67 abort: tag 'blecch' does not exist
68 [255]
68 [255]
69
69
70 $ hg tag -r 0 "bleah0"
70 $ hg tag -r 0 "bleah0"
71 $ hg tag -l -r 1 "bleah1"
71 $ hg tag -l -r 1 "bleah1"
72 $ hg tag gack gawk gorp
72 $ hg tag gack gawk gorp
73 $ hg tag -f gack
73 $ hg tag -f gack
74 $ hg tag --remove gack gorp
74 $ hg tag --remove gack gorp
75
75
76 $ hg tag "bleah "
76 $ hg tag "bleah "
77 abort: tag 'bleah' already exists (use -f to force)
77 abort: tag 'bleah' already exists (use -f to force)
78 [255]
78 [255]
79 $ hg tag " bleah"
79 $ hg tag " bleah"
80 abort: tag 'bleah' already exists (use -f to force)
80 abort: tag 'bleah' already exists (use -f to force)
81 [255]
81 [255]
82 $ hg tag " bleah"
82 $ hg tag " bleah"
83 abort: tag 'bleah' already exists (use -f to force)
83 abort: tag 'bleah' already exists (use -f to force)
84 [255]
84 [255]
85 $ hg tag -r 0 " bleahbleah "
85 $ hg tag -r 0 " bleahbleah "
86 $ hg tag -r 0 " bleah bleah "
86 $ hg tag -r 0 " bleah bleah "
87
87
88 $ cat .hgtags
88 $ cat .hgtags
89 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
89 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
90 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
90 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
91 336fccc858a4eb69609a291105009e484a6b6b8d gack
91 336fccc858a4eb69609a291105009e484a6b6b8d gack
92 336fccc858a4eb69609a291105009e484a6b6b8d gawk
92 336fccc858a4eb69609a291105009e484a6b6b8d gawk
93 336fccc858a4eb69609a291105009e484a6b6b8d gorp
93 336fccc858a4eb69609a291105009e484a6b6b8d gorp
94 336fccc858a4eb69609a291105009e484a6b6b8d gack
94 336fccc858a4eb69609a291105009e484a6b6b8d gack
95 799667b6f2d9b957f73fa644a918c2df22bab58f gack
95 799667b6f2d9b957f73fa644a918c2df22bab58f gack
96 799667b6f2d9b957f73fa644a918c2df22bab58f gack
96 799667b6f2d9b957f73fa644a918c2df22bab58f gack
97 0000000000000000000000000000000000000000 gack
97 0000000000000000000000000000000000000000 gack
98 336fccc858a4eb69609a291105009e484a6b6b8d gorp
98 336fccc858a4eb69609a291105009e484a6b6b8d gorp
99 0000000000000000000000000000000000000000 gorp
99 0000000000000000000000000000000000000000 gorp
100 acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
100 acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
101 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
101 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
102
102
103 $ cat .hg/localtags
103 $ cat .hg/localtags
104 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
104 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
105
105
106 tagging on a non-head revision
106 tagging on a non-head revision
107
107
108 $ hg update 0
108 $ hg update 0
109 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
109 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
110 $ hg tag -l localblah
110 $ hg tag -l localblah
111 $ hg tag "foobar"
111 $ hg tag "foobar"
112 abort: not at a branch head (use -f to force)
112 abort: not at a branch head (use -f to force)
113 [255]
113 [255]
114 $ hg tag -f "foobar"
114 $ hg tag -f "foobar"
115 $ cat .hgtags
115 $ cat .hgtags
116 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
116 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
117 $ cat .hg/localtags
117 $ cat .hg/localtags
118 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
118 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
119 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
119 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
120
120
121 $ hg tag -l 'xx
121 $ hg tag -l 'xx
122 > newline'
122 > newline'
123 abort: '\n' cannot be used in a name
123 abort: '\n' cannot be used in a name
124 [255]
124 [255]
125 $ hg tag -l 'xx:xx'
125 $ hg tag -l 'xx:xx'
126 abort: ':' cannot be used in a name
126 abort: ':' cannot be used in a name
127 [255]
127 [255]
128
128
129 cloning local tags
129 cloning local tags
130
130
131 $ cd ..
131 $ cd ..
132 $ hg -R test log -r0:5
132 $ hg -R test log -r0:5
133 changeset: 0:acb14030fe0a
133 changeset: 0:acb14030fe0a
134 tag: bleah
134 tag: bleah
135 tag: bleah bleah
135 tag: bleah bleah
136 tag: bleah0
136 tag: bleah0
137 tag: bleahbleah
137 tag: bleahbleah
138 tag: foobar
138 tag: foobar
139 tag: localblah
139 tag: localblah
140 user: test
140 user: test
141 date: Thu Jan 01 00:00:00 1970 +0000
141 date: Thu Jan 01 00:00:00 1970 +0000
142 summary: test
142 summary: test
143
143
144 changeset: 1:d4f0d2909abc
144 changeset: 1:d4f0d2909abc
145 tag: bleah1
145 tag: bleah1
146 user: test
146 user: test
147 date: Thu Jan 01 00:00:00 1970 +0000
147 date: Thu Jan 01 00:00:00 1970 +0000
148 summary: Added tag bleah for changeset acb14030fe0a
148 summary: Added tag bleah for changeset acb14030fe0a
149
149
150 changeset: 2:336fccc858a4
150 changeset: 2:336fccc858a4
151 tag: gawk
151 tag: gawk
152 user: test
152 user: test
153 date: Thu Jan 01 00:00:00 1970 +0000
153 date: Thu Jan 01 00:00:00 1970 +0000
154 summary: Added tag bleah0 for changeset acb14030fe0a
154 summary: Added tag bleah0 for changeset acb14030fe0a
155
155
156 changeset: 3:799667b6f2d9
156 changeset: 3:799667b6f2d9
157 user: test
157 user: test
158 date: Thu Jan 01 00:00:00 1970 +0000
158 date: Thu Jan 01 00:00:00 1970 +0000
159 summary: Added tag gack, gawk, gorp for changeset 336fccc858a4
159 summary: Added tag gack, gawk, gorp for changeset 336fccc858a4
160
160
161 changeset: 4:154eeb7c0138
161 changeset: 4:154eeb7c0138
162 user: test
162 user: test
163 date: Thu Jan 01 00:00:00 1970 +0000
163 date: Thu Jan 01 00:00:00 1970 +0000
164 summary: Added tag gack for changeset 799667b6f2d9
164 summary: Added tag gack for changeset 799667b6f2d9
165
165
166 changeset: 5:b4bb47aaff09
166 changeset: 5:b4bb47aaff09
167 user: test
167 user: test
168 date: Thu Jan 01 00:00:00 1970 +0000
168 date: Thu Jan 01 00:00:00 1970 +0000
169 summary: Removed tag gack, gorp
169 summary: Removed tag gack, gorp
170
170
171 $ hg clone -q -rbleah1 test test1
171 $ hg clone -q -rbleah1 test test1
172 $ hg -R test1 parents --style=compact
172 $ hg -R test1 parents --style=compact
173 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test
173 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test
174 Added tag bleah for changeset acb14030fe0a
174 Added tag bleah for changeset acb14030fe0a
175
175
176 $ hg clone -q -r5 test#bleah1 test2
176 $ hg clone -q -r5 test#bleah1 test2
177 $ hg -R test2 parents --style=compact
177 $ hg -R test2 parents --style=compact
178 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test
178 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test
179 Removed tag gack, gorp
179 Removed tag gack, gorp
180
180
181 $ hg clone -q -U test#bleah1 test3
181 $ hg clone -q -U test#bleah1 test3
182 $ hg -R test3 parents --style=compact
182 $ hg -R test3 parents --style=compact
183
183
184 $ cd test
184 $ cd test
185
185
186 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
186 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
187 doesn't end with EOL
187 doesn't end with EOL
188
188
189 $ python << EOF
189 $ python << EOF
190 > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
190 > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
191 > f = file('.hg/localtags', 'w'); f.write(last); f.close()
191 > f = file('.hg/localtags', 'w'); f.write(last); f.close()
192 > EOF
192 > EOF
193 $ cat .hg/localtags; echo
193 $ cat .hg/localtags; echo
194 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
194 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
195 $ hg tag -l localnewline
195 $ hg tag -l localnewline
196 $ cat .hg/localtags; echo
196 $ cat .hg/localtags; echo
197 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
197 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
198 c2899151f4e76890c602a2597a650a72666681bf localnewline
198 c2899151f4e76890c602a2597a650a72666681bf localnewline
199
199
200
200
201 $ python << EOF
201 $ python << EOF
202 > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
202 > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
203 > f = file('.hgtags', 'w'); f.write(last); f.close()
203 > f = file('.hgtags', 'w'); f.write(last); f.close()
204 > EOF
204 > EOF
205 $ hg ci -m'broken manual edit of .hgtags'
205 $ hg ci -m'broken manual edit of .hgtags'
206 $ cat .hgtags; echo
206 $ cat .hgtags; echo
207 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
207 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
208 $ hg tag newline
208 $ hg tag newline
209 $ cat .hgtags; echo
209 $ cat .hgtags; echo
210 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
210 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
211 a0eea09de1eeec777b46f2085260a373b2fbc293 newline
211 a0eea09de1eeec777b46f2085260a373b2fbc293 newline
212
212
213
213
214 tag and branch using same name
214 tag and branch using same name
215
215
216 $ hg branch tag-and-branch-same-name
216 $ hg branch tag-and-branch-same-name
217 marked working directory as branch tag-and-branch-same-name
217 marked working directory as branch tag-and-branch-same-name
218 (branches are permanent and global, did you want a bookmark?)
218 (branches are permanent and global, did you want a bookmark?)
219 $ hg ci -m"discouraged"
219 $ hg ci -m"discouraged"
220 $ hg tag tag-and-branch-same-name
220 $ hg tag tag-and-branch-same-name
221 warning: tag tag-and-branch-same-name conflicts with existing branch name
221 warning: tag tag-and-branch-same-name conflicts with existing branch name
222
222
223 test custom commit messages
223 test custom commit messages
224
224
225 $ cat > editor.sh << '__EOF__'
225 $ cat > editor.sh << '__EOF__'
226 > echo "==== before editing"
226 > echo "==== before editing"
227 > cat "$1"
227 > cat "$1"
228 > echo "===="
228 > echo "===="
229 > echo "custom tag message" > "$1"
229 > echo "custom tag message" > "$1"
230 > echo "second line" >> "$1"
230 > echo "second line" >> "$1"
231 > __EOF__
231 > __EOF__
232
232
233 at first, test saving last-message.txt
233 at first, test saving last-message.txt
234
234
235 (test that editor is not invoked before transaction starting)
235 (test that editor is not invoked before transaction starting)
236
236
237 $ cat > .hg/hgrc << '__EOF__'
237 $ cat > .hg/hgrc << '__EOF__'
238 > [hooks]
238 > [hooks]
239 > # this failure occurs before editor invocation
239 > # this failure occurs before editor invocation
240 > pretag.test-saving-lastmessage = false
240 > pretag.test-saving-lastmessage = false
241 > __EOF__
241 > __EOF__
242 $ rm -f .hg/last-message.txt
242 $ rm -f .hg/last-message.txt
243 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e
243 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e
244 abort: pretag.test-saving-lastmessage hook exited with status 1
244 abort: pretag.test-saving-lastmessage hook exited with status 1
245 [255]
245 [255]
246 $ test -f .hg/last-message.txt
246 $ test -f .hg/last-message.txt
247 [1]
247 [1]
248
248
249 (test that editor is invoked and commit message is saved into
249 (test that editor is invoked and commit message is saved into
250 "last-message.txt")
250 "last-message.txt")
251
251
252 $ cat >> .hg/hgrc << '__EOF__'
252 $ cat >> .hg/hgrc << '__EOF__'
253 > [hooks]
253 > [hooks]
254 > pretag.test-saving-lastmessage =
254 > pretag.test-saving-lastmessage =
255 > # this failure occurs after editor invocation
255 > # this failure occurs after editor invocation
256 > pretxncommit.unexpectedabort = false
256 > pretxncommit.unexpectedabort = false
257 > __EOF__
257 > __EOF__
258
258
259 (this tests also that editor is invoked, if '--edit' is specified,
259 (this tests also that editor is invoked, if '--edit' is specified,
260 regardless of '--message')
260 regardless of '--message')
261
261
262 $ rm -f .hg/last-message.txt
262 $ rm -f .hg/last-message.txt
263 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e -m "foo bar"
263 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e -m "foo bar"
264 ==== before editing
264 ==== before editing
265 foo bar
265 foo bar
266
266
267
267
268 HG: Enter commit message. Lines beginning with 'HG:' are removed.
268 HG: Enter commit message. Lines beginning with 'HG:' are removed.
269 HG: Leave message empty to abort commit.
269 HG: Leave message empty to abort commit.
270 HG: --
270 HG: --
271 HG: user: test
271 HG: user: test
272 HG: branch 'tag-and-branch-same-name'
272 HG: branch 'tag-and-branch-same-name'
273 HG: changed .hgtags
273 HG: changed .hgtags
274 ====
274 ====
275 transaction abort!
275 transaction abort!
276 rollback completed
276 rollback completed
277 note: commit message saved in .hg/last-message.txt
277 note: commit message saved in .hg/last-message.txt
278 abort: pretxncommit.unexpectedabort hook exited with status 1
278 abort: pretxncommit.unexpectedabort hook exited with status 1
279 [255]
279 [255]
280 $ cat .hg/last-message.txt
280 $ cat .hg/last-message.txt
281 custom tag message
281 custom tag message
282 second line
282 second line
283
283
284 $ cat >> .hg/hgrc << '__EOF__'
284 $ cat >> .hg/hgrc << '__EOF__'
285 > [hooks]
285 > [hooks]
286 > pretxncommit.unexpectedabort =
286 > pretxncommit.unexpectedabort =
287 > __EOF__
287 > __EOF__
288 $ hg status .hgtags
288 $ hg status .hgtags
289 M .hgtags
289 M .hgtags
290 $ hg revert --no-backup -q .hgtags
290 $ hg revert --no-backup -q .hgtags
291
291
292 then, test custom commit message itself
292 then, test custom commit message itself
293
293
294 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e
294 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e
295 ==== before editing
295 ==== before editing
296 Added tag custom-tag for changeset 75a534207be6
296 Added tag custom-tag for changeset 75a534207be6
297
297
298
298
299 HG: Enter commit message. Lines beginning with 'HG:' are removed.
299 HG: Enter commit message. Lines beginning with 'HG:' are removed.
300 HG: Leave message empty to abort commit.
300 HG: Leave message empty to abort commit.
301 HG: --
301 HG: --
302 HG: user: test
302 HG: user: test
303 HG: branch 'tag-and-branch-same-name'
303 HG: branch 'tag-and-branch-same-name'
304 HG: changed .hgtags
304 HG: changed .hgtags
305 ====
305 ====
306 $ hg log -l1 --template "{desc}\n"
306 $ hg log -l1 --template "{desc}\n"
307 custom tag message
307 custom tag message
308 second line
308 second line
309
309
310
310
311 local tag with .hgtags modified
311 local tag with .hgtags modified
312
312
313 $ hg tag hgtags-modified
313 $ hg tag hgtags-modified
314 $ hg rollback
314 $ hg rollback
315 repository tip rolled back to revision 13 (undo commit)
315 repository tip rolled back to revision 13 (undo commit)
316 working directory now based on revision 13
316 working directory now based on revision 13
317 $ hg st
317 $ hg st
318 M .hgtags
318 M .hgtags
319 ? .hgtags.orig
319 ? .hgtags.orig
320 ? editor.sh
320 ? editor.sh
321 $ hg tag --local baz
321 $ hg tag --local baz
322 $ hg revert --no-backup .hgtags
322 $ hg revert --no-backup .hgtags
323
323
324
324
325 tagging when at named-branch-head that's not a topo-head
325 tagging when at named-branch-head that's not a topo-head
326
326
327 $ hg up default
327 $ hg up default
328 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
328 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 $ hg merge -t internal:local
329 $ hg merge -t internal:local
330 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
330 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
331 (branch merge, don't forget to commit)
331 (branch merge, don't forget to commit)
332 $ hg ci -m 'merge named branch'
332 $ hg ci -m 'merge named branch'
333 $ hg up 13
333 $ hg up 13
334 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 $ hg tag new-topo-head
335 $ hg tag new-topo-head
336
336
337 tagging on null rev
337 tagging on null rev
338
338
339 $ hg up null
339 $ hg up null
340 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
340 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
341 $ hg tag nullrev
341 $ hg tag nullrev
342 abort: not at a branch head (use -f to force)
342 abort: not at a branch head (use -f to force)
343 [255]
343 [255]
344
344
345 $ hg init empty
345 $ hg init empty
346 $ hg tag -R empty nullrev
346 $ hg tag -R empty nullrev
347 abort: cannot tag null revision
347 abort: cannot tag null revision
348 [255]
348 [255]
349
349
350 $ hg tag -R empty -r 00000000000 -f nulltag
350 $ hg tag -R empty -r 00000000000 -f nulltag
351 abort: cannot tag null revision
351 abort: cannot tag null revision
352 [255]
352 [255]
353
353
354 $ cd ..
354 $ cd ..
355
355
356 tagging on an uncommitted merge (issue2542)
356 tagging on an uncommitted merge (issue2542)
357
357
358 $ hg init repo-tag-uncommitted-merge
358 $ hg init repo-tag-uncommitted-merge
359 $ cd repo-tag-uncommitted-merge
359 $ cd repo-tag-uncommitted-merge
360 $ echo c1 > f1
360 $ echo c1 > f1
361 $ hg ci -Am0
361 $ hg ci -Am0
362 adding f1
362 adding f1
363 $ echo c2 > f2
363 $ echo c2 > f2
364 $ hg ci -Am1
364 $ hg ci -Am1
365 adding f2
365 adding f2
366 $ hg co -q 0
366 $ hg co -q 0
367 $ hg branch b1
367 $ hg branch b1
368 marked working directory as branch b1
368 marked working directory as branch b1
369 (branches are permanent and global, did you want a bookmark?)
369 (branches are permanent and global, did you want a bookmark?)
370 $ hg ci -m2
370 $ hg ci -m2
371 $ hg up default
371 $ hg up default
372 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
372 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
373 $ hg merge b1
373 $ hg merge b1
374 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 (branch merge, don't forget to commit)
375 (branch merge, don't forget to commit)
376
376
377 $ hg tag t1
377 $ hg tag t1
378 abort: uncommitted merge
378 abort: uncommitted merge
379 [255]
379 [255]
380 $ hg status
380 $ hg status
381 $ hg tag --rev 1 t2
381 $ hg tag --rev 1 t2
382 abort: uncommitted merge
382 abort: uncommitted merge
383 [255]
383 [255]
384 $ hg tag --rev 1 --local t3
384 $ hg tag --rev 1 --local t3
385 $ hg tags -v
385 $ hg tags -v
386 tip 2:2a156e8887cc
386 tip 2:2a156e8887cc
387 t3 1:c3adabd1a5f4 local
387 t3 1:c3adabd1a5f4 local
388
388
389 $ cd ..
389 $ cd ..
390
390
391 commit hook on tag used to be run without write lock - issue3344
391 commit hook on tag used to be run without write lock - issue3344
392
392
393 $ hg init repo-tag
393 $ hg init repo-tag
394 $ touch repo-tag/test
394 $ touch repo-tag/test
395 $ hg -R repo-tag commit -A -m "test"
395 $ hg -R repo-tag commit -A -m "test"
396 adding test
396 adding test
397 $ hg init repo-tag-target
397 $ hg init repo-tag-target
398 $ hg -R repo-tag --config hooks.commit="\"hg\" push \"`pwd`/repo-tag-target\"" tag tag
398 $ hg -R repo-tag --config hooks.commit="\"hg\" push \"`pwd`/repo-tag-target\"" tag tag
399 pushing to $TESTTMP/repo-tag-target (glob)
399 pushing to $TESTTMP/repo-tag-target (glob)
400 searching for changes
400 searching for changes
401 adding changesets
401 adding changesets
402 adding manifests
402 adding manifests
403 adding file changes
403 adding file changes
404 added 2 changesets with 2 changes to 2 files
404 added 2 changesets with 2 changes to 2 files
405
405
406 automatically merge resolvable tag conflicts (i.e. tags that differ in rank)
406 automatically merge resolvable tag conflicts (i.e. tags that differ in rank)
407 create two clones with some different tags as well as some common tags
407 create two clones with some different tags as well as some common tags
408 check that we can merge tags that differ in rank
408 check that we can merge tags that differ in rank
409
409
410 $ hg init repo-automatic-tag-merge
410 $ hg init repo-automatic-tag-merge
411 $ cd repo-automatic-tag-merge
411 $ cd repo-automatic-tag-merge
412 $ echo c0 > f0
412 $ echo c0 > f0
413 $ hg ci -A -m0
413 $ hg ci -A -m0
414 adding f0
414 adding f0
415 $ hg tag tbase
415 $ hg tag tbase
416 $ cd ..
416 $ cd ..
417 $ hg clone repo-automatic-tag-merge repo-automatic-tag-merge-clone
417 $ hg clone repo-automatic-tag-merge repo-automatic-tag-merge-clone
418 updating to branch default
418 updating to branch default
419 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
419 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
420 $ cd repo-automatic-tag-merge-clone
420 $ cd repo-automatic-tag-merge-clone
421 $ echo c1 > f1
421 $ echo c1 > f1
422 $ hg ci -A -m1
422 $ hg ci -A -m1
423 adding f1
423 adding f1
424 $ hg tag t1 t2 t3
424 $ hg tag t1 t2 t3
425 $ hg tag --remove t2
425 $ hg tag --remove t2
426 $ hg tag t5
426 $ hg tag t5
427 $ echo c2 > f2
427 $ echo c2 > f2
428 $ hg ci -A -m2
428 $ hg ci -A -m2
429 adding f2
429 adding f2
430 $ hg tag -f t3
430 $ hg tag -f t3
431
431
432 $ cd ../repo-automatic-tag-merge
432 $ cd ../repo-automatic-tag-merge
433 $ echo c3 > f3
433 $ echo c3 > f3
434 $ hg ci -A -m3
434 $ hg ci -A -m3
435 adding f3
435 adding f3
436 $ hg tag -f t4 t5 t6
436 $ hg tag -f t4 t5 t6
437 $ hg tag --remove t5
437 $ hg tag --remove t5
438 $ echo c4 > f4
438 $ echo c4 > f4
439 $ hg ci -A -m4
439 $ hg ci -A -m4
440 adding f4
440 adding f4
441 $ hg tag t2
441 $ hg tag t2
442 $ hg tag -f t6
442 $ hg tag -f t6
443
443
444 $ cd ../repo-automatic-tag-merge-clone
444 $ cd ../repo-automatic-tag-merge-clone
445 $ hg pull
445 $ hg pull
446 pulling from $TESTTMP/repo-automatic-tag-merge (glob)
446 pulling from $TESTTMP/repo-automatic-tag-merge (glob)
447 searching for changes
447 searching for changes
448 adding changesets
448 adding changesets
449 adding manifests
449 adding manifests
450 adding file changes
450 adding file changes
451 added 6 changesets with 6 changes to 3 files (+1 heads)
451 added 6 changesets with 6 changes to 3 files (+1 heads)
452 (run 'hg heads' to see heads, 'hg merge' to merge)
452 (run 'hg heads' to see heads, 'hg merge' to merge)
453 $ hg merge --tool internal:tagmerge
453 $ hg merge --tool internal:tagmerge
454 merging .hgtags
454 merging .hgtags
455 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
455 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
456 (branch merge, don't forget to commit)
456 (branch merge, don't forget to commit)
457 $ hg status
457 $ hg status
458 M .hgtags
458 M .hgtags
459 M f3
459 M f3
460 M f4
460 M f4
461 $ hg resolve -l
461 $ hg resolve -l
462 R .hgtags
462 R .hgtags
463 $ cat .hgtags
463 $ cat .hgtags
464 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
464 9aa4e1292a27a248f8d07339bed9931d54907be7 t4
465 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
465 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
466 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
466 9aa4e1292a27a248f8d07339bed9931d54907be7 t6
467 09af2ce14077a94effef208b49a718f4836d4338 t6
467 09af2ce14077a94effef208b49a718f4836d4338 t6
468 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
468 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
469 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
469 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
470 929bca7b18d067cbf3844c3896319a940059d748 t2
470 929bca7b18d067cbf3844c3896319a940059d748 t2
471 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
471 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
472 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
472 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
473 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
473 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
474 0000000000000000000000000000000000000000 t2
474 0000000000000000000000000000000000000000 t2
475 875517b4806a848f942811a315a5bce30804ae85 t5
475 875517b4806a848f942811a315a5bce30804ae85 t5
476 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
476 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
477 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
477 9aa4e1292a27a248f8d07339bed9931d54907be7 t5
478 0000000000000000000000000000000000000000 t5
478 0000000000000000000000000000000000000000 t5
479 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
479 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
480 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
480 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
481
481
482 check that the merge tried to minimize the diff witht he first merge parent
482 check that the merge tried to minimize the diff witht he first merge parent
483
483
484 $ hg diff --git -r 'p1()' .hgtags
484 $ hg diff --git -r 'p1()' .hgtags
485 diff --git a/.hgtags b/.hgtags
485 diff --git a/.hgtags b/.hgtags
486 --- a/.hgtags
486 --- a/.hgtags
487 +++ b/.hgtags
487 +++ b/.hgtags
488 @@ -1,9 +1,17 @@
488 @@ -1,9 +1,17 @@
489 +9aa4e1292a27a248f8d07339bed9931d54907be7 t4
489 +9aa4e1292a27a248f8d07339bed9931d54907be7 t4
490 +9aa4e1292a27a248f8d07339bed9931d54907be7 t6
490 +9aa4e1292a27a248f8d07339bed9931d54907be7 t6
491 +9aa4e1292a27a248f8d07339bed9931d54907be7 t6
491 +9aa4e1292a27a248f8d07339bed9931d54907be7 t6
492 +09af2ce14077a94effef208b49a718f4836d4338 t6
492 +09af2ce14077a94effef208b49a718f4836d4338 t6
493 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
493 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
494 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
494 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
495 +929bca7b18d067cbf3844c3896319a940059d748 t2
495 +929bca7b18d067cbf3844c3896319a940059d748 t2
496 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
496 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
497 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
497 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
498 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
498 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
499 0000000000000000000000000000000000000000 t2
499 0000000000000000000000000000000000000000 t2
500 875517b4806a848f942811a315a5bce30804ae85 t5
500 875517b4806a848f942811a315a5bce30804ae85 t5
501 +9aa4e1292a27a248f8d07339bed9931d54907be7 t5
501 +9aa4e1292a27a248f8d07339bed9931d54907be7 t5
502 +9aa4e1292a27a248f8d07339bed9931d54907be7 t5
502 +9aa4e1292a27a248f8d07339bed9931d54907be7 t5
503 +0000000000000000000000000000000000000000 t5
503 +0000000000000000000000000000000000000000 t5
504 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
504 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
505 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
505 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
506
506
507 detect merge tag conflicts
507 detect merge tag conflicts
508
508
509 $ hg update -C -r tip
509 $ hg update -C -r tip
510 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
510 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
511 $ hg tag t7
511 $ hg tag t7
512 $ hg update -C -r 'first(sort(head()))'
512 $ hg update -C -r 'first(sort(head()))'
513 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
513 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
514 $ printf "%s %s\n" `hg log -r . --template "{node} t7"` >> .hgtags
514 $ printf "%s %s\n" `hg log -r . --template "{node} t7"` >> .hgtags
515 $ hg commit -m "manually add conflicting t7 tag"
515 $ hg commit -m "manually add conflicting t7 tag"
516 $ hg merge --tool internal:tagmerge
516 $ hg merge --tool internal:tagmerge
517 merging .hgtags
517 merging .hgtags
518 automatic .hgtags merge failed
518 automatic .hgtags merge failed
519 the following 1 tags are in conflict: t7
519 the following 1 tags are in conflict: t7
520 automatic tag merging of .hgtags failed! (use 'hg resolve --tool internal:merge' or another merge tool of your choice)
520 automatic tag merging of .hgtags failed! (use 'hg resolve --tool :merge' or another merge tool of your choice)
521 2 files updated, 0 files merged, 0 files removed, 1 files unresolved
521 2 files updated, 0 files merged, 0 files removed, 1 files unresolved
522 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
522 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
523 [1]
523 [1]
524 $ hg resolve -l
524 $ hg resolve -l
525 U .hgtags
525 U .hgtags
526 $ cat .hgtags
526 $ cat .hgtags
527 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
527 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
528 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
528 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
529 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
529 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
530 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
530 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
531 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
531 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
532 0000000000000000000000000000000000000000 t2
532 0000000000000000000000000000000000000000 t2
533 875517b4806a848f942811a315a5bce30804ae85 t5
533 875517b4806a848f942811a315a5bce30804ae85 t5
534 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
534 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
535 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
535 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
536 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
536 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
537
537
538 $ cd ..
538 $ cd ..
539
539
540 handle the loss of tags
540 handle the loss of tags
541
541
542 $ hg clone repo-automatic-tag-merge-clone repo-merge-lost-tags
542 $ hg clone repo-automatic-tag-merge-clone repo-merge-lost-tags
543 updating to branch default
543 updating to branch default
544 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
544 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 $ cd repo-merge-lost-tags
545 $ cd repo-merge-lost-tags
546 $ echo c5 > f5
546 $ echo c5 > f5
547 $ hg ci -A -m5
547 $ hg ci -A -m5
548 adding f5
548 adding f5
549 $ hg tag -f t7
549 $ hg tag -f t7
550 $ hg update -r 'p1(t7)'
550 $ hg update -r 'p1(t7)'
551 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
551 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
552 $ printf '' > .hgtags
552 $ printf '' > .hgtags
553 $ hg commit -m 'delete all tags'
553 $ hg commit -m 'delete all tags'
554 created new head
554 created new head
555 $ hg update -r 'max(t7::)'
555 $ hg update -r 'max(t7::)'
556 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 $ hg merge -r tip --tool internal:tagmerge
557 $ hg merge -r tip --tool internal:tagmerge
558 merging .hgtags
558 merging .hgtags
559 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
559 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
560 (branch merge, don't forget to commit)
560 (branch merge, don't forget to commit)
561 $ hg resolve -l
561 $ hg resolve -l
562 R .hgtags
562 R .hgtags
563 $ cat .hgtags
563 $ cat .hgtags
564 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
564 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
565 0000000000000000000000000000000000000000 tbase
565 0000000000000000000000000000000000000000 tbase
566 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
566 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
567 0000000000000000000000000000000000000000 t1
567 0000000000000000000000000000000000000000 t1
568 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
568 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
569 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
569 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
570 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
570 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
571 0000000000000000000000000000000000000000 t2
571 0000000000000000000000000000000000000000 t2
572 875517b4806a848f942811a315a5bce30804ae85 t5
572 875517b4806a848f942811a315a5bce30804ae85 t5
573 0000000000000000000000000000000000000000 t5
573 0000000000000000000000000000000000000000 t5
574 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
574 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
575 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
575 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
576 0000000000000000000000000000000000000000 t3
576 0000000000000000000000000000000000000000 t3
577 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
577 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
578 0000000000000000000000000000000000000000 t7
578 0000000000000000000000000000000000000000 t7
579 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
579 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
580 fd3a9e394ce3afb354a496323bf68ac1755a30de t7
580 fd3a9e394ce3afb354a496323bf68ac1755a30de t7
581
581
582 also check that we minimize the diff with the 1st merge parent
582 also check that we minimize the diff with the 1st merge parent
583
583
584 $ hg diff --git -r 'p1()' .hgtags
584 $ hg diff --git -r 'p1()' .hgtags
585 diff --git a/.hgtags b/.hgtags
585 diff --git a/.hgtags b/.hgtags
586 --- a/.hgtags
586 --- a/.hgtags
587 +++ b/.hgtags
587 +++ b/.hgtags
588 @@ -1,12 +1,17 @@
588 @@ -1,12 +1,17 @@
589 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
589 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase
590 +0000000000000000000000000000000000000000 tbase
590 +0000000000000000000000000000000000000000 tbase
591 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
591 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1
592 +0000000000000000000000000000000000000000 t1
592 +0000000000000000000000000000000000000000 t1
593 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
593 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
594 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
594 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
595 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
595 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2
596 0000000000000000000000000000000000000000 t2
596 0000000000000000000000000000000000000000 t2
597 875517b4806a848f942811a315a5bce30804ae85 t5
597 875517b4806a848f942811a315a5bce30804ae85 t5
598 +0000000000000000000000000000000000000000 t5
598 +0000000000000000000000000000000000000000 t5
599 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
599 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3
600 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
600 79505d5360b07e3e79d1052e347e73c02b8afa5b t3
601 +0000000000000000000000000000000000000000 t3
601 +0000000000000000000000000000000000000000 t3
602 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
602 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
603 +0000000000000000000000000000000000000000 t7
603 +0000000000000000000000000000000000000000 t7
604 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
604 ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7
605 fd3a9e394ce3afb354a496323bf68ac1755a30de t7
605 fd3a9e394ce3afb354a496323bf68ac1755a30de t7
606
606
General Comments 0
You need to be logged in to leave comments. Login now