##// END OF EJS Templates
branching: merge stable into default
Raphaël Gomès -
r49827:4057563e merge default
parent child Browse files
Show More
@@ -1,1232 +1,1231 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 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2006, 2007, 2008 Olivia Mackall <olivia@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
8
9 import contextlib
9 import contextlib
10 import os
10 import os
11 import re
11 import re
12 import shutil
12 import shutil
13
13
14 from .i18n import _
14 from .i18n import _
15 from .node import (
15 from .node import (
16 hex,
16 hex,
17 short,
17 short,
18 )
18 )
19 from .pycompat import (
19 from .pycompat import (
20 getattr,
20 getattr,
21 )
21 )
22
22
23 from . import (
23 from . import (
24 encoding,
24 encoding,
25 error,
25 error,
26 formatter,
26 formatter,
27 match,
27 match,
28 pycompat,
28 pycompat,
29 registrar,
29 registrar,
30 scmutil,
30 scmutil,
31 simplemerge,
31 simplemerge,
32 tagmerge,
32 tagmerge,
33 templatekw,
33 templatekw,
34 templater,
34 templater,
35 templateutil,
35 templateutil,
36 util,
36 util,
37 )
37 )
38
38
39 from .utils import (
39 from .utils import (
40 procutil,
40 procutil,
41 stringutil,
41 stringutil,
42 )
42 )
43
43
44
44
45 def _toolstr(ui, tool, part, *args):
45 def _toolstr(ui, tool, part, *args):
46 return ui.config(b"merge-tools", tool + b"." + part, *args)
46 return ui.config(b"merge-tools", tool + b"." + part, *args)
47
47
48
48
49 def _toolbool(ui, tool, part, *args):
49 def _toolbool(ui, tool, part, *args):
50 return ui.configbool(b"merge-tools", tool + b"." + part, *args)
50 return ui.configbool(b"merge-tools", tool + b"." + part, *args)
51
51
52
52
53 def _toollist(ui, tool, part):
53 def _toollist(ui, tool, part):
54 return ui.configlist(b"merge-tools", tool + b"." + part)
54 return ui.configlist(b"merge-tools", tool + b"." + part)
55
55
56
56
57 internals = {}
57 internals = {}
58 # Merge tools to document.
58 # Merge tools to document.
59 internalsdoc = {}
59 internalsdoc = {}
60
60
61 internaltool = registrar.internalmerge()
61 internaltool = registrar.internalmerge()
62
62
63 # internal tool merge types
63 # internal tool merge types
64 nomerge = internaltool.nomerge
64 nomerge = internaltool.nomerge
65 mergeonly = internaltool.mergeonly # just the full merge, no premerge
65 mergeonly = internaltool.mergeonly # just the full merge, no premerge
66 fullmerge = internaltool.fullmerge # both premerge and merge
66 fullmerge = internaltool.fullmerge # both premerge and merge
67
67
68 # IMPORTANT: keep the last line of this prompt very short ("What do you want to
68 # IMPORTANT: keep the last line of this prompt very short ("What do you want to
69 # do?") because of issue6158, ideally to <40 English characters (to allow other
69 # do?") because of issue6158, ideally to <40 English characters (to allow other
70 # languages that may take more columns to still have a chance to fit in an
70 # languages that may take more columns to still have a chance to fit in an
71 # 80-column screen).
71 # 80-column screen).
72 _localchangedotherdeletedmsg = _(
72 _localchangedotherdeletedmsg = _(
73 b"file '%(fd)s' was deleted in other%(o)s but was modified in local%(l)s.\n"
73 b"file '%(fd)s' was deleted in other%(o)s but was modified in local%(l)s.\n"
74 b"You can use (c)hanged version, (d)elete, or leave (u)nresolved.\n"
74 b"You can use (c)hanged version, (d)elete, or leave (u)nresolved.\n"
75 b"What do you want to do?"
75 b"What do you want to do?"
76 b"$$ &Changed $$ &Delete $$ &Unresolved"
76 b"$$ &Changed $$ &Delete $$ &Unresolved"
77 )
77 )
78
78
79 _otherchangedlocaldeletedmsg = _(
79 _otherchangedlocaldeletedmsg = _(
80 b"file '%(fd)s' was deleted in local%(l)s but was modified in other%(o)s.\n"
80 b"file '%(fd)s' was deleted in local%(l)s but was modified in other%(o)s.\n"
81 b"You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.\n"
81 b"You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.\n"
82 b"What do you want to do?"
82 b"What do you want to do?"
83 b"$$ &Changed $$ &Deleted $$ &Unresolved"
83 b"$$ &Changed $$ &Deleted $$ &Unresolved"
84 )
84 )
85
85
86
86
87 class absentfilectx:
87 class absentfilectx:
88 """Represents a file that's ostensibly in a context but is actually not
88 """Represents a file that's ostensibly in a context but is actually not
89 present in it.
89 present in it.
90
90
91 This is here because it's very specific to the filemerge code for now --
91 This is here because it's very specific to the filemerge code for now --
92 other code is likely going to break with the values this returns."""
92 other code is likely going to break with the values this returns."""
93
93
94 def __init__(self, ctx, f):
94 def __init__(self, ctx, f):
95 self._ctx = ctx
95 self._ctx = ctx
96 self._f = f
96 self._f = f
97
97
98 def __bytes__(self):
98 def __bytes__(self):
99 return b'absent file %s@%s' % (self._f, self._ctx)
99 return b'absent file %s@%s' % (self._f, self._ctx)
100
100
101 def path(self):
101 def path(self):
102 return self._f
102 return self._f
103
103
104 def size(self):
104 def size(self):
105 return None
105 return None
106
106
107 def data(self):
107 def data(self):
108 return None
108 return None
109
109
110 def filenode(self):
110 def filenode(self):
111 return self._ctx.repo().nullid
111 return self._ctx.repo().nullid
112
112
113 _customcmp = True
113 _customcmp = True
114
114
115 def cmp(self, fctx):
115 def cmp(self, fctx):
116 """compare with other file context
116 """compare with other file context
117
117
118 returns True if different from fctx.
118 returns True if different from fctx.
119 """
119 """
120 return not (
120 return not (
121 fctx.isabsent()
121 fctx.isabsent()
122 and fctx.changectx() == self.changectx()
122 and fctx.changectx() == self.changectx()
123 and fctx.path() == self.path()
123 and fctx.path() == self.path()
124 )
124 )
125
125
126 def flags(self):
126 def flags(self):
127 return b''
127 return b''
128
128
129 def changectx(self):
129 def changectx(self):
130 return self._ctx
130 return self._ctx
131
131
132 def isbinary(self):
132 def isbinary(self):
133 return False
133 return False
134
134
135 def isabsent(self):
135 def isabsent(self):
136 return True
136 return True
137
137
138
138
139 def _findtool(ui, tool):
139 def _findtool(ui, tool):
140 if tool in internals:
140 if tool in internals:
141 return tool
141 return tool
142 cmd = _toolstr(ui, tool, b"executable", tool)
142 cmd = _toolstr(ui, tool, b"executable", tool)
143 if cmd.startswith(b'python:'):
143 if cmd.startswith(b'python:'):
144 return cmd
144 return cmd
145 return findexternaltool(ui, tool)
145 return findexternaltool(ui, tool)
146
146
147
147
148 def _quotetoolpath(cmd):
148 def _quotetoolpath(cmd):
149 if cmd.startswith(b'python:'):
149 if cmd.startswith(b'python:'):
150 return cmd
150 return cmd
151 return procutil.shellquote(cmd)
151 return procutil.shellquote(cmd)
152
152
153
153
154 def findexternaltool(ui, tool):
154 def findexternaltool(ui, tool):
155 for kn in (b"regkey", b"regkeyalt"):
155 for kn in (b"regkey", b"regkeyalt"):
156 k = _toolstr(ui, tool, kn)
156 k = _toolstr(ui, tool, kn)
157 if not k:
157 if not k:
158 continue
158 continue
159 p = util.lookupreg(k, _toolstr(ui, tool, b"regname"))
159 p = util.lookupreg(k, _toolstr(ui, tool, b"regname"))
160 if p:
160 if p:
161 p = procutil.findexe(p + _toolstr(ui, tool, b"regappend", b""))
161 p = procutil.findexe(p + _toolstr(ui, tool, b"regappend", b""))
162 if p:
162 if p:
163 return p
163 return p
164 exe = _toolstr(ui, tool, b"executable", tool)
164 exe = _toolstr(ui, tool, b"executable", tool)
165 return procutil.findexe(util.expandpath(exe))
165 return procutil.findexe(util.expandpath(exe))
166
166
167
167
168 def _picktool(repo, ui, path, binary, symlink, changedelete):
168 def _picktool(repo, ui, path, binary, symlink, changedelete):
169 strictcheck = ui.configbool(b'merge', b'strict-capability-check')
169 strictcheck = ui.configbool(b'merge', b'strict-capability-check')
170
170
171 def hascapability(tool, capability, strict=False):
171 def hascapability(tool, capability, strict=False):
172 if tool in internals:
172 if tool in internals:
173 return strict and internals[tool].capabilities.get(capability)
173 return strict and internals[tool].capabilities.get(capability)
174 return _toolbool(ui, tool, capability)
174 return _toolbool(ui, tool, capability)
175
175
176 def supportscd(tool):
176 def supportscd(tool):
177 return tool in internals and internals[tool].mergetype == nomerge
177 return tool in internals and internals[tool].mergetype == nomerge
178
178
179 def check(tool, pat, symlink, binary, changedelete):
179 def check(tool, pat, symlink, binary, changedelete):
180 tmsg = tool
180 tmsg = tool
181 if pat:
181 if pat:
182 tmsg = _(b"%s (for pattern %s)") % (tool, pat)
182 tmsg = _(b"%s (for pattern %s)") % (tool, pat)
183 if not _findtool(ui, tool):
183 if not _findtool(ui, tool):
184 if pat: # explicitly requested tool deserves a warning
184 if pat: # explicitly requested tool deserves a warning
185 ui.warn(_(b"couldn't find merge tool %s\n") % tmsg)
185 ui.warn(_(b"couldn't find merge tool %s\n") % tmsg)
186 else: # configured but non-existing tools are more silent
186 else: # configured but non-existing tools are more silent
187 ui.note(_(b"couldn't find merge tool %s\n") % tmsg)
187 ui.note(_(b"couldn't find merge tool %s\n") % tmsg)
188 elif symlink and not hascapability(tool, b"symlink", strictcheck):
188 elif symlink and not hascapability(tool, b"symlink", strictcheck):
189 ui.warn(_(b"tool %s can't handle symlinks\n") % tmsg)
189 ui.warn(_(b"tool %s can't handle symlinks\n") % tmsg)
190 elif binary and not hascapability(tool, b"binary", strictcheck):
190 elif binary and not hascapability(tool, b"binary", strictcheck):
191 ui.warn(_(b"tool %s can't handle binary\n") % tmsg)
191 ui.warn(_(b"tool %s can't handle binary\n") % tmsg)
192 elif changedelete and not supportscd(tool):
192 elif changedelete and not supportscd(tool):
193 # the nomerge tools are the only tools that support change/delete
193 # the nomerge tools are the only tools that support change/delete
194 # conflicts
194 # conflicts
195 pass
195 pass
196 elif not procutil.gui() and _toolbool(ui, tool, b"gui"):
196 elif not procutil.gui() and _toolbool(ui, tool, b"gui"):
197 ui.warn(_(b"tool %s requires a GUI\n") % tmsg)
197 ui.warn(_(b"tool %s requires a GUI\n") % tmsg)
198 else:
198 else:
199 return True
199 return True
200 return False
200 return False
201
201
202 # internal config: ui.forcemerge
202 # internal config: ui.forcemerge
203 # forcemerge comes from command line arguments, highest priority
203 # forcemerge comes from command line arguments, highest priority
204 force = ui.config(b'ui', b'forcemerge')
204 force = ui.config(b'ui', b'forcemerge')
205 if force:
205 if force:
206 toolpath = _findtool(ui, force)
206 toolpath = _findtool(ui, force)
207 if changedelete and not supportscd(toolpath):
207 if changedelete and not supportscd(toolpath):
208 return b":prompt", None
208 return b":prompt", None
209 else:
209 else:
210 if toolpath:
210 if toolpath:
211 return (force, _quotetoolpath(toolpath))
211 return (force, _quotetoolpath(toolpath))
212 else:
212 else:
213 # mimic HGMERGE if given tool not found
213 # mimic HGMERGE if given tool not found
214 return (force, force)
214 return (force, force)
215
215
216 # HGMERGE takes next precedence
216 # HGMERGE takes next precedence
217 hgmerge = encoding.environ.get(b"HGMERGE")
217 hgmerge = encoding.environ.get(b"HGMERGE")
218 if hgmerge:
218 if hgmerge:
219 if changedelete and not supportscd(hgmerge):
219 if changedelete and not supportscd(hgmerge):
220 return b":prompt", None
220 return b":prompt", None
221 else:
221 else:
222 return (hgmerge, hgmerge)
222 return (hgmerge, hgmerge)
223
223
224 # then patterns
224 # then patterns
225
225
226 # whether binary capability should be checked strictly
226 # whether binary capability should be checked strictly
227 binarycap = binary and strictcheck
227 binarycap = binary and strictcheck
228
228
229 for pat, tool in ui.configitems(b"merge-patterns"):
229 for pat, tool in ui.configitems(b"merge-patterns"):
230 mf = match.match(repo.root, b'', [pat])
230 mf = match.match(repo.root, b'', [pat])
231 if mf(path) and check(tool, pat, symlink, binarycap, changedelete):
231 if mf(path) and check(tool, pat, symlink, binarycap, changedelete):
232 if binary and not hascapability(tool, b"binary", strict=True):
232 if binary and not hascapability(tool, b"binary", strict=True):
233 ui.warn(
233 ui.warn(
234 _(
234 _(
235 b"warning: check merge-patterns configurations,"
235 b"warning: check merge-patterns configurations,"
236 b" if %r for binary file %r is unintentional\n"
236 b" if %r for binary file %r is unintentional\n"
237 b"(see 'hg help merge-tools'"
237 b"(see 'hg help merge-tools'"
238 b" for binary files capability)\n"
238 b" for binary files capability)\n"
239 )
239 )
240 % (pycompat.bytestr(tool), pycompat.bytestr(path))
240 % (pycompat.bytestr(tool), pycompat.bytestr(path))
241 )
241 )
242 toolpath = _findtool(ui, tool)
242 toolpath = _findtool(ui, tool)
243 return (tool, _quotetoolpath(toolpath))
243 return (tool, _quotetoolpath(toolpath))
244
244
245 # then merge tools
245 # then merge tools
246 tools = {}
246 tools = {}
247 disabled = set()
247 disabled = set()
248 for k, v in ui.configitems(b"merge-tools"):
248 for k, v in ui.configitems(b"merge-tools"):
249 t = k.split(b'.')[0]
249 t = k.split(b'.')[0]
250 if t not in tools:
250 if t not in tools:
251 tools[t] = int(_toolstr(ui, t, b"priority"))
251 tools[t] = int(_toolstr(ui, t, b"priority"))
252 if _toolbool(ui, t, b"disabled"):
252 if _toolbool(ui, t, b"disabled"):
253 disabled.add(t)
253 disabled.add(t)
254 names = tools.keys()
254 names = tools.keys()
255 tools = sorted(
255 tools = sorted(
256 [(-p, tool) for tool, p in tools.items() if tool not in disabled]
256 [(-p, tool) for tool, p in tools.items() if tool not in disabled]
257 )
257 )
258 uimerge = ui.config(b"ui", b"merge")
258 uimerge = ui.config(b"ui", b"merge")
259 if uimerge:
259 if uimerge:
260 # external tools defined in uimerge won't be able to handle
260 # external tools defined in uimerge won't be able to handle
261 # change/delete conflicts
261 # change/delete conflicts
262 if check(uimerge, path, symlink, binary, changedelete):
262 if check(uimerge, path, symlink, binary, changedelete):
263 if uimerge not in names and not changedelete:
263 if uimerge not in names and not changedelete:
264 return (uimerge, uimerge)
264 return (uimerge, uimerge)
265 tools.insert(0, (None, uimerge)) # highest priority
265 tools.insert(0, (None, uimerge)) # highest priority
266 tools.append((None, b"hgmerge")) # the old default, if found
266 tools.append((None, b"hgmerge")) # the old default, if found
267 for p, t in tools:
267 for p, t in tools:
268 if check(t, None, symlink, binary, changedelete):
268 if check(t, None, symlink, binary, changedelete):
269 toolpath = _findtool(ui, t)
269 toolpath = _findtool(ui, t)
270 return (t, _quotetoolpath(toolpath))
270 return (t, _quotetoolpath(toolpath))
271
271
272 # internal merge or prompt as last resort
272 # internal merge or prompt as last resort
273 if symlink or binary or changedelete:
273 if symlink or binary or changedelete:
274 if not changedelete and len(tools):
274 if not changedelete and len(tools):
275 # any tool is rejected by capability for symlink or binary
275 # any tool is rejected by capability for symlink or binary
276 ui.warn(_(b"no tool found to merge %s\n") % path)
276 ui.warn(_(b"no tool found to merge %s\n") % path)
277 return b":prompt", None
277 return b":prompt", None
278 return b":merge", None
278 return b":merge", None
279
279
280
280
281 def _eoltype(data):
281 def _eoltype(data):
282 """Guess the EOL type of a file"""
282 """Guess the EOL type of a file"""
283 if b'\0' in data: # binary
283 if b'\0' in data: # binary
284 return None
284 return None
285 if b'\r\n' in data: # Windows
285 if b'\r\n' in data: # Windows
286 return b'\r\n'
286 return b'\r\n'
287 if b'\r' in data: # Old Mac
287 if b'\r' in data: # Old Mac
288 return b'\r'
288 return b'\r'
289 if b'\n' in data: # UNIX
289 if b'\n' in data: # UNIX
290 return b'\n'
290 return b'\n'
291 return None # unknown
291 return None # unknown
292
292
293
293
294 def _matcheol(file, backup):
294 def _matcheol(file, backup):
295 """Convert EOL markers in a file to match origfile"""
295 """Convert EOL markers in a file to match origfile"""
296 tostyle = _eoltype(backup.data()) # No repo.wread filters?
296 tostyle = _eoltype(backup.data()) # No repo.wread filters?
297 if tostyle:
297 if tostyle:
298 data = util.readfile(file)
298 data = util.readfile(file)
299 style = _eoltype(data)
299 style = _eoltype(data)
300 if style:
300 if style:
301 newdata = data.replace(style, tostyle)
301 newdata = data.replace(style, tostyle)
302 if newdata != data:
302 if newdata != data:
303 util.writefile(file, newdata)
303 util.writefile(file, newdata)
304
304
305
305
306 @internaltool(b'prompt', nomerge)
306 @internaltool(b'prompt', nomerge)
307 def _iprompt(repo, mynode, local, other, base, toolconf):
307 def _iprompt(repo, mynode, local, other, base, toolconf):
308 """Asks the user which of the local `p1()` or the other `p2()` version to
308 """Asks the user which of the local `p1()` or the other `p2()` version to
309 keep as the merged version."""
309 keep as the merged version."""
310 ui = repo.ui
310 ui = repo.ui
311 fd = local.fctx.path()
311 fd = local.fctx.path()
312 uipathfn = scmutil.getuipathfn(repo)
312 uipathfn = scmutil.getuipathfn(repo)
313
313
314 # Avoid prompting during an in-memory merge since it doesn't support merge
314 # Avoid prompting during an in-memory merge since it doesn't support merge
315 # conflicts.
315 # conflicts.
316 if local.fctx.changectx().isinmemory():
316 if local.fctx.changectx().isinmemory():
317 raise error.InMemoryMergeConflictsError(
317 raise error.InMemoryMergeConflictsError(
318 b'in-memory merge does not support file conflicts'
318 b'in-memory merge does not support file conflicts'
319 )
319 )
320
320
321 prompts = partextras([local.label, other.label])
321 prompts = partextras([local.label, other.label])
322 prompts[b'fd'] = uipathfn(fd)
322 prompts[b'fd'] = uipathfn(fd)
323 try:
323 try:
324 if other.fctx.isabsent():
324 if other.fctx.isabsent():
325 index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2)
325 index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2)
326 choice = [b'local', b'other', b'unresolved'][index]
326 choice = [b'local', b'other', b'unresolved'][index]
327 elif local.fctx.isabsent():
327 elif local.fctx.isabsent():
328 index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2)
328 index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2)
329 choice = [b'other', b'local', b'unresolved'][index]
329 choice = [b'other', b'local', b'unresolved'][index]
330 else:
330 else:
331 # IMPORTANT: keep the last line of this prompt ("What do you want to
331 # IMPORTANT: keep the last line of this prompt ("What do you want to
332 # do?") very short, see comment next to _localchangedotherdeletedmsg
332 # do?") very short, see comment next to _localchangedotherdeletedmsg
333 # at the top of the file for details.
333 # at the top of the file for details.
334 index = ui.promptchoice(
334 index = ui.promptchoice(
335 _(
335 _(
336 b"file '%(fd)s' needs to be resolved.\n"
336 b"file '%(fd)s' needs to be resolved.\n"
337 b"You can keep (l)ocal%(l)s, take (o)ther%(o)s, or leave "
337 b"You can keep (l)ocal%(l)s, take (o)ther%(o)s, or leave "
338 b"(u)nresolved.\n"
338 b"(u)nresolved.\n"
339 b"What do you want to do?"
339 b"What do you want to do?"
340 b"$$ &Local $$ &Other $$ &Unresolved"
340 b"$$ &Local $$ &Other $$ &Unresolved"
341 )
341 )
342 % prompts,
342 % prompts,
343 2,
343 2,
344 )
344 )
345 choice = [b'local', b'other', b'unresolved'][index]
345 choice = [b'local', b'other', b'unresolved'][index]
346
346
347 if choice == b'other':
347 if choice == b'other':
348 return _iother(repo, mynode, local, other, base, toolconf)
348 return _iother(repo, mynode, local, other, base, toolconf)
349 elif choice == b'local':
349 elif choice == b'local':
350 return _ilocal(repo, mynode, local, other, base, toolconf)
350 return _ilocal(repo, mynode, local, other, base, toolconf)
351 elif choice == b'unresolved':
351 elif choice == b'unresolved':
352 return _ifail(repo, mynode, local, other, base, toolconf)
352 return _ifail(repo, mynode, local, other, base, toolconf)
353 except error.ResponseExpected:
353 except error.ResponseExpected:
354 ui.write(b"\n")
354 ui.write(b"\n")
355 return _ifail(repo, mynode, local, other, base, toolconf)
355 return _ifail(repo, mynode, local, other, base, toolconf)
356
356
357
357
358 @internaltool(b'local', nomerge)
358 @internaltool(b'local', nomerge)
359 def _ilocal(repo, mynode, local, other, base, toolconf):
359 def _ilocal(repo, mynode, local, other, base, toolconf):
360 """Uses the local `p1()` version of files as the merged version."""
360 """Uses the local `p1()` version of files as the merged version."""
361 return 0, local.fctx.isabsent()
361 return 0, local.fctx.isabsent()
362
362
363
363
364 @internaltool(b'other', nomerge)
364 @internaltool(b'other', nomerge)
365 def _iother(repo, mynode, local, other, base, toolconf):
365 def _iother(repo, mynode, local, other, base, toolconf):
366 """Uses the other `p2()` version of files as the merged version."""
366 """Uses the other `p2()` version of files as the merged version."""
367 if other.fctx.isabsent():
367 if other.fctx.isabsent():
368 # local changed, remote deleted -- 'deleted' picked
368 # local changed, remote deleted -- 'deleted' picked
369 _underlyingfctxifabsent(local.fctx).remove()
369 _underlyingfctxifabsent(local.fctx).remove()
370 deleted = True
370 deleted = True
371 else:
371 else:
372 _underlyingfctxifabsent(local.fctx).write(
372 _underlyingfctxifabsent(local.fctx).write(
373 other.fctx.data(), other.fctx.flags()
373 other.fctx.data(), other.fctx.flags()
374 )
374 )
375 deleted = False
375 deleted = False
376 return 0, deleted
376 return 0, deleted
377
377
378
378
379 @internaltool(b'fail', nomerge)
379 @internaltool(b'fail', nomerge)
380 def _ifail(repo, mynode, local, other, base, toolconf):
380 def _ifail(repo, mynode, local, other, base, toolconf):
381 """
381 """
382 Rather than attempting to merge files that were modified on both
382 Rather than attempting to merge files that were modified on both
383 branches, it marks them as unresolved. The resolve command must be
383 branches, it marks them as unresolved. The resolve command must be
384 used to resolve these conflicts."""
384 used to resolve these conflicts."""
385 # for change/delete conflicts write out the changed version, then fail
385 # for change/delete conflicts write out the changed version, then fail
386 if local.fctx.isabsent():
386 if local.fctx.isabsent():
387 _underlyingfctxifabsent(local.fctx).write(
387 _underlyingfctxifabsent(local.fctx).write(
388 other.fctx.data(), other.fctx.flags()
388 other.fctx.data(), other.fctx.flags()
389 )
389 )
390 return 1, False
390 return 1, False
391
391
392
392
393 def _underlyingfctxifabsent(filectx):
393 def _underlyingfctxifabsent(filectx):
394 """Sometimes when resolving, our fcd is actually an absentfilectx, but
394 """Sometimes when resolving, our fcd is actually an absentfilectx, but
395 we want to write to it (to do the resolve). This helper returns the
395 we want to write to it (to do the resolve). This helper returns the
396 underyling workingfilectx in that case.
396 underyling workingfilectx in that case.
397 """
397 """
398 if filectx.isabsent():
398 if filectx.isabsent():
399 return filectx.changectx()[filectx.path()]
399 return filectx.changectx()[filectx.path()]
400 else:
400 else:
401 return filectx
401 return filectx
402
402
403
403
404 def _verifytext(input, ui):
404 def _verifytext(input, ui):
405 """verifies that text is non-binary"""
405 """verifies that text is non-binary"""
406 if stringutil.binary(input.text()):
406 if stringutil.binary(input.text()):
407 msg = _(b"%s looks like a binary file.") % input.fctx.path()
407 msg = _(b"%s looks like a binary file.") % input.fctx.path()
408 ui.warn(_(b'warning: %s\n') % msg)
408 ui.warn(_(b'warning: %s\n') % msg)
409 raise error.Abort(msg)
409 raise error.Abort(msg)
410
410
411
411
412 def _premerge(repo, local, other, base, toolconf):
412 def _premerge(repo, local, other, base, toolconf):
413 tool, toolpath, binary, symlink, scriptfn = toolconf
413 tool, toolpath, binary, symlink, scriptfn = toolconf
414 if symlink or local.fctx.isabsent() or other.fctx.isabsent():
414 if symlink or local.fctx.isabsent() or other.fctx.isabsent():
415 return 1
415 return 1
416
416
417 ui = repo.ui
417 ui = repo.ui
418
418
419 validkeep = [b'keep', b'keep-merge3', b'keep-mergediff']
419 validkeep = [b'keep', b'keep-merge3', b'keep-mergediff']
420
420
421 # do we attempt to simplemerge first?
421 # do we attempt to simplemerge first?
422 try:
422 try:
423 premerge = _toolbool(ui, tool, b"premerge", not binary)
423 premerge = _toolbool(ui, tool, b"premerge", not binary)
424 except error.ConfigError:
424 except error.ConfigError:
425 premerge = _toolstr(ui, tool, b"premerge", b"").lower()
425 premerge = _toolstr(ui, tool, b"premerge", b"").lower()
426 if premerge not in validkeep:
426 if premerge not in validkeep:
427 _valid = b', '.join([b"'" + v + b"'" for v in validkeep])
427 _valid = b', '.join([b"'" + v + b"'" for v in validkeep])
428 raise error.ConfigError(
428 raise error.ConfigError(
429 _(b"%s.premerge not valid ('%s' is neither boolean nor %s)")
429 _(b"%s.premerge not valid ('%s' is neither boolean nor %s)")
430 % (tool, premerge, _valid)
430 % (tool, premerge, _valid)
431 )
431 )
432
432
433 if premerge:
433 if premerge:
434 mode = b'merge'
434 mode = b'merge'
435 if premerge == b'keep-mergediff':
435 if premerge == b'keep-mergediff':
436 mode = b'mergediff'
436 mode = b'mergediff'
437 elif premerge == b'keep-merge3':
437 elif premerge == b'keep-merge3':
438 mode = b'merge3'
438 mode = b'merge3'
439 if any(
439 if any(
440 stringutil.binary(input.text()) for input in (local, base, other)
440 stringutil.binary(input.text()) for input in (local, base, other)
441 ):
441 ):
442 return 1 # continue merging
442 return 1 # continue merging
443 merged_text, conflicts = simplemerge.simplemerge(
443 merged_text, conflicts = simplemerge.simplemerge(
444 local, base, other, mode=mode
444 local, base, other, mode=mode
445 )
445 )
446 if not conflicts or premerge in validkeep:
446 if not conflicts or premerge in validkeep:
447 # fcd.flags() already has the merged flags (done in
447 # fcd.flags() already has the merged flags (done in
448 # mergestate.resolve())
448 # mergestate.resolve())
449 local.fctx.write(merged_text, local.fctx.flags())
449 local.fctx.write(merged_text, local.fctx.flags())
450 if not conflicts:
450 if not conflicts:
451 ui.debug(b" premerge successful\n")
451 ui.debug(b" premerge successful\n")
452 return 0
452 return 0
453 return 1 # continue merging
453 return 1 # continue merging
454
454
455
455
456 def _mergecheck(repo, mynode, fcd, fco, fca, toolconf):
456 def _mergecheck(repo, mynode, fcd, fco, fca, toolconf):
457 tool, toolpath, binary, symlink, scriptfn = toolconf
457 tool, toolpath, binary, symlink, scriptfn = toolconf
458 uipathfn = scmutil.getuipathfn(repo)
458 uipathfn = scmutil.getuipathfn(repo)
459 if symlink:
459 if symlink:
460 repo.ui.warn(
460 repo.ui.warn(
461 _(b'warning: internal %s cannot merge symlinks for %s\n')
461 _(b'warning: internal %s cannot merge symlinks for %s\n')
462 % (tool, uipathfn(fcd.path()))
462 % (tool, uipathfn(fcd.path()))
463 )
463 )
464 return False
464 return False
465 if fcd.isabsent() or fco.isabsent():
465 if fcd.isabsent() or fco.isabsent():
466 repo.ui.warn(
466 repo.ui.warn(
467 _(
467 _(
468 b'warning: internal %s cannot merge change/delete '
468 b'warning: internal %s cannot merge change/delete '
469 b'conflict for %s\n'
469 b'conflict for %s\n'
470 )
470 )
471 % (tool, uipathfn(fcd.path()))
471 % (tool, uipathfn(fcd.path()))
472 )
472 )
473 return False
473 return False
474 return True
474 return True
475
475
476
476
477 def _merge(repo, local, other, base, mode):
477 def _merge(repo, local, other, base, mode):
478 """
478 """
479 Uses the internal non-interactive simple merge algorithm for merging
479 Uses the internal non-interactive simple merge algorithm for merging
480 files. It will fail if there are any conflicts and leave markers in
480 files. It will fail if there are any conflicts and leave markers in
481 the partially merged file. Markers will have two sections, one for each side
481 the partially merged file. Markers will have two sections, one for each side
482 of merge, unless mode equals 'union' which suppresses the markers."""
482 of merge, unless mode equals 'union' which suppresses the markers."""
483 ui = repo.ui
483 ui = repo.ui
484
484
485 try:
485 try:
486 _verifytext(local, ui)
486 _verifytext(local, ui)
487 _verifytext(base, ui)
487 _verifytext(base, ui)
488 _verifytext(other, ui)
488 _verifytext(other, ui)
489 except error.Abort:
489 except error.Abort:
490 return True, True, False
490 return True, True, False
491 else:
491 else:
492 merged_text, conflicts = simplemerge.simplemerge(
492 merged_text, conflicts = simplemerge.simplemerge(
493 local, base, other, mode=mode
493 local, base, other, mode=mode
494 )
494 )
495 # fcd.flags() already has the merged flags (done in
495 # fcd.flags() already has the merged flags (done in
496 # mergestate.resolve())
496 # mergestate.resolve())
497 local.fctx.write(merged_text, local.fctx.flags())
497 local.fctx.write(merged_text, local.fctx.flags())
498 return True, conflicts, False
498 return True, conflicts, False
499
499
500
500
501 @internaltool(
501 @internaltool(
502 b'union',
502 b'union',
503 fullmerge,
503 fullmerge,
504 _(
504 _(
505 b"warning: conflicts while merging %s! "
505 b"warning: conflicts while merging %s! "
506 b"(edit, then use 'hg resolve --mark')\n"
506 b"(edit, then use 'hg resolve --mark')\n"
507 ),
507 ),
508 precheck=_mergecheck,
508 precheck=_mergecheck,
509 )
509 )
510 def _iunion(repo, mynode, local, other, base, toolconf, backup):
510 def _iunion(repo, mynode, local, other, base, toolconf, backup):
511 """
511 """
512 Uses the internal non-interactive simple merge algorithm for merging
512 Uses the internal non-interactive simple merge algorithm for merging
513 files. It will use both left and right sides for conflict regions.
513 files. It will use both left and right sides for conflict regions.
514 No markers are inserted."""
514 No markers are inserted."""
515 return _merge(repo, local, other, base, b'union')
515 return _merge(repo, local, other, base, b'union')
516
516
517
517
518 @internaltool(
518 @internaltool(
519 b'merge',
519 b'merge',
520 fullmerge,
520 fullmerge,
521 _(
521 _(
522 b"warning: conflicts while merging %s! "
522 b"warning: conflicts while merging %s! "
523 b"(edit, then use 'hg resolve --mark')\n"
523 b"(edit, then use 'hg resolve --mark')\n"
524 ),
524 ),
525 precheck=_mergecheck,
525 precheck=_mergecheck,
526 )
526 )
527 def _imerge(repo, mynode, local, other, base, toolconf, backup):
527 def _imerge(repo, mynode, local, other, base, toolconf, backup):
528 """
528 """
529 Uses the internal non-interactive simple merge algorithm for merging
529 Uses the internal non-interactive simple merge algorithm for merging
530 files. It will fail if there are any conflicts and leave markers in
530 files. It will fail if there are any conflicts and leave markers in
531 the partially merged file. Markers will have two sections, one for each side
531 the partially merged file. Markers will have two sections, one for each side
532 of merge."""
532 of merge."""
533 return _merge(repo, local, other, base, b'merge')
533 return _merge(repo, local, other, base, b'merge')
534
534
535
535
536 @internaltool(
536 @internaltool(
537 b'merge3',
537 b'merge3',
538 fullmerge,
538 fullmerge,
539 _(
539 _(
540 b"warning: conflicts while merging %s! "
540 b"warning: conflicts while merging %s! "
541 b"(edit, then use 'hg resolve --mark')\n"
541 b"(edit, then use 'hg resolve --mark')\n"
542 ),
542 ),
543 precheck=_mergecheck,
543 precheck=_mergecheck,
544 )
544 )
545 def _imerge3(repo, mynode, local, other, base, toolconf, backup):
545 def _imerge3(repo, mynode, local, other, base, toolconf, backup):
546 """
546 """
547 Uses the internal non-interactive simple merge algorithm for merging
547 Uses the internal non-interactive simple merge algorithm for merging
548 files. It will fail if there are any conflicts and leave markers in
548 files. It will fail if there are any conflicts and leave markers in
549 the partially merged file. Marker will have three sections, one from each
549 the partially merged file. Marker will have three sections, one from each
550 side of the merge and one for the base content."""
550 side of the merge and one for the base content."""
551 return _merge(repo, local, other, base, b'merge3')
551 return _merge(repo, local, other, base, b'merge3')
552
552
553
553
554 @internaltool(
554 @internaltool(
555 b'merge3-lie-about-conflicts',
555 b'merge3-lie-about-conflicts',
556 fullmerge,
556 fullmerge,
557 b'',
557 b'',
558 precheck=_mergecheck,
558 precheck=_mergecheck,
559 )
559 )
560 def _imerge3alwaysgood(*args, **kwargs):
560 def _imerge3alwaysgood(*args, **kwargs):
561 # Like merge3, but record conflicts as resolved with markers in place.
561 # Like merge3, but record conflicts as resolved with markers in place.
562 #
562 #
563 # This is used for `diff.merge` to show the differences between
563 # This is used for `diff.merge` to show the differences between
564 # the auto-merge state and the committed merge state. It may be
564 # the auto-merge state and the committed merge state. It may be
565 # useful for other things.
565 # useful for other things.
566 b1, junk, b2 = _imerge3(*args, **kwargs)
566 b1, junk, b2 = _imerge3(*args, **kwargs)
567 # TODO is this right? I'm not sure what these return values mean,
567 # TODO is this right? I'm not sure what these return values mean,
568 # but as far as I can tell this will indicate to callers tha the
568 # but as far as I can tell this will indicate to callers tha the
569 # merge succeeded.
569 # merge succeeded.
570 return b1, False, b2
570 return b1, False, b2
571
571
572
572
573 @internaltool(
573 @internaltool(
574 b'mergediff',
574 b'mergediff',
575 fullmerge,
575 fullmerge,
576 _(
576 _(
577 b"warning: conflicts while merging %s! "
577 b"warning: conflicts while merging %s! "
578 b"(edit, then use 'hg resolve --mark')\n"
578 b"(edit, then use 'hg resolve --mark')\n"
579 ),
579 ),
580 precheck=_mergecheck,
580 precheck=_mergecheck,
581 )
581 )
582 def _imerge_diff(repo, mynode, local, other, base, toolconf, backup):
582 def _imerge_diff(repo, mynode, local, other, base, toolconf, backup):
583 """
583 """
584 Uses the internal non-interactive simple merge algorithm for merging
584 Uses the internal non-interactive simple merge algorithm for merging
585 files. It will fail if there are any conflicts and leave markers in
585 files. It will fail if there are any conflicts and leave markers in
586 the partially merged file. The marker will have two sections, one with the
586 the partially merged file. The marker will have two sections, one with the
587 content from one side of the merge, and one with a diff from the base
587 content from one side of the merge, and one with a diff from the base
588 content to the content on the other side. (experimental)"""
588 content to the content on the other side. (experimental)"""
589 return _merge(repo, local, other, base, b'mergediff')
589 return _merge(repo, local, other, base, b'mergediff')
590
590
591
591
592 @internaltool(b'merge-local', mergeonly, precheck=_mergecheck)
592 @internaltool(b'merge-local', mergeonly, precheck=_mergecheck)
593 def _imergelocal(repo, mynode, local, other, base, toolconf, backup):
593 def _imergelocal(repo, mynode, local, other, base, toolconf, backup):
594 """
594 """
595 Like :merge, but resolve all conflicts non-interactively in favor
595 Like :merge, but resolve all conflicts non-interactively in favor
596 of the local `p1()` changes."""
596 of the local `p1()` changes."""
597 return _merge(repo, local, other, base, b'local')
597 return _merge(repo, local, other, base, b'local')
598
598
599
599
600 @internaltool(b'merge-other', mergeonly, precheck=_mergecheck)
600 @internaltool(b'merge-other', mergeonly, precheck=_mergecheck)
601 def _imergeother(repo, mynode, local, other, base, toolconf, backup):
601 def _imergeother(repo, mynode, local, other, base, toolconf, backup):
602 """
602 """
603 Like :merge, but resolve all conflicts non-interactively in favor
603 Like :merge, but resolve all conflicts non-interactively in favor
604 of the other `p2()` changes."""
604 of the other `p2()` changes."""
605 return _merge(repo, local, other, base, b'other')
605 return _merge(repo, local, other, base, b'other')
606
606
607
607
608 @internaltool(
608 @internaltool(
609 b'tagmerge',
609 b'tagmerge',
610 mergeonly,
610 mergeonly,
611 _(
611 _(
612 b"automatic tag merging of %s failed! "
612 b"automatic tag merging of %s failed! "
613 b"(use 'hg resolve --tool :merge' or another merge "
613 b"(use 'hg resolve --tool :merge' or another merge "
614 b"tool of your choice)\n"
614 b"tool of your choice)\n"
615 ),
615 ),
616 )
616 )
617 def _itagmerge(repo, mynode, local, other, base, toolconf, backup):
617 def _itagmerge(repo, mynode, local, other, base, toolconf, backup):
618 """
618 """
619 Uses the internal tag merge algorithm (experimental).
619 Uses the internal tag merge algorithm (experimental).
620 """
620 """
621 success, status = tagmerge.merge(repo, local.fctx, other.fctx, base.fctx)
621 success, status = tagmerge.merge(repo, local.fctx, other.fctx, base.fctx)
622 return success, status, False
622 return success, status, False
623
623
624
624
625 @internaltool(b'dump', fullmerge, binary=True, symlink=True)
625 @internaltool(b'dump', fullmerge, binary=True, symlink=True)
626 def _idump(repo, mynode, local, other, base, toolconf, backup):
626 def _idump(repo, mynode, local, other, base, toolconf, backup):
627 """
627 """
628 Creates three versions of the files to merge, containing the
628 Creates three versions of the files to merge, containing the
629 contents of local, other and base. These files can then be used to
629 contents of local, other and base. These files can then be used to
630 perform a merge manually. If the file to be merged is named
630 perform a merge manually. If the file to be merged is named
631 ``a.txt``, these files will accordingly be named ``a.txt.local``,
631 ``a.txt``, these files will accordingly be named ``a.txt.local``,
632 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
632 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
633 same directory as ``a.txt``.
633 same directory as ``a.txt``.
634
634
635 This implies premerge. Therefore, files aren't dumped, if premerge
635 This implies premerge. Therefore, files aren't dumped, if premerge
636 runs successfully. Use :forcedump to forcibly write files out.
636 runs successfully. Use :forcedump to forcibly write files out.
637 """
637 """
638 a = _workingpath(repo, local.fctx)
638 a = _workingpath(repo, local.fctx)
639 fd = local.fctx.path()
639 fd = local.fctx.path()
640
640
641 from . import context
641 from . import context
642
642
643 if isinstance(local.fctx, context.overlayworkingfilectx):
643 if isinstance(local.fctx, context.overlayworkingfilectx):
644 raise error.InMemoryMergeConflictsError(
644 raise error.InMemoryMergeConflictsError(
645 b'in-memory merge does not support the :dump tool.'
645 b'in-memory merge does not support the :dump tool.'
646 )
646 )
647
647
648 util.writefile(a + b".local", local.fctx.decodeddata())
648 util.writefile(a + b".local", local.fctx.decodeddata())
649 repo.wwrite(fd + b".other", other.fctx.data(), other.fctx.flags())
649 repo.wwrite(fd + b".other", other.fctx.data(), other.fctx.flags())
650 repo.wwrite(fd + b".base", base.fctx.data(), base.fctx.flags())
650 repo.wwrite(fd + b".base", base.fctx.data(), base.fctx.flags())
651 return False, 1, False
651 return False, 1, False
652
652
653
653
654 @internaltool(b'forcedump', mergeonly, binary=True, symlink=True)
654 @internaltool(b'forcedump', mergeonly, binary=True, symlink=True)
655 def _forcedump(repo, mynode, local, other, base, toolconf, backup):
655 def _forcedump(repo, mynode, local, other, base, toolconf, backup):
656 """
656 """
657 Creates three versions of the files as same as :dump, but omits premerge.
657 Creates three versions of the files as same as :dump, but omits premerge.
658 """
658 """
659 return _idump(repo, mynode, local, other, base, toolconf, backup)
659 return _idump(repo, mynode, local, other, base, toolconf, backup)
660
660
661
661
662 def _xmergeimm(repo, mynode, local, other, base, toolconf, backup):
662 def _xmergeimm(repo, mynode, local, other, base, toolconf, backup):
663 # In-memory merge simply raises an exception on all external merge tools,
663 # In-memory merge simply raises an exception on all external merge tools,
664 # for now.
664 # for now.
665 #
665 #
666 # It would be possible to run most tools with temporary files, but this
666 # It would be possible to run most tools with temporary files, but this
667 # raises the question of what to do if the user only partially resolves the
667 # raises the question of what to do if the user only partially resolves the
668 # file -- we can't leave a merge state. (Copy to somewhere in the .hg/
668 # file -- we can't leave a merge state. (Copy to somewhere in the .hg/
669 # directory and tell the user how to get it is my best idea, but it's
669 # directory and tell the user how to get it is my best idea, but it's
670 # clunky.)
670 # clunky.)
671 raise error.InMemoryMergeConflictsError(
671 raise error.InMemoryMergeConflictsError(
672 b'in-memory merge does not support external merge tools'
672 b'in-memory merge does not support external merge tools'
673 )
673 )
674
674
675
675
676 def _describemerge(ui, repo, mynode, fcl, fcb, fco, env, toolpath, args):
676 def _describemerge(ui, repo, mynode, fcl, fcb, fco, env, toolpath, args):
677 tmpl = ui.config(b'command-templates', b'pre-merge-tool-output')
677 tmpl = ui.config(b'command-templates', b'pre-merge-tool-output')
678 if not tmpl:
678 if not tmpl:
679 return
679 return
680
680
681 mappingdict = templateutil.mappingdict
681 mappingdict = templateutil.mappingdict
682 props = {
682 props = {
683 b'ctx': fcl.changectx(),
683 b'ctx': fcl.changectx(),
684 b'node': hex(mynode),
684 b'node': hex(mynode),
685 b'path': fcl.path(),
685 b'path': fcl.path(),
686 b'local': mappingdict(
686 b'local': mappingdict(
687 {
687 {
688 b'ctx': fcl.changectx(),
688 b'ctx': fcl.changectx(),
689 b'fctx': fcl,
689 b'fctx': fcl,
690 b'node': hex(mynode),
690 b'node': hex(mynode),
691 b'name': _(b'local'),
691 b'name': _(b'local'),
692 b'islink': b'l' in fcl.flags(),
692 b'islink': b'l' in fcl.flags(),
693 b'label': env[b'HG_MY_LABEL'],
693 b'label': env[b'HG_MY_LABEL'],
694 }
694 }
695 ),
695 ),
696 b'base': mappingdict(
696 b'base': mappingdict(
697 {
697 {
698 b'ctx': fcb.changectx(),
698 b'ctx': fcb.changectx(),
699 b'fctx': fcb,
699 b'fctx': fcb,
700 b'name': _(b'base'),
700 b'name': _(b'base'),
701 b'islink': b'l' in fcb.flags(),
701 b'islink': b'l' in fcb.flags(),
702 b'label': env[b'HG_BASE_LABEL'],
702 b'label': env[b'HG_BASE_LABEL'],
703 }
703 }
704 ),
704 ),
705 b'other': mappingdict(
705 b'other': mappingdict(
706 {
706 {
707 b'ctx': fco.changectx(),
707 b'ctx': fco.changectx(),
708 b'fctx': fco,
708 b'fctx': fco,
709 b'name': _(b'other'),
709 b'name': _(b'other'),
710 b'islink': b'l' in fco.flags(),
710 b'islink': b'l' in fco.flags(),
711 b'label': env[b'HG_OTHER_LABEL'],
711 b'label': env[b'HG_OTHER_LABEL'],
712 }
712 }
713 ),
713 ),
714 b'toolpath': toolpath,
714 b'toolpath': toolpath,
715 b'toolargs': args,
715 b'toolargs': args,
716 }
716 }
717
717
718 # TODO: make all of this something that can be specified on a per-tool basis
718 # TODO: make all of this something that can be specified on a per-tool basis
719 tmpl = templater.unquotestring(tmpl)
719 tmpl = templater.unquotestring(tmpl)
720
720
721 # Not using cmdutil.rendertemplate here since it causes errors importing
721 # Not using cmdutil.rendertemplate here since it causes errors importing
722 # things for us to import cmdutil.
722 # things for us to import cmdutil.
723 tres = formatter.templateresources(ui, repo)
723 tres = formatter.templateresources(ui, repo)
724 t = formatter.maketemplater(
724 t = formatter.maketemplater(
725 ui, tmpl, defaults=templatekw.keywords, resources=tres
725 ui, tmpl, defaults=templatekw.keywords, resources=tres
726 )
726 )
727 ui.status(t.renderdefault(props))
727 ui.status(t.renderdefault(props))
728
728
729
729
730 def _xmerge(repo, mynode, local, other, base, toolconf, backup):
730 def _xmerge(repo, mynode, local, other, base, toolconf, backup):
731 fcd = local.fctx
731 fcd = local.fctx
732 fco = other.fctx
732 fco = other.fctx
733 fca = base.fctx
733 fca = base.fctx
734 tool, toolpath, binary, symlink, scriptfn = toolconf
734 tool, toolpath, binary, symlink, scriptfn = toolconf
735 uipathfn = scmutil.getuipathfn(repo)
735 uipathfn = scmutil.getuipathfn(repo)
736 if fcd.isabsent() or fco.isabsent():
736 if fcd.isabsent() or fco.isabsent():
737 repo.ui.warn(
737 repo.ui.warn(
738 _(b'warning: %s cannot merge change/delete conflict for %s\n')
738 _(b'warning: %s cannot merge change/delete conflict for %s\n')
739 % (tool, uipathfn(fcd.path()))
739 % (tool, uipathfn(fcd.path()))
740 )
740 )
741 return False, 1, None
741 return False, 1, None
742 localpath = _workingpath(repo, fcd)
742 localpath = _workingpath(repo, fcd)
743 args = _toolstr(repo.ui, tool, b"args")
743 args = _toolstr(repo.ui, tool, b"args")
744
744
745 files = [
745 files = [
746 (b"base", fca.path(), fca.decodeddata()),
746 (b"base", fca.path(), fca.decodeddata()),
747 (b"other", fco.path(), fco.decodeddata()),
747 (b"other", fco.path(), fco.decodeddata()),
748 ]
748 ]
749 outpath = b""
749 outpath = b""
750 if b"$output" in args:
750 if b"$output" in args:
751 # read input from backup, write to original
751 # read input from backup, write to original
752 outpath = localpath
752 outpath = localpath
753 localoutputpath = backup.path()
753 localoutputpath = backup.path()
754 # Remove the .orig to make syntax-highlighting more likely.
754 # Remove the .orig to make syntax-highlighting more likely.
755 if localoutputpath.endswith(b'.orig'):
755 if localoutputpath.endswith(b'.orig'):
756 localoutputpath, ext = os.path.splitext(localoutputpath)
756 localoutputpath, ext = os.path.splitext(localoutputpath)
757 localdata = util.readfile(localpath)
757 files.append((b"local", localoutputpath, backup.data()))
758 files.append((b"local", localoutputpath, localdata))
759
758
760 with _maketempfiles(files) as temppaths:
759 with _maketempfiles(files) as temppaths:
761 basepath, otherpath = temppaths[:2]
760 basepath, otherpath = temppaths[:2]
762 if len(temppaths) == 3:
761 if len(temppaths) == 3:
763 localpath = temppaths[2]
762 localpath = temppaths[2]
764
763
765 def format_label(input):
764 def format_label(input):
766 if input.label_detail:
765 if input.label_detail:
767 return b'%s: %s' % (input.label, input.label_detail)
766 return b'%s: %s' % (input.label, input.label_detail)
768 else:
767 else:
769 return input.label
768 return input.label
770
769
771 env = {
770 env = {
772 b'HG_FILE': fcd.path(),
771 b'HG_FILE': fcd.path(),
773 b'HG_MY_NODE': short(mynode),
772 b'HG_MY_NODE': short(mynode),
774 b'HG_OTHER_NODE': short(fco.changectx().node()),
773 b'HG_OTHER_NODE': short(fco.changectx().node()),
775 b'HG_BASE_NODE': short(fca.changectx().node()),
774 b'HG_BASE_NODE': short(fca.changectx().node()),
776 b'HG_MY_ISLINK': b'l' in fcd.flags(),
775 b'HG_MY_ISLINK': b'l' in fcd.flags(),
777 b'HG_OTHER_ISLINK': b'l' in fco.flags(),
776 b'HG_OTHER_ISLINK': b'l' in fco.flags(),
778 b'HG_BASE_ISLINK': b'l' in fca.flags(),
777 b'HG_BASE_ISLINK': b'l' in fca.flags(),
779 b'HG_MY_LABEL': format_label(local),
778 b'HG_MY_LABEL': format_label(local),
780 b'HG_OTHER_LABEL': format_label(other),
779 b'HG_OTHER_LABEL': format_label(other),
781 b'HG_BASE_LABEL': format_label(base),
780 b'HG_BASE_LABEL': format_label(base),
782 }
781 }
783 ui = repo.ui
782 ui = repo.ui
784
783
785 replace = {
784 replace = {
786 b'local': localpath,
785 b'local': localpath,
787 b'base': basepath,
786 b'base': basepath,
788 b'other': otherpath,
787 b'other': otherpath,
789 b'output': outpath,
788 b'output': outpath,
790 b'labellocal': format_label(local),
789 b'labellocal': format_label(local),
791 b'labelother': format_label(other),
790 b'labelother': format_label(other),
792 b'labelbase': format_label(base),
791 b'labelbase': format_label(base),
793 }
792 }
794 args = util.interpolate(
793 args = util.interpolate(
795 br'\$',
794 br'\$',
796 replace,
795 replace,
797 args,
796 args,
798 lambda s: procutil.shellquote(util.localpath(s)),
797 lambda s: procutil.shellquote(util.localpath(s)),
799 )
798 )
800 if _toolbool(ui, tool, b"gui"):
799 if _toolbool(ui, tool, b"gui"):
801 repo.ui.status(
800 repo.ui.status(
802 _(b'running merge tool %s for file %s\n')
801 _(b'running merge tool %s for file %s\n')
803 % (tool, uipathfn(fcd.path()))
802 % (tool, uipathfn(fcd.path()))
804 )
803 )
805 if scriptfn is None:
804 if scriptfn is None:
806 cmd = toolpath + b' ' + args
805 cmd = toolpath + b' ' + args
807 repo.ui.debug(b'launching merge tool: %s\n' % cmd)
806 repo.ui.debug(b'launching merge tool: %s\n' % cmd)
808 _describemerge(ui, repo, mynode, fcd, fca, fco, env, toolpath, args)
807 _describemerge(ui, repo, mynode, fcd, fca, fco, env, toolpath, args)
809 r = ui.system(
808 r = ui.system(
810 cmd, cwd=repo.root, environ=env, blockedtag=b'mergetool'
809 cmd, cwd=repo.root, environ=env, blockedtag=b'mergetool'
811 )
810 )
812 else:
811 else:
813 repo.ui.debug(
812 repo.ui.debug(
814 b'launching python merge script: %s:%s\n' % (toolpath, scriptfn)
813 b'launching python merge script: %s:%s\n' % (toolpath, scriptfn)
815 )
814 )
816 r = 0
815 r = 0
817 try:
816 try:
818 # avoid cycle cmdutil->merge->filemerge->extensions->cmdutil
817 # avoid cycle cmdutil->merge->filemerge->extensions->cmdutil
819 from . import extensions
818 from . import extensions
820
819
821 mod = extensions.loadpath(toolpath, b'hgmerge.%s' % tool)
820 mod = extensions.loadpath(toolpath, b'hgmerge.%s' % tool)
822 except Exception:
821 except Exception:
823 raise error.Abort(
822 raise error.Abort(
824 _(b"loading python merge script failed: %s") % toolpath
823 _(b"loading python merge script failed: %s") % toolpath
825 )
824 )
826 mergefn = getattr(mod, scriptfn, None)
825 mergefn = getattr(mod, scriptfn, None)
827 if mergefn is None:
826 if mergefn is None:
828 raise error.Abort(
827 raise error.Abort(
829 _(b"%s does not have function: %s") % (toolpath, scriptfn)
828 _(b"%s does not have function: %s") % (toolpath, scriptfn)
830 )
829 )
831 argslist = procutil.shellsplit(args)
830 argslist = procutil.shellsplit(args)
832 # avoid cycle cmdutil->merge->filemerge->hook->extensions->cmdutil
831 # avoid cycle cmdutil->merge->filemerge->hook->extensions->cmdutil
833 from . import hook
832 from . import hook
834
833
835 ret, raised = hook.pythonhook(
834 ret, raised = hook.pythonhook(
836 ui, repo, b"merge", toolpath, mergefn, {b'args': argslist}, True
835 ui, repo, b"merge", toolpath, mergefn, {b'args': argslist}, True
837 )
836 )
838 if raised:
837 if raised:
839 r = 1
838 r = 1
840 repo.ui.debug(b'merge tool returned: %d\n' % r)
839 repo.ui.debug(b'merge tool returned: %d\n' % r)
841 return True, r, False
840 return True, r, False
842
841
843
842
844 def _populate_label_detail(input, template):
843 def _populate_label_detail(input, template):
845 """Applies the given template to the ctx and stores it in the input."""
844 """Applies the given template to the ctx and stores it in the input."""
846 ctx = input.fctx.changectx()
845 ctx = input.fctx.changectx()
847 if ctx.node() is None:
846 if ctx.node() is None:
848 ctx = ctx.p1()
847 ctx = ctx.p1()
849
848
850 props = {b'ctx': ctx}
849 props = {b'ctx': ctx}
851 templateresult = template.renderdefault(props)
850 templateresult = template.renderdefault(props)
852 input.label_detail = templateresult.splitlines()[0] # split for safety
851 input.label_detail = templateresult.splitlines()[0] # split for safety
853
852
854
853
855 def _populate_label_details(repo, inputs, tool=None):
854 def _populate_label_details(repo, inputs, tool=None):
856 """Populates the label details using the conflict marker template."""
855 """Populates the label details using the conflict marker template."""
857 ui = repo.ui
856 ui = repo.ui
858 template = ui.config(b'command-templates', b'mergemarker')
857 template = ui.config(b'command-templates', b'mergemarker')
859 if tool is not None:
858 if tool is not None:
860 template = _toolstr(ui, tool, b'mergemarkertemplate', template)
859 template = _toolstr(ui, tool, b'mergemarkertemplate', template)
861 template = templater.unquotestring(template)
860 template = templater.unquotestring(template)
862 tres = formatter.templateresources(ui, repo)
861 tres = formatter.templateresources(ui, repo)
863 tmpl = formatter.maketemplater(
862 tmpl = formatter.maketemplater(
864 ui, template, defaults=templatekw.keywords, resources=tres
863 ui, template, defaults=templatekw.keywords, resources=tres
865 )
864 )
866
865
867 for input in inputs:
866 for input in inputs:
868 _populate_label_detail(input, tmpl)
867 _populate_label_detail(input, tmpl)
869
868
870
869
871 def partextras(labels):
870 def partextras(labels):
872 """Return a dictionary of extra labels for use in prompts to the user
871 """Return a dictionary of extra labels for use in prompts to the user
873
872
874 Intended use is in strings of the form "(l)ocal%(l)s".
873 Intended use is in strings of the form "(l)ocal%(l)s".
875 """
874 """
876 if labels is None:
875 if labels is None:
877 return {
876 return {
878 b"l": b"",
877 b"l": b"",
879 b"o": b"",
878 b"o": b"",
880 }
879 }
881
880
882 return {
881 return {
883 b"l": b" [%s]" % labels[0],
882 b"l": b" [%s]" % labels[0],
884 b"o": b" [%s]" % labels[1],
883 b"o": b" [%s]" % labels[1],
885 }
884 }
886
885
887
886
888 def _makebackup(repo, ui, fcd):
887 def _makebackup(repo, ui, fcd):
889 """Makes and returns a filectx-like object for ``fcd``'s backup file.
888 """Makes and returns a filectx-like object for ``fcd``'s backup file.
890
889
891 In addition to preserving the user's pre-existing modifications to `fcd`
890 In addition to preserving the user's pre-existing modifications to `fcd`
892 (if any), the backup is used to undo certain premerges, confirm whether a
891 (if any), the backup is used to undo certain premerges, confirm whether a
893 merge changed anything, and determine what line endings the new file should
892 merge changed anything, and determine what line endings the new file should
894 have.
893 have.
895
894
896 Backups only need to be written once since their content doesn't change
895 Backups only need to be written once since their content doesn't change
897 afterwards.
896 afterwards.
898 """
897 """
899 if fcd.isabsent():
898 if fcd.isabsent():
900 return None
899 return None
901 # TODO: Break this import cycle somehow. (filectx -> ctx -> fileset ->
900 # TODO: Break this import cycle somehow. (filectx -> ctx -> fileset ->
902 # merge -> filemerge). (I suspect the fileset import is the weakest link)
901 # merge -> filemerge). (I suspect the fileset import is the weakest link)
903 from . import context
902 from . import context
904
903
905 if isinstance(fcd, context.overlayworkingfilectx):
904 if isinstance(fcd, context.overlayworkingfilectx):
906 # If we're merging in-memory, we're free to put the backup anywhere.
905 # If we're merging in-memory, we're free to put the backup anywhere.
907 fd, backup = pycompat.mkstemp(b'hg-merge-backup')
906 fd, backup = pycompat.mkstemp(b'hg-merge-backup')
908 with os.fdopen(fd, 'wb') as f:
907 with os.fdopen(fd, 'wb') as f:
909 f.write(fcd.data())
908 f.write(fcd.data())
910 else:
909 else:
911 backup = scmutil.backuppath(ui, repo, fcd.path())
910 backup = scmutil.backuppath(ui, repo, fcd.path())
912 a = _workingpath(repo, fcd)
911 a = _workingpath(repo, fcd)
913 util.copyfile(a, backup)
912 util.copyfile(a, backup)
914
913
915 return context.arbitraryfilectx(backup, repo=repo)
914 return context.arbitraryfilectx(backup, repo=repo)
916
915
917
916
918 @contextlib.contextmanager
917 @contextlib.contextmanager
919 def _maketempfiles(files):
918 def _maketempfiles(files):
920 """Creates a temporary file for each (prefix, path, data) tuple in `files`,
919 """Creates a temporary file for each (prefix, path, data) tuple in `files`,
921 so an external merge tool may use them.
920 so an external merge tool may use them.
922 """
921 """
923 tmproot = pycompat.mkdtemp(prefix=b'hgmerge-')
922 tmproot = pycompat.mkdtemp(prefix=b'hgmerge-')
924
923
925 def maketempfrompath(prefix, path, data):
924 def maketempfrompath(prefix, path, data):
926 fullbase, ext = os.path.splitext(path)
925 fullbase, ext = os.path.splitext(path)
927 pre = b"%s~%s" % (os.path.basename(fullbase), prefix)
926 pre = b"%s~%s" % (os.path.basename(fullbase), prefix)
928 name = os.path.join(tmproot, pre)
927 name = os.path.join(tmproot, pre)
929 if ext:
928 if ext:
930 name += ext
929 name += ext
931 util.writefile(name, data)
930 util.writefile(name, data)
932 return name
931 return name
933
932
934 temp_files = []
933 temp_files = []
935 for prefix, path, data in files:
934 for prefix, path, data in files:
936 temp_files.append(maketempfrompath(prefix, path, data))
935 temp_files.append(maketempfrompath(prefix, path, data))
937 try:
936 try:
938 yield temp_files
937 yield temp_files
939 finally:
938 finally:
940 shutil.rmtree(tmproot)
939 shutil.rmtree(tmproot)
941
940
942
941
943 def filemerge(repo, wctx, mynode, orig, fcd, fco, fca, labels=None):
942 def filemerge(repo, wctx, mynode, orig, fcd, fco, fca, labels=None):
944 """perform a 3-way merge in the working directory
943 """perform a 3-way merge in the working directory
945
944
946 mynode = parent node before merge
945 mynode = parent node before merge
947 orig = original local filename before merge
946 orig = original local filename before merge
948 fco = other file context
947 fco = other file context
949 fca = ancestor file context
948 fca = ancestor file context
950 fcd = local file context for current/destination file
949 fcd = local file context for current/destination file
951
950
952 Returns whether the merge is complete, the return value of the merge, and
951 Returns whether the merge is complete, the return value of the merge, and
953 a boolean indicating whether the file was deleted from disk."""
952 a boolean indicating whether the file was deleted from disk."""
954 ui = repo.ui
953 ui = repo.ui
955 fd = fcd.path()
954 fd = fcd.path()
956 uipathfn = scmutil.getuipathfn(repo)
955 uipathfn = scmutil.getuipathfn(repo)
957 fduipath = uipathfn(fd)
956 fduipath = uipathfn(fd)
958 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
957 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
959 symlink = b'l' in fcd.flags() + fco.flags()
958 symlink = b'l' in fcd.flags() + fco.flags()
960 changedelete = fcd.isabsent() or fco.isabsent()
959 changedelete = fcd.isabsent() or fco.isabsent()
961 tool, toolpath = _picktool(repo, ui, fd, binary, symlink, changedelete)
960 tool, toolpath = _picktool(repo, ui, fd, binary, symlink, changedelete)
962 scriptfn = None
961 scriptfn = None
963 if tool in internals and tool.startswith(b'internal:'):
962 if tool in internals and tool.startswith(b'internal:'):
964 # normalize to new-style names (':merge' etc)
963 # normalize to new-style names (':merge' etc)
965 tool = tool[len(b'internal') :]
964 tool = tool[len(b'internal') :]
966 if toolpath and toolpath.startswith(b'python:'):
965 if toolpath and toolpath.startswith(b'python:'):
967 invalidsyntax = False
966 invalidsyntax = False
968 if toolpath.count(b':') >= 2:
967 if toolpath.count(b':') >= 2:
969 script, scriptfn = toolpath[7:].rsplit(b':', 1)
968 script, scriptfn = toolpath[7:].rsplit(b':', 1)
970 if not scriptfn:
969 if not scriptfn:
971 invalidsyntax = True
970 invalidsyntax = True
972 # missing :callable can lead to spliting on windows drive letter
971 # missing :callable can lead to spliting on windows drive letter
973 if b'\\' in scriptfn or b'/' in scriptfn:
972 if b'\\' in scriptfn or b'/' in scriptfn:
974 invalidsyntax = True
973 invalidsyntax = True
975 else:
974 else:
976 invalidsyntax = True
975 invalidsyntax = True
977 if invalidsyntax:
976 if invalidsyntax:
978 raise error.Abort(_(b"invalid 'python:' syntax: %s") % toolpath)
977 raise error.Abort(_(b"invalid 'python:' syntax: %s") % toolpath)
979 toolpath = script
978 toolpath = script
980 ui.debug(
979 ui.debug(
981 b"picked tool '%s' for %s (binary %s symlink %s changedelete %s)\n"
980 b"picked tool '%s' for %s (binary %s symlink %s changedelete %s)\n"
982 % (
981 % (
983 tool,
982 tool,
984 fduipath,
983 fduipath,
985 pycompat.bytestr(binary),
984 pycompat.bytestr(binary),
986 pycompat.bytestr(symlink),
985 pycompat.bytestr(symlink),
987 pycompat.bytestr(changedelete),
986 pycompat.bytestr(changedelete),
988 )
987 )
989 )
988 )
990
989
991 if tool in internals:
990 if tool in internals:
992 func = internals[tool]
991 func = internals[tool]
993 mergetype = func.mergetype
992 mergetype = func.mergetype
994 onfailure = func.onfailure
993 onfailure = func.onfailure
995 precheck = func.precheck
994 precheck = func.precheck
996 isexternal = False
995 isexternal = False
997 else:
996 else:
998 if wctx.isinmemory():
997 if wctx.isinmemory():
999 func = _xmergeimm
998 func = _xmergeimm
1000 else:
999 else:
1001 func = _xmerge
1000 func = _xmerge
1002 mergetype = fullmerge
1001 mergetype = fullmerge
1003 onfailure = _(b"merging %s failed!\n")
1002 onfailure = _(b"merging %s failed!\n")
1004 precheck = None
1003 precheck = None
1005 isexternal = True
1004 isexternal = True
1006
1005
1007 toolconf = tool, toolpath, binary, symlink, scriptfn
1006 toolconf = tool, toolpath, binary, symlink, scriptfn
1008
1007
1009 if not labels:
1008 if not labels:
1010 labels = [b'local', b'other']
1009 labels = [b'local', b'other']
1011 if len(labels) < 3:
1010 if len(labels) < 3:
1012 labels.append(b'base')
1011 labels.append(b'base')
1013 local = simplemerge.MergeInput(fcd, labels[0])
1012 local = simplemerge.MergeInput(fcd, labels[0])
1014 other = simplemerge.MergeInput(fco, labels[1])
1013 other = simplemerge.MergeInput(fco, labels[1])
1015 base = simplemerge.MergeInput(fca, labels[2])
1014 base = simplemerge.MergeInput(fca, labels[2])
1016 if mergetype == nomerge:
1015 if mergetype == nomerge:
1017 return func(
1016 return func(
1018 repo,
1017 repo,
1019 mynode,
1018 mynode,
1020 local,
1019 local,
1021 other,
1020 other,
1022 base,
1021 base,
1023 toolconf,
1022 toolconf,
1024 )
1023 )
1025
1024
1026 if orig != fco.path():
1025 if orig != fco.path():
1027 ui.status(
1026 ui.status(
1028 _(b"merging %s and %s to %s\n")
1027 _(b"merging %s and %s to %s\n")
1029 % (uipathfn(orig), uipathfn(fco.path()), fduipath)
1028 % (uipathfn(orig), uipathfn(fco.path()), fduipath)
1030 )
1029 )
1031 else:
1030 else:
1032 ui.status(_(b"merging %s\n") % fduipath)
1031 ui.status(_(b"merging %s\n") % fduipath)
1033
1032
1034 ui.debug(b"my %s other %s ancestor %s\n" % (fcd, fco, fca))
1033 ui.debug(b"my %s other %s ancestor %s\n" % (fcd, fco, fca))
1035
1034
1036 if precheck and not precheck(repo, mynode, fcd, fco, fca, toolconf):
1035 if precheck and not precheck(repo, mynode, fcd, fco, fca, toolconf):
1037 if onfailure:
1036 if onfailure:
1038 if wctx.isinmemory():
1037 if wctx.isinmemory():
1039 raise error.InMemoryMergeConflictsError(
1038 raise error.InMemoryMergeConflictsError(
1040 b'in-memory merge does not support merge conflicts'
1039 b'in-memory merge does not support merge conflicts'
1041 )
1040 )
1042 ui.warn(onfailure % fduipath)
1041 ui.warn(onfailure % fduipath)
1043 return 1, False
1042 return 1, False
1044
1043
1045 backup = _makebackup(repo, ui, fcd)
1044 backup = _makebackup(repo, ui, fcd)
1046 r = 1
1045 r = 1
1047 try:
1046 try:
1048 internalmarkerstyle = ui.config(b'ui', b'mergemarkers')
1047 internalmarkerstyle = ui.config(b'ui', b'mergemarkers')
1049 if isexternal:
1048 if isexternal:
1050 markerstyle = _toolstr(ui, tool, b'mergemarkers')
1049 markerstyle = _toolstr(ui, tool, b'mergemarkers')
1051 else:
1050 else:
1052 markerstyle = internalmarkerstyle
1051 markerstyle = internalmarkerstyle
1053
1052
1054 if mergetype == fullmerge:
1053 if mergetype == fullmerge:
1055 # conflict markers generated by premerge will use 'detailed'
1054 # conflict markers generated by premerge will use 'detailed'
1056 # settings if either ui.mergemarkers or the tool's mergemarkers
1055 # settings if either ui.mergemarkers or the tool's mergemarkers
1057 # setting is 'detailed'. This way tools can have basic labels in
1056 # setting is 'detailed'. This way tools can have basic labels in
1058 # space-constrained areas of the UI, but still get full information
1057 # space-constrained areas of the UI, but still get full information
1059 # in conflict markers if premerge is 'keep' or 'keep-merge3'.
1058 # in conflict markers if premerge is 'keep' or 'keep-merge3'.
1060 labeltool = None
1059 labeltool = None
1061 if markerstyle != b'basic':
1060 if markerstyle != b'basic':
1062 # respect 'tool's mergemarkertemplate (which defaults to
1061 # respect 'tool's mergemarkertemplate (which defaults to
1063 # command-templates.mergemarker)
1062 # command-templates.mergemarker)
1064 labeltool = tool
1063 labeltool = tool
1065 if internalmarkerstyle != b'basic' or markerstyle != b'basic':
1064 if internalmarkerstyle != b'basic' or markerstyle != b'basic':
1066 _populate_label_details(
1065 _populate_label_details(
1067 repo, [local, other, base], tool=labeltool
1066 repo, [local, other, base], tool=labeltool
1068 )
1067 )
1069
1068
1070 r = _premerge(
1069 r = _premerge(
1071 repo,
1070 repo,
1072 local,
1071 local,
1073 other,
1072 other,
1074 base,
1073 base,
1075 toolconf,
1074 toolconf,
1076 )
1075 )
1077 # we're done if premerge was successful (r is 0)
1076 # we're done if premerge was successful (r is 0)
1078 if not r:
1077 if not r:
1079 return r, False
1078 return r, False
1080
1079
1081 # Reset to basic labels
1080 # Reset to basic labels
1082 local.label_detail = None
1081 local.label_detail = None
1083 other.label_detail = None
1082 other.label_detail = None
1084 base.label_detail = None
1083 base.label_detail = None
1085
1084
1086 if markerstyle != b'basic':
1085 if markerstyle != b'basic':
1087 _populate_label_details(repo, [local, other, base], tool=tool)
1086 _populate_label_details(repo, [local, other, base], tool=tool)
1088
1087
1089 needcheck, r, deleted = func(
1088 needcheck, r, deleted = func(
1090 repo,
1089 repo,
1091 mynode,
1090 mynode,
1092 local,
1091 local,
1093 other,
1092 other,
1094 base,
1093 base,
1095 toolconf,
1094 toolconf,
1096 backup,
1095 backup,
1097 )
1096 )
1098
1097
1099 if needcheck:
1098 if needcheck:
1100 r = _check(repo, r, ui, tool, fcd, backup)
1099 r = _check(repo, r, ui, tool, fcd, backup)
1101
1100
1102 if r:
1101 if r:
1103 if onfailure:
1102 if onfailure:
1104 if wctx.isinmemory():
1103 if wctx.isinmemory():
1105 raise error.InMemoryMergeConflictsError(
1104 raise error.InMemoryMergeConflictsError(
1106 b'in-memory merge '
1105 b'in-memory merge '
1107 b'does not support '
1106 b'does not support '
1108 b'merge conflicts'
1107 b'merge conflicts'
1109 )
1108 )
1110 ui.warn(onfailure % fduipath)
1109 ui.warn(onfailure % fduipath)
1111 _onfilemergefailure(ui)
1110 _onfilemergefailure(ui)
1112
1111
1113 return r, deleted
1112 return r, deleted
1114 finally:
1113 finally:
1115 if not r and backup is not None:
1114 if not r and backup is not None:
1116 backup.remove()
1115 backup.remove()
1117
1116
1118
1117
1119 def _haltmerge():
1118 def _haltmerge():
1120 msg = _(b'merge halted after failed merge (see hg resolve)')
1119 msg = _(b'merge halted after failed merge (see hg resolve)')
1121 raise error.InterventionRequired(msg)
1120 raise error.InterventionRequired(msg)
1122
1121
1123
1122
1124 def _onfilemergefailure(ui):
1123 def _onfilemergefailure(ui):
1125 action = ui.config(b'merge', b'on-failure')
1124 action = ui.config(b'merge', b'on-failure')
1126 if action == b'prompt':
1125 if action == b'prompt':
1127 msg = _(b'continue merge operation (yn)?$$ &Yes $$ &No')
1126 msg = _(b'continue merge operation (yn)?$$ &Yes $$ &No')
1128 if ui.promptchoice(msg, 0) == 1:
1127 if ui.promptchoice(msg, 0) == 1:
1129 _haltmerge()
1128 _haltmerge()
1130 if action == b'halt':
1129 if action == b'halt':
1131 _haltmerge()
1130 _haltmerge()
1132 # default action is 'continue', in which case we neither prompt nor halt
1131 # default action is 'continue', in which case we neither prompt nor halt
1133
1132
1134
1133
1135 def hasconflictmarkers(data):
1134 def hasconflictmarkers(data):
1136 # Detect lines starting with a string of 7 identical characters from the
1135 # Detect lines starting with a string of 7 identical characters from the
1137 # subset Mercurial uses for conflict markers, followed by either the end of
1136 # subset Mercurial uses for conflict markers, followed by either the end of
1138 # line or a space and some text. Note that using [<>=+|-]{7} would detect
1137 # line or a space and some text. Note that using [<>=+|-]{7} would detect
1139 # `<><><><><` as a conflict marker, which we don't want.
1138 # `<><><><><` as a conflict marker, which we don't want.
1140 return bool(
1139 return bool(
1141 re.search(
1140 re.search(
1142 br"^([<>=+|-])\1{6}( .*)$",
1141 br"^([<>=+|-])\1{6}( .*)$",
1143 data,
1142 data,
1144 re.MULTILINE,
1143 re.MULTILINE,
1145 )
1144 )
1146 )
1145 )
1147
1146
1148
1147
1149 def _check(repo, r, ui, tool, fcd, backup):
1148 def _check(repo, r, ui, tool, fcd, backup):
1150 fd = fcd.path()
1149 fd = fcd.path()
1151 uipathfn = scmutil.getuipathfn(repo)
1150 uipathfn = scmutil.getuipathfn(repo)
1152
1151
1153 if not r and (
1152 if not r and (
1154 _toolbool(ui, tool, b"checkconflicts")
1153 _toolbool(ui, tool, b"checkconflicts")
1155 or b'conflicts' in _toollist(ui, tool, b"check")
1154 or b'conflicts' in _toollist(ui, tool, b"check")
1156 ):
1155 ):
1157 if hasconflictmarkers(fcd.data()):
1156 if hasconflictmarkers(fcd.data()):
1158 r = 1
1157 r = 1
1159
1158
1160 checked = False
1159 checked = False
1161 if b'prompt' in _toollist(ui, tool, b"check"):
1160 if b'prompt' in _toollist(ui, tool, b"check"):
1162 checked = True
1161 checked = True
1163 if ui.promptchoice(
1162 if ui.promptchoice(
1164 _(b"was merge of '%s' successful (yn)?$$ &Yes $$ &No")
1163 _(b"was merge of '%s' successful (yn)?$$ &Yes $$ &No")
1165 % uipathfn(fd),
1164 % uipathfn(fd),
1166 1,
1165 1,
1167 ):
1166 ):
1168 r = 1
1167 r = 1
1169
1168
1170 if (
1169 if (
1171 not r
1170 not r
1172 and not checked
1171 and not checked
1173 and (
1172 and (
1174 _toolbool(ui, tool, b"checkchanged")
1173 _toolbool(ui, tool, b"checkchanged")
1175 or b'changed' in _toollist(ui, tool, b"check")
1174 or b'changed' in _toollist(ui, tool, b"check")
1176 )
1175 )
1177 ):
1176 ):
1178 if backup is not None and not fcd.cmp(backup):
1177 if backup is not None and not fcd.cmp(backup):
1179 if ui.promptchoice(
1178 if ui.promptchoice(
1180 _(
1179 _(
1181 b" output file %s appears unchanged\n"
1180 b" output file %s appears unchanged\n"
1182 b"was merge successful (yn)?"
1181 b"was merge successful (yn)?"
1183 b"$$ &Yes $$ &No"
1182 b"$$ &Yes $$ &No"
1184 )
1183 )
1185 % uipathfn(fd),
1184 % uipathfn(fd),
1186 1,
1185 1,
1187 ):
1186 ):
1188 r = 1
1187 r = 1
1189
1188
1190 if backup is not None and _toolbool(ui, tool, b"fixeol"):
1189 if backup is not None and _toolbool(ui, tool, b"fixeol"):
1191 _matcheol(_workingpath(repo, fcd), backup)
1190 _matcheol(_workingpath(repo, fcd), backup)
1192
1191
1193 return r
1192 return r
1194
1193
1195
1194
1196 def _workingpath(repo, ctx):
1195 def _workingpath(repo, ctx):
1197 return repo.wjoin(ctx.path())
1196 return repo.wjoin(ctx.path())
1198
1197
1199
1198
1200 def loadinternalmerge(ui, extname, registrarobj):
1199 def loadinternalmerge(ui, extname, registrarobj):
1201 """Load internal merge tool from specified registrarobj"""
1200 """Load internal merge tool from specified registrarobj"""
1202 for name, func in registrarobj._table.items():
1201 for name, func in registrarobj._table.items():
1203 fullname = b':' + name
1202 fullname = b':' + name
1204 internals[fullname] = func
1203 internals[fullname] = func
1205 internals[b'internal:' + name] = func
1204 internals[b'internal:' + name] = func
1206 internalsdoc[fullname] = func
1205 internalsdoc[fullname] = func
1207
1206
1208 capabilities = sorted([k for k, v in func.capabilities.items() if v])
1207 capabilities = sorted([k for k, v in func.capabilities.items() if v])
1209 if capabilities:
1208 if capabilities:
1210 capdesc = b" (actual capabilities: %s)" % b', '.join(
1209 capdesc = b" (actual capabilities: %s)" % b', '.join(
1211 capabilities
1210 capabilities
1212 )
1211 )
1213 func.__doc__ = func.__doc__ + pycompat.sysstr(b"\n\n%s" % capdesc)
1212 func.__doc__ = func.__doc__ + pycompat.sysstr(b"\n\n%s" % capdesc)
1214
1213
1215 # to put i18n comments into hg.pot for automatically generated texts
1214 # to put i18n comments into hg.pot for automatically generated texts
1216
1215
1217 # i18n: "binary" and "symlink" are keywords
1216 # i18n: "binary" and "symlink" are keywords
1218 # i18n: this text is added automatically
1217 # i18n: this text is added automatically
1219 _(b" (actual capabilities: binary, symlink)")
1218 _(b" (actual capabilities: binary, symlink)")
1220 # i18n: "binary" is keyword
1219 # i18n: "binary" is keyword
1221 # i18n: this text is added automatically
1220 # i18n: this text is added automatically
1222 _(b" (actual capabilities: binary)")
1221 _(b" (actual capabilities: binary)")
1223 # i18n: "symlink" is keyword
1222 # i18n: "symlink" is keyword
1224 # i18n: this text is added automatically
1223 # i18n: this text is added automatically
1225 _(b" (actual capabilities: symlink)")
1224 _(b" (actual capabilities: symlink)")
1226
1225
1227
1226
1228 # load built-in merge tools explicitly to setup internalsdoc
1227 # load built-in merge tools explicitly to setup internalsdoc
1229 loadinternalmerge(None, None, internaltool)
1228 loadinternalmerge(None, None, internaltool)
1230
1229
1231 # tell hggettext to extract docstrings from these functions:
1230 # tell hggettext to extract docstrings from these functions:
1232 i18nfunctions = internals.values()
1231 i18nfunctions = internals.values()
@@ -1,819 +1,819 b''
1 #require serve no-reposimplestore no-chg
1 #require serve no-reposimplestore no-chg
2
2
3 #testcases stream-legacy stream-bundle2
3 #testcases stream-legacy stream-bundle2
4
4
5 #if stream-legacy
5 #if stream-legacy
6 $ cat << EOF >> $HGRCPATH
6 $ cat << EOF >> $HGRCPATH
7 > [server]
7 > [server]
8 > bundle2.stream = no
8 > bundle2.stream = no
9 > EOF
9 > EOF
10 #endif
10 #endif
11
11
12 Initialize repository
12 Initialize repository
13
13
14 $ hg init server
14 $ hg init server
15 $ cd server
15 $ cd server
16 $ sh $TESTDIR/testlib/stream_clone_setup.sh
16 $ sh $TESTDIR/testlib/stream_clone_setup.sh
17 adding 00changelog-ab349180a0405010.nd
17 adding 00changelog-ab349180a0405010.nd
18 adding 00changelog.d
18 adding 00changelog.d
19 adding 00changelog.i
19 adding 00changelog.i
20 adding 00changelog.n
20 adding 00changelog.n
21 adding 00manifest.d
21 adding 00manifest.d
22 adding 00manifest.i
22 adding 00manifest.i
23 adding container/isam-build-centos7/bazel-coverage-generator-sandboxfs-compatibility-0758e3e4f6057904d44399bd666faba9e7f40686.patch
23 adding container/isam-build-centos7/bazel-coverage-generator-sandboxfs-compatibility-0758e3e4f6057904d44399bd666faba9e7f40686.patch
24 adding data/foo.d
24 adding data/foo.d
25 adding data/foo.i
25 adding data/foo.i
26 adding data/foo.n
26 adding data/foo.n
27 adding data/undo.babar
27 adding data/undo.babar
28 adding data/undo.d
28 adding data/undo.d
29 adding data/undo.foo.d
29 adding data/undo.foo.d
30 adding data/undo.foo.i
30 adding data/undo.foo.i
31 adding data/undo.foo.n
31 adding data/undo.foo.n
32 adding data/undo.i
32 adding data/undo.i
33 adding data/undo.n
33 adding data/undo.n
34 adding data/undo.py
34 adding data/undo.py
35 adding foo.d
35 adding foo.d
36 adding foo.i
36 adding foo.i
37 adding foo.n
37 adding foo.n
38 adding meta/foo.d
38 adding meta/foo.d
39 adding meta/foo.i
39 adding meta/foo.i
40 adding meta/foo.n
40 adding meta/foo.n
41 adding meta/undo.babar
41 adding meta/undo.babar
42 adding meta/undo.d
42 adding meta/undo.d
43 adding meta/undo.foo.d
43 adding meta/undo.foo.d
44 adding meta/undo.foo.i
44 adding meta/undo.foo.i
45 adding meta/undo.foo.n
45 adding meta/undo.foo.n
46 adding meta/undo.i
46 adding meta/undo.i
47 adding meta/undo.n
47 adding meta/undo.n
48 adding meta/undo.py
48 adding meta/undo.py
49 adding savanah/foo.d
49 adding savanah/foo.d
50 adding savanah/foo.i
50 adding savanah/foo.i
51 adding savanah/foo.n
51 adding savanah/foo.n
52 adding savanah/undo.babar
52 adding savanah/undo.babar
53 adding savanah/undo.d
53 adding savanah/undo.d
54 adding savanah/undo.foo.d
54 adding savanah/undo.foo.d
55 adding savanah/undo.foo.i
55 adding savanah/undo.foo.i
56 adding savanah/undo.foo.n
56 adding savanah/undo.foo.n
57 adding savanah/undo.i
57 adding savanah/undo.i
58 adding savanah/undo.n
58 adding savanah/undo.n
59 adding savanah/undo.py
59 adding savanah/undo.py
60 adding store/C\xc3\xa9lesteVille_is_a_Capital_City (esc)
60 adding store/C\xc3\xa9lesteVille_is_a_Capital_City (esc)
61 adding store/foo.d
61 adding store/foo.d
62 adding store/foo.i
62 adding store/foo.i
63 adding store/foo.n
63 adding store/foo.n
64 adding store/undo.babar
64 adding store/undo.babar
65 adding store/undo.d
65 adding store/undo.d
66 adding store/undo.foo.d
66 adding store/undo.foo.d
67 adding store/undo.foo.i
67 adding store/undo.foo.i
68 adding store/undo.foo.n
68 adding store/undo.foo.n
69 adding store/undo.i
69 adding store/undo.i
70 adding store/undo.n
70 adding store/undo.n
71 adding store/undo.py
71 adding store/undo.py
72 adding undo.babar
72 adding undo.babar
73 adding undo.d
73 adding undo.d
74 adding undo.foo.d
74 adding undo.foo.d
75 adding undo.foo.i
75 adding undo.foo.i
76 adding undo.foo.n
76 adding undo.foo.n
77 adding undo.i
77 adding undo.i
78 adding undo.n
78 adding undo.n
79 adding undo.py
79 adding undo.py
80
80
81 $ hg --config server.uncompressed=false serve -p $HGPORT -d --pid-file=hg.pid
81 $ hg --config server.uncompressed=false serve -p $HGPORT -d --pid-file=hg.pid
82 $ cat hg.pid > $DAEMON_PIDS
82 $ cat hg.pid > $DAEMON_PIDS
83 $ cd ..
83 $ cd ..
84
84
85 Check local clone
85 Check local clone
86 ==================
86 ==================
87
87
88 The logic is close enough of uncompressed.
88 The logic is close enough of uncompressed.
89 This is present here to reuse the testing around file with "special" names.
89 This is present here to reuse the testing around file with "special" names.
90
90
91 $ hg clone server local-clone
91 $ hg clone server local-clone
92 updating to branch default
92 updating to branch default
93 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
94
94
95 Check that the clone went well
95 Check that the clone went well
96
96
97 $ hg verify -R local-clone
97 $ hg verify -R local-clone
98 checking changesets
98 checking changesets
99 checking manifests
99 checking manifests
100 crosschecking files in changesets and manifests
100 crosschecking files in changesets and manifests
101 checking files
101 checking files
102 checked 3 changesets with 1088 changes to 1088 files
102 checked 3 changesets with 1088 changes to 1088 files
103
103
104 Check uncompressed
104 Check uncompressed
105 ==================
105 ==================
106
106
107 Cannot stream clone when server.uncompressed is set
107 Cannot stream clone when server.uncompressed is set
108
108
109 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out'
109 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out'
110 200 Script output follows
110 200 Script output follows
111
111
112 1
112 1
113
113
114 #if stream-legacy
114 #if stream-legacy
115 $ hg debugcapabilities http://localhost:$HGPORT
115 $ hg debugcapabilities http://localhost:$HGPORT
116 Main capabilities:
116 Main capabilities:
117 batch
117 batch
118 branchmap
118 branchmap
119 $USUAL_BUNDLE2_CAPS_SERVER$
119 $USUAL_BUNDLE2_CAPS_SERVER$
120 changegroupsubset
120 changegroupsubset
121 compression=$BUNDLE2_COMPRESSIONS$
121 compression=$BUNDLE2_COMPRESSIONS$
122 getbundle
122 getbundle
123 httpheader=1024
123 httpheader=1024
124 httpmediatype=0.1rx,0.1tx,0.2tx
124 httpmediatype=0.1rx,0.1tx,0.2tx
125 known
125 known
126 lookup
126 lookup
127 pushkey
127 pushkey
128 unbundle=HG10GZ,HG10BZ,HG10UN
128 unbundle=HG10GZ,HG10BZ,HG10UN
129 unbundlehash
129 unbundlehash
130 Bundle2 capabilities:
130 Bundle2 capabilities:
131 HG20
131 HG20
132 bookmarks
132 bookmarks
133 changegroup
133 changegroup
134 01
134 01
135 02
135 02
136 checkheads
136 checkheads
137 related
137 related
138 digests
138 digests
139 md5
139 md5
140 sha1
140 sha1
141 sha512
141 sha512
142 error
142 error
143 abort
143 abort
144 unsupportedcontent
144 unsupportedcontent
145 pushraced
145 pushraced
146 pushkey
146 pushkey
147 hgtagsfnodes
147 hgtagsfnodes
148 listkeys
148 listkeys
149 phases
149 phases
150 heads
150 heads
151 pushkey
151 pushkey
152 remote-changegroup
152 remote-changegroup
153 http
153 http
154 https
154 https
155
155
156 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
156 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
157 warning: stream clone requested but server has them disabled
157 warning: stream clone requested but server has them disabled
158 requesting all changes
158 requesting all changes
159 adding changesets
159 adding changesets
160 adding manifests
160 adding manifests
161 adding file changes
161 adding file changes
162 added 3 changesets with 1088 changes to 1088 files
162 added 3 changesets with 1088 changes to 1088 files
163 new changesets 96ee1d7354c4:5223b5e3265f
163 new changesets 96ee1d7354c4:5223b5e3265f
164
164
165 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
165 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
166 200 Script output follows
166 200 Script output follows
167 content-type: application/mercurial-0.2
167 content-type: application/mercurial-0.2
168
168
169
169
170 $ f --size body --hexdump --bytes 100
170 $ f --size body --hexdump --bytes 100
171 body: size=232
171 body: size=232
172 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
172 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
173 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
173 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
174 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
174 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
175 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
175 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
176 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
176 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
177 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
177 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
178 0060: 69 73 20 66 |is f|
178 0060: 69 73 20 66 |is f|
179
179
180 #endif
180 #endif
181 #if stream-bundle2
181 #if stream-bundle2
182 $ hg debugcapabilities http://localhost:$HGPORT
182 $ hg debugcapabilities http://localhost:$HGPORT
183 Main capabilities:
183 Main capabilities:
184 batch
184 batch
185 branchmap
185 branchmap
186 $USUAL_BUNDLE2_CAPS_SERVER$
186 $USUAL_BUNDLE2_CAPS_SERVER$
187 changegroupsubset
187 changegroupsubset
188 compression=$BUNDLE2_COMPRESSIONS$
188 compression=$BUNDLE2_COMPRESSIONS$
189 getbundle
189 getbundle
190 httpheader=1024
190 httpheader=1024
191 httpmediatype=0.1rx,0.1tx,0.2tx
191 httpmediatype=0.1rx,0.1tx,0.2tx
192 known
192 known
193 lookup
193 lookup
194 pushkey
194 pushkey
195 unbundle=HG10GZ,HG10BZ,HG10UN
195 unbundle=HG10GZ,HG10BZ,HG10UN
196 unbundlehash
196 unbundlehash
197 Bundle2 capabilities:
197 Bundle2 capabilities:
198 HG20
198 HG20
199 bookmarks
199 bookmarks
200 changegroup
200 changegroup
201 01
201 01
202 02
202 02
203 checkheads
203 checkheads
204 related
204 related
205 digests
205 digests
206 md5
206 md5
207 sha1
207 sha1
208 sha512
208 sha512
209 error
209 error
210 abort
210 abort
211 unsupportedcontent
211 unsupportedcontent
212 pushraced
212 pushraced
213 pushkey
213 pushkey
214 hgtagsfnodes
214 hgtagsfnodes
215 listkeys
215 listkeys
216 phases
216 phases
217 heads
217 heads
218 pushkey
218 pushkey
219 remote-changegroup
219 remote-changegroup
220 http
220 http
221 https
221 https
222
222
223 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
223 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
224 warning: stream clone requested but server has them disabled
224 warning: stream clone requested but server has them disabled
225 requesting all changes
225 requesting all changes
226 adding changesets
226 adding changesets
227 adding manifests
227 adding manifests
228 adding file changes
228 adding file changes
229 added 3 changesets with 1088 changes to 1088 files
229 added 3 changesets with 1088 changes to 1088 files
230 new changesets 96ee1d7354c4:5223b5e3265f
230 new changesets 96ee1d7354c4:5223b5e3265f
231
231
232 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
232 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
233 200 Script output follows
233 200 Script output follows
234 content-type: application/mercurial-0.2
234 content-type: application/mercurial-0.2
235
235
236
236
237 $ f --size body --hexdump --bytes 100
237 $ f --size body --hexdump --bytes 100
238 body: size=232
238 body: size=232
239 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
239 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
240 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
240 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
241 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
241 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
242 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
242 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
243 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
243 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
244 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
244 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
245 0060: 69 73 20 66 |is f|
245 0060: 69 73 20 66 |is f|
246
246
247 #endif
247 #endif
248
248
249 $ killdaemons.py
249 $ killdaemons.py
250 $ cd server
250 $ cd server
251 $ hg serve -p $HGPORT -d --pid-file=hg.pid --error errors.txt
251 $ hg serve -p $HGPORT -d --pid-file=hg.pid --error errors.txt
252 $ cat hg.pid > $DAEMON_PIDS
252 $ cat hg.pid > $DAEMON_PIDS
253 $ cd ..
253 $ cd ..
254
254
255 Basic clone
255 Basic clone
256
256
257 #if stream-legacy
257 #if stream-legacy
258 $ hg clone --stream -U http://localhost:$HGPORT clone1
258 $ hg clone --stream -U http://localhost:$HGPORT clone1
259 streaming all changes
259 streaming all changes
260 1090 files to transfer, 102 KB of data (no-zstd !)
260 1090 files to transfer, 102 KB of data (no-zstd !)
261 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
261 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
262 1090 files to transfer, 98.8 KB of data (zstd !)
262 1090 files to transfer, 98.8 KB of data (zstd !)
263 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
263 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
264 searching for changes
264 searching for changes
265 no changes found
265 no changes found
266 $ cat server/errors.txt
266 $ cat server/errors.txt
267 #endif
267 #endif
268 #if stream-bundle2
268 #if stream-bundle2
269 $ hg clone --stream -U http://localhost:$HGPORT clone1
269 $ hg clone --stream -U http://localhost:$HGPORT clone1
270 streaming all changes
270 streaming all changes
271 1093 files to transfer, 102 KB of data (no-zstd !)
271 1093 files to transfer, 102 KB of data (no-zstd !)
272 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
272 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
273 1093 files to transfer, 98.9 KB of data (zstd !)
273 1093 files to transfer, 98.9 KB of data (zstd !)
274 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
274 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
275
275
276 $ ls -1 clone1/.hg/cache
276 $ ls -1 clone1/.hg/cache
277 branch2-base
277 branch2-base
278 branch2-immutable
278 branch2-immutable
279 branch2-served
279 branch2-served
280 branch2-served.hidden
280 branch2-served.hidden
281 branch2-visible
281 branch2-visible
282 branch2-visible-hidden
282 branch2-visible-hidden
283 rbc-names-v1
283 rbc-names-v1
284 rbc-revs-v1
284 rbc-revs-v1
285 tags2
285 tags2
286 tags2-served
286 tags2-served
287 $ cat server/errors.txt
287 $ cat server/errors.txt
288 #endif
288 #endif
289
289
290 getbundle requests with stream=1 are uncompressed
290 getbundle requests with stream=1 are uncompressed
291
291
292 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto '0.1 0.2 comp=zlib,none' --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
292 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto '0.1 0.2 comp=zlib,none' --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
293 200 Script output follows
293 200 Script output follows
294 content-type: application/mercurial-0.2
294 content-type: application/mercurial-0.2
295
295
296
296
297 #if no-zstd no-rust
297 #if no-zstd no-rust
298 $ f --size --hex --bytes 256 body
298 $ f --size --hex --bytes 256 body
299 body: size=119123
299 body: size=119123
300 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
300 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
301 0010: 62 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |b.STREAM2.......|
301 0010: 62 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |b.STREAM2.......|
302 0020: 06 09 04 0c 26 62 79 74 65 63 6f 75 6e 74 31 30 |....&bytecount10|
302 0020: 06 09 04 0c 26 62 79 74 65 63 6f 75 6e 74 31 30 |....&bytecount10|
303 0030: 34 31 31 35 66 69 6c 65 63 6f 75 6e 74 31 30 39 |4115filecount109|
303 0030: 34 31 31 35 66 69 6c 65 63 6f 75 6e 74 31 30 39 |4115filecount109|
304 0040: 33 72 65 71 75 69 72 65 6d 65 6e 74 73 67 65 6e |3requirementsgen|
304 0040: 33 72 65 71 75 69 72 65 6d 65 6e 74 73 67 65 6e |3requirementsgen|
305 0050: 65 72 61 6c 64 65 6c 74 61 25 32 43 72 65 76 6c |eraldelta%2Crevl|
305 0050: 65 72 61 6c 64 65 6c 74 61 25 32 43 72 65 76 6c |eraldelta%2Crevl|
306 0060: 6f 67 76 31 25 32 43 73 70 61 72 73 65 72 65 76 |ogv1%2Csparserev|
306 0060: 6f 67 76 31 25 32 43 73 70 61 72 73 65 72 65 76 |ogv1%2Csparserev|
307 0070: 6c 6f 67 00 00 80 00 73 08 42 64 61 74 61 2f 30 |log....s.Bdata/0|
307 0070: 6c 6f 67 00 00 80 00 73 08 42 64 61 74 61 2f 30 |log....s.Bdata/0|
308 0080: 2e 69 00 03 00 01 00 00 00 00 00 00 00 02 00 00 |.i..............|
308 0080: 2e 69 00 03 00 01 00 00 00 00 00 00 00 02 00 00 |.i..............|
309 0090: 00 01 00 00 00 00 00 00 00 01 ff ff ff ff ff ff |................|
309 0090: 00 01 00 00 00 00 00 00 00 01 ff ff ff ff ff ff |................|
310 00a0: ff ff 80 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 |...)c.I.#....Vg.|
310 00a0: ff ff 80 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 |...)c.I.#....Vg.|
311 00b0: 67 2c 69 d1 ec 39 00 00 00 00 00 00 00 00 00 00 |g,i..9..........|
311 00b0: 67 2c 69 d1 ec 39 00 00 00 00 00 00 00 00 00 00 |g,i..9..........|
312 00c0: 00 00 75 30 73 26 45 64 61 74 61 2f 30 30 63 68 |..u0s&Edata/00ch|
312 00c0: 00 00 75 30 73 26 45 64 61 74 61 2f 30 30 63 68 |..u0s&Edata/00ch|
313 00d0: 61 6e 67 65 6c 6f 67 2d 61 62 33 34 39 31 38 30 |angelog-ab349180|
313 00d0: 61 6e 67 65 6c 6f 67 2d 61 62 33 34 39 31 38 30 |angelog-ab349180|
314 00e0: 61 30 34 30 35 30 31 30 2e 6e 64 2e 69 00 03 00 |a0405010.nd.i...|
314 00e0: 61 30 34 30 35 30 31 30 2e 6e 64 2e 69 00 03 00 |a0405010.nd.i...|
315 00f0: 01 00 00 00 00 00 00 00 05 00 00 00 04 00 00 00 |................|
315 00f0: 01 00 00 00 00 00 00 00 05 00 00 00 04 00 00 00 |................|
316 #endif
316 #endif
317 #if zstd no-rust
317 #if zstd no-rust
318 $ f --size --hex --bytes 256 body
318 $ f --size --hex --bytes 256 body
319 body: size=116310
319 body: size=116310 (no-bigendian !)
320 body: size=116335 (bigendian !)
320 body: size=116305 (bigendian !)
321 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
321 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
322 0010: 7c 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 ||.STREAM2.......|
322 0010: 7c 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 ||.STREAM2.......|
323 0020: 06 09 04 0c 40 62 79 74 65 63 6f 75 6e 74 31 30 |....@bytecount10|
323 0020: 06 09 04 0c 40 62 79 74 65 63 6f 75 6e 74 31 30 |....@bytecount10|
324 0030: 31 32 37 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |1276filecount109| (no-bigendian !)
324 0030: 31 32 37 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |1276filecount109| (no-bigendian !)
325 0030: 31 32 37 31 66 69 6c 65 63 6f 75 6e 74 31 30 39 |1271filecount109| (bigendian !)
325 0030: 31 32 37 31 66 69 6c 65 63 6f 75 6e 74 31 30 39 |1271filecount109| (bigendian !)
326 0040: 33 72 65 71 75 69 72 65 6d 65 6e 74 73 67 65 6e |3requirementsgen|
326 0040: 33 72 65 71 75 69 72 65 6d 65 6e 74 73 67 65 6e |3requirementsgen|
327 0050: 65 72 61 6c 64 65 6c 74 61 25 32 43 72 65 76 6c |eraldelta%2Crevl|
327 0050: 65 72 61 6c 64 65 6c 74 61 25 32 43 72 65 76 6c |eraldelta%2Crevl|
328 0060: 6f 67 2d 63 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a |og-compression-z|
328 0060: 6f 67 2d 63 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a |og-compression-z|
329 0070: 73 74 64 25 32 43 72 65 76 6c 6f 67 76 31 25 32 |std%2Crevlogv1%2|
329 0070: 73 74 64 25 32 43 72 65 76 6c 6f 67 76 31 25 32 |std%2Crevlogv1%2|
330 0080: 43 73 70 61 72 73 65 72 65 76 6c 6f 67 00 00 80 |Csparserevlog...|
330 0080: 43 73 70 61 72 73 65 72 65 76 6c 6f 67 00 00 80 |Csparserevlog...|
331 0090: 00 73 08 42 64 61 74 61 2f 30 2e 69 00 03 00 01 |.s.Bdata/0.i....|
331 0090: 00 73 08 42 64 61 74 61 2f 30 2e 69 00 03 00 01 |.s.Bdata/0.i....|
332 00a0: 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 |................|
332 00a0: 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 |................|
333 00b0: 00 00 00 01 ff ff ff ff ff ff ff ff 80 29 63 a0 |.............)c.|
333 00b0: 00 00 00 01 ff ff ff ff ff ff ff ff 80 29 63 a0 |.............)c.|
334 00c0: 49 d3 23 87 bf ce fe 56 67 92 67 2c 69 d1 ec 39 |I.#....Vg.g,i..9|
334 00c0: 49 d3 23 87 bf ce fe 56 67 92 67 2c 69 d1 ec 39 |I.#....Vg.g,i..9|
335 00d0: 00 00 00 00 00 00 00 00 00 00 00 00 75 30 73 26 |............u0s&|
335 00d0: 00 00 00 00 00 00 00 00 00 00 00 00 75 30 73 26 |............u0s&|
336 00e0: 45 64 61 74 61 2f 30 30 63 68 61 6e 67 65 6c 6f |Edata/00changelo|
336 00e0: 45 64 61 74 61 2f 30 30 63 68 61 6e 67 65 6c 6f |Edata/00changelo|
337 00f0: 67 2d 61 62 33 34 39 31 38 30 61 30 34 30 35 30 |g-ab349180a04050|
337 00f0: 67 2d 61 62 33 34 39 31 38 30 61 30 34 30 35 30 |g-ab349180a04050|
338 #endif
338 #endif
339 #if zstd rust no-dirstate-v2
339 #if zstd rust no-dirstate-v2
340 $ f --size --hex --bytes 256 body
340 $ f --size --hex --bytes 256 body
341 body: size=116310
341 body: size=116310
342 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
342 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
343 0010: 7c 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 ||.STREAM2.......|
343 0010: 7c 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 ||.STREAM2.......|
344 0020: 06 09 04 0c 40 62 79 74 65 63 6f 75 6e 74 31 30 |....@bytecount10|
344 0020: 06 09 04 0c 40 62 79 74 65 63 6f 75 6e 74 31 30 |....@bytecount10|
345 0030: 31 32 37 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |1276filecount109|
345 0030: 31 32 37 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |1276filecount109|
346 0040: 33 72 65 71 75 69 72 65 6d 65 6e 74 73 67 65 6e |3requirementsgen|
346 0040: 33 72 65 71 75 69 72 65 6d 65 6e 74 73 67 65 6e |3requirementsgen|
347 0050: 65 72 61 6c 64 65 6c 74 61 25 32 43 72 65 76 6c |eraldelta%2Crevl|
347 0050: 65 72 61 6c 64 65 6c 74 61 25 32 43 72 65 76 6c |eraldelta%2Crevl|
348 0060: 6f 67 2d 63 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a |og-compression-z|
348 0060: 6f 67 2d 63 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a |og-compression-z|
349 0070: 73 74 64 25 32 43 72 65 76 6c 6f 67 76 31 25 32 |std%2Crevlogv1%2|
349 0070: 73 74 64 25 32 43 72 65 76 6c 6f 67 76 31 25 32 |std%2Crevlogv1%2|
350 0080: 43 73 70 61 72 73 65 72 65 76 6c 6f 67 00 00 80 |Csparserevlog...|
350 0080: 43 73 70 61 72 73 65 72 65 76 6c 6f 67 00 00 80 |Csparserevlog...|
351 0090: 00 73 08 42 64 61 74 61 2f 30 2e 69 00 03 00 01 |.s.Bdata/0.i....|
351 0090: 00 73 08 42 64 61 74 61 2f 30 2e 69 00 03 00 01 |.s.Bdata/0.i....|
352 00a0: 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 |................|
352 00a0: 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 |................|
353 00b0: 00 00 00 01 ff ff ff ff ff ff ff ff 80 29 63 a0 |.............)c.|
353 00b0: 00 00 00 01 ff ff ff ff ff ff ff ff 80 29 63 a0 |.............)c.|
354 00c0: 49 d3 23 87 bf ce fe 56 67 92 67 2c 69 d1 ec 39 |I.#....Vg.g,i..9|
354 00c0: 49 d3 23 87 bf ce fe 56 67 92 67 2c 69 d1 ec 39 |I.#....Vg.g,i..9|
355 00d0: 00 00 00 00 00 00 00 00 00 00 00 00 75 30 73 26 |............u0s&|
355 00d0: 00 00 00 00 00 00 00 00 00 00 00 00 75 30 73 26 |............u0s&|
356 00e0: 45 64 61 74 61 2f 30 30 63 68 61 6e 67 65 6c 6f |Edata/00changelo|
356 00e0: 45 64 61 74 61 2f 30 30 63 68 61 6e 67 65 6c 6f |Edata/00changelo|
357 00f0: 67 2d 61 62 33 34 39 31 38 30 61 30 34 30 35 30 |g-ab349180a04050|
357 00f0: 67 2d 61 62 33 34 39 31 38 30 61 30 34 30 35 30 |g-ab349180a04050|
358 #endif
358 #endif
359 #if zstd dirstate-v2
359 #if zstd dirstate-v2
360 $ f --size --hex --bytes 256 body
360 $ f --size --hex --bytes 256 body
361 body: size=109549
361 body: size=109549
362 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
362 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
363 0010: c0 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
363 0010: c0 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
364 0020: 05 09 04 0c 85 62 79 74 65 63 6f 75 6e 74 39 35 |.....bytecount95|
364 0020: 05 09 04 0c 85 62 79 74 65 63 6f 75 6e 74 39 35 |.....bytecount95|
365 0030: 38 39 37 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |897filecount1030|
365 0030: 38 39 37 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |897filecount1030|
366 0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 65 |requirementsdote|
366 0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 65 |requirementsdote|
367 0050: 6e 63 6f 64 65 25 32 43 65 78 70 2d 64 69 72 73 |ncode%2Cexp-dirs|
367 0050: 6e 63 6f 64 65 25 32 43 65 78 70 2d 64 69 72 73 |ncode%2Cexp-dirs|
368 0060: 74 61 74 65 2d 76 32 25 32 43 66 6e 63 61 63 68 |tate-v2%2Cfncach|
368 0060: 74 61 74 65 2d 76 32 25 32 43 66 6e 63 61 63 68 |tate-v2%2Cfncach|
369 0070: 65 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 |e%2Cgeneraldelta|
369 0070: 65 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 |e%2Cgeneraldelta|
370 0080: 25 32 43 70 65 72 73 69 73 74 65 6e 74 2d 6e 6f |%2Cpersistent-no|
370 0080: 25 32 43 70 65 72 73 69 73 74 65 6e 74 2d 6e 6f |%2Cpersistent-no|
371 0090: 64 65 6d 61 70 25 32 43 72 65 76 6c 6f 67 2d 63 |demap%2Crevlog-c|
371 0090: 64 65 6d 61 70 25 32 43 72 65 76 6c 6f 67 2d 63 |demap%2Crevlog-c|
372 00a0: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 25 |ompression-zstd%|
372 00a0: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 25 |ompression-zstd%|
373 00b0: 32 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 |2Crevlogv1%2Cspa|
373 00b0: 32 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 |2Crevlogv1%2Cspa|
374 00c0: 72 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 |rserevlog%2Cstor|
374 00c0: 72 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 |rserevlog%2Cstor|
375 00d0: 65 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |e....s.Bdata/0.i|
375 00d0: 65 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |e....s.Bdata/0.i|
376 00e0: 00 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |................|
376 00e0: 00 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |................|
377 00f0: 00 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |................|
377 00f0: 00 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |................|
378 #endif
378 #endif
379
379
380 --uncompressed is an alias to --stream
380 --uncompressed is an alias to --stream
381
381
382 #if stream-legacy
382 #if stream-legacy
383 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
383 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
384 streaming all changes
384 streaming all changes
385 1090 files to transfer, 102 KB of data (no-zstd !)
385 1090 files to transfer, 102 KB of data (no-zstd !)
386 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
386 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
387 1090 files to transfer, 98.8 KB of data (zstd !)
387 1090 files to transfer, 98.8 KB of data (zstd !)
388 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
388 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
389 searching for changes
389 searching for changes
390 no changes found
390 no changes found
391 #endif
391 #endif
392 #if stream-bundle2
392 #if stream-bundle2
393 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
393 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
394 streaming all changes
394 streaming all changes
395 1093 files to transfer, 102 KB of data (no-zstd !)
395 1093 files to transfer, 102 KB of data (no-zstd !)
396 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
396 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
397 1093 files to transfer, 98.9 KB of data (zstd !)
397 1093 files to transfer, 98.9 KB of data (zstd !)
398 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
398 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
399 #endif
399 #endif
400
400
401 Clone with background file closing enabled
401 Clone with background file closing enabled
402
402
403 #if stream-legacy
403 #if stream-legacy
404 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
404 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
405 using http://localhost:$HGPORT/
405 using http://localhost:$HGPORT/
406 sending capabilities command
406 sending capabilities command
407 sending branchmap command
407 sending branchmap command
408 streaming all changes
408 streaming all changes
409 sending stream_out command
409 sending stream_out command
410 1090 files to transfer, 102 KB of data (no-zstd !)
410 1090 files to transfer, 102 KB of data (no-zstd !)
411 1090 files to transfer, 98.8 KB of data (zstd !)
411 1090 files to transfer, 98.8 KB of data (zstd !)
412 starting 4 threads for background file closing
412 starting 4 threads for background file closing
413 updating the branch cache
413 updating the branch cache
414 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
414 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
415 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
415 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
416 query 1; heads
416 query 1; heads
417 sending batch command
417 sending batch command
418 searching for changes
418 searching for changes
419 all remote heads known locally
419 all remote heads known locally
420 no changes found
420 no changes found
421 sending getbundle command
421 sending getbundle command
422 bundle2-input-bundle: with-transaction
422 bundle2-input-bundle: with-transaction
423 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
423 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
424 bundle2-input-part: "phase-heads" supported
424 bundle2-input-part: "phase-heads" supported
425 bundle2-input-part: total payload size 24
425 bundle2-input-part: total payload size 24
426 bundle2-input-bundle: 2 parts total
426 bundle2-input-bundle: 2 parts total
427 checking for updated bookmarks
427 checking for updated bookmarks
428 updating the branch cache
428 updating the branch cache
429 (sent 5 HTTP requests and * bytes; received * bytes in responses) (glob)
429 (sent 5 HTTP requests and * bytes; received * bytes in responses) (glob)
430 #endif
430 #endif
431 #if stream-bundle2
431 #if stream-bundle2
432 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
432 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
433 using http://localhost:$HGPORT/
433 using http://localhost:$HGPORT/
434 sending capabilities command
434 sending capabilities command
435 query 1; heads
435 query 1; heads
436 sending batch command
436 sending batch command
437 streaming all changes
437 streaming all changes
438 sending getbundle command
438 sending getbundle command
439 bundle2-input-bundle: with-transaction
439 bundle2-input-bundle: with-transaction
440 bundle2-input-part: "stream2" (params: 3 mandatory) supported
440 bundle2-input-part: "stream2" (params: 3 mandatory) supported
441 applying stream bundle
441 applying stream bundle
442 1093 files to transfer, 102 KB of data (no-zstd !)
442 1093 files to transfer, 102 KB of data (no-zstd !)
443 1093 files to transfer, 98.9 KB of data (zstd !)
443 1093 files to transfer, 98.9 KB of data (zstd !)
444 starting 4 threads for background file closing
444 starting 4 threads for background file closing
445 starting 4 threads for background file closing
445 starting 4 threads for background file closing
446 updating the branch cache
446 updating the branch cache
447 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
447 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
448 bundle2-input-part: total payload size 118984 (no-zstd !)
448 bundle2-input-part: total payload size 118984 (no-zstd !)
449 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
449 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
450 bundle2-input-part: total payload size 116145 (zstd no-bigendian !)
450 bundle2-input-part: total payload size 116145 (zstd no-bigendian !)
451 bundle2-input-part: total payload size 116140 (zstd bigendian !)
451 bundle2-input-part: total payload size 116140 (zstd bigendian !)
452 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
452 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
453 bundle2-input-bundle: 2 parts total
453 bundle2-input-bundle: 2 parts total
454 checking for updated bookmarks
454 checking for updated bookmarks
455 updating the branch cache
455 updating the branch cache
456 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
456 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
457 #endif
457 #endif
458
458
459 Cannot stream clone when there are secret changesets
459 Cannot stream clone when there are secret changesets
460
460
461 $ hg -R server phase --force --secret -r tip
461 $ hg -R server phase --force --secret -r tip
462 $ hg clone --stream -U http://localhost:$HGPORT secret-denied
462 $ hg clone --stream -U http://localhost:$HGPORT secret-denied
463 warning: stream clone requested but server has them disabled
463 warning: stream clone requested but server has them disabled
464 requesting all changes
464 requesting all changes
465 adding changesets
465 adding changesets
466 adding manifests
466 adding manifests
467 adding file changes
467 adding file changes
468 added 2 changesets with 1025 changes to 1025 files
468 added 2 changesets with 1025 changes to 1025 files
469 new changesets 96ee1d7354c4:c17445101a72
469 new changesets 96ee1d7354c4:c17445101a72
470
470
471 $ killdaemons.py
471 $ killdaemons.py
472
472
473 Streaming of secrets can be overridden by server config
473 Streaming of secrets can be overridden by server config
474
474
475 $ cd server
475 $ cd server
476 $ hg serve --config server.uncompressedallowsecret=true -p $HGPORT -d --pid-file=hg.pid
476 $ hg serve --config server.uncompressedallowsecret=true -p $HGPORT -d --pid-file=hg.pid
477 $ cat hg.pid > $DAEMON_PIDS
477 $ cat hg.pid > $DAEMON_PIDS
478 $ cd ..
478 $ cd ..
479
479
480 #if stream-legacy
480 #if stream-legacy
481 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
481 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
482 streaming all changes
482 streaming all changes
483 1090 files to transfer, 102 KB of data (no-zstd !)
483 1090 files to transfer, 102 KB of data (no-zstd !)
484 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
484 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
485 1090 files to transfer, 98.8 KB of data (zstd !)
485 1090 files to transfer, 98.8 KB of data (zstd !)
486 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
486 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
487 searching for changes
487 searching for changes
488 no changes found
488 no changes found
489 #endif
489 #endif
490 #if stream-bundle2
490 #if stream-bundle2
491 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
491 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
492 streaming all changes
492 streaming all changes
493 1093 files to transfer, 102 KB of data (no-zstd !)
493 1093 files to transfer, 102 KB of data (no-zstd !)
494 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
494 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
495 1093 files to transfer, 98.9 KB of data (zstd !)
495 1093 files to transfer, 98.9 KB of data (zstd !)
496 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
496 transferred 98.9 KB in * seconds (* */sec) (glob) (zstd !)
497 #endif
497 #endif
498
498
499 $ killdaemons.py
499 $ killdaemons.py
500
500
501 Verify interaction between preferuncompressed and secret presence
501 Verify interaction between preferuncompressed and secret presence
502
502
503 $ cd server
503 $ cd server
504 $ hg serve --config server.preferuncompressed=true -p $HGPORT -d --pid-file=hg.pid
504 $ hg serve --config server.preferuncompressed=true -p $HGPORT -d --pid-file=hg.pid
505 $ cat hg.pid > $DAEMON_PIDS
505 $ cat hg.pid > $DAEMON_PIDS
506 $ cd ..
506 $ cd ..
507
507
508 $ hg clone -U http://localhost:$HGPORT preferuncompressed-secret
508 $ hg clone -U http://localhost:$HGPORT preferuncompressed-secret
509 requesting all changes
509 requesting all changes
510 adding changesets
510 adding changesets
511 adding manifests
511 adding manifests
512 adding file changes
512 adding file changes
513 added 2 changesets with 1025 changes to 1025 files
513 added 2 changesets with 1025 changes to 1025 files
514 new changesets 96ee1d7354c4:c17445101a72
514 new changesets 96ee1d7354c4:c17445101a72
515
515
516 $ killdaemons.py
516 $ killdaemons.py
517
517
518 Clone not allowed when full bundles disabled and can't serve secrets
518 Clone not allowed when full bundles disabled and can't serve secrets
519
519
520 $ cd server
520 $ cd server
521 $ hg serve --config server.disablefullbundle=true -p $HGPORT -d --pid-file=hg.pid
521 $ hg serve --config server.disablefullbundle=true -p $HGPORT -d --pid-file=hg.pid
522 $ cat hg.pid > $DAEMON_PIDS
522 $ cat hg.pid > $DAEMON_PIDS
523 $ cd ..
523 $ cd ..
524
524
525 $ hg clone --stream http://localhost:$HGPORT secret-full-disabled
525 $ hg clone --stream http://localhost:$HGPORT secret-full-disabled
526 warning: stream clone requested but server has them disabled
526 warning: stream clone requested but server has them disabled
527 requesting all changes
527 requesting all changes
528 remote: abort: server has pull-based clones disabled
528 remote: abort: server has pull-based clones disabled
529 abort: pull failed on remote
529 abort: pull failed on remote
530 (remove --pull if specified or upgrade Mercurial)
530 (remove --pull if specified or upgrade Mercurial)
531 [100]
531 [100]
532
532
533 Local stream clone with secrets involved
533 Local stream clone with secrets involved
534 (This is just a test over behavior: if you have access to the repo's files,
534 (This is just a test over behavior: if you have access to the repo's files,
535 there is no security so it isn't important to prevent a clone here.)
535 there is no security so it isn't important to prevent a clone here.)
536
536
537 $ hg clone -U --stream server local-secret
537 $ hg clone -U --stream server local-secret
538 warning: stream clone requested but server has them disabled
538 warning: stream clone requested but server has them disabled
539 requesting all changes
539 requesting all changes
540 adding changesets
540 adding changesets
541 adding manifests
541 adding manifests
542 adding file changes
542 adding file changes
543 added 2 changesets with 1025 changes to 1025 files
543 added 2 changesets with 1025 changes to 1025 files
544 new changesets 96ee1d7354c4:c17445101a72
544 new changesets 96ee1d7354c4:c17445101a72
545
545
546 Stream clone while repo is changing:
546 Stream clone while repo is changing:
547
547
548 $ mkdir changing
548 $ mkdir changing
549 $ cd changing
549 $ cd changing
550
550
551 extension for delaying the server process so we reliably can modify the repo
551 extension for delaying the server process so we reliably can modify the repo
552 while cloning
552 while cloning
553
553
554 $ cat > stream_steps.py <<EOF
554 $ cat > stream_steps.py <<EOF
555 > import os
555 > import os
556 > import sys
556 > import sys
557 > from mercurial import (
557 > from mercurial import (
558 > encoding,
558 > encoding,
559 > extensions,
559 > extensions,
560 > streamclone,
560 > streamclone,
561 > testing,
561 > testing,
562 > )
562 > )
563 > WALKED_FILE_1 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_1']
563 > WALKED_FILE_1 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_1']
564 > WALKED_FILE_2 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_2']
564 > WALKED_FILE_2 = encoding.environ[b'HG_TEST_STREAM_WALKED_FILE_2']
565 >
565 >
566 > def _test_sync_point_walk_1(orig, repo):
566 > def _test_sync_point_walk_1(orig, repo):
567 > testing.write_file(WALKED_FILE_1)
567 > testing.write_file(WALKED_FILE_1)
568 >
568 >
569 > def _test_sync_point_walk_2(orig, repo):
569 > def _test_sync_point_walk_2(orig, repo):
570 > assert repo._currentlock(repo._lockref) is None
570 > assert repo._currentlock(repo._lockref) is None
571 > testing.wait_file(WALKED_FILE_2)
571 > testing.wait_file(WALKED_FILE_2)
572 >
572 >
573 > extensions.wrapfunction(
573 > extensions.wrapfunction(
574 > streamclone,
574 > streamclone,
575 > '_test_sync_point_walk_1',
575 > '_test_sync_point_walk_1',
576 > _test_sync_point_walk_1
576 > _test_sync_point_walk_1
577 > )
577 > )
578 > extensions.wrapfunction(
578 > extensions.wrapfunction(
579 > streamclone,
579 > streamclone,
580 > '_test_sync_point_walk_2',
580 > '_test_sync_point_walk_2',
581 > _test_sync_point_walk_2
581 > _test_sync_point_walk_2
582 > )
582 > )
583 > EOF
583 > EOF
584
584
585 prepare repo with small and big file to cover both code paths in emitrevlogdata
585 prepare repo with small and big file to cover both code paths in emitrevlogdata
586
586
587 $ hg init repo
587 $ hg init repo
588 $ touch repo/f1
588 $ touch repo/f1
589 $ $TESTDIR/seq.py 50000 > repo/f2
589 $ $TESTDIR/seq.py 50000 > repo/f2
590 $ hg -R repo ci -Aqm "0"
590 $ hg -R repo ci -Aqm "0"
591 $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1"
591 $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1"
592 $ export HG_TEST_STREAM_WALKED_FILE_1
592 $ export HG_TEST_STREAM_WALKED_FILE_1
593 $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2"
593 $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2"
594 $ export HG_TEST_STREAM_WALKED_FILE_2
594 $ export HG_TEST_STREAM_WALKED_FILE_2
595 $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3"
595 $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3"
596 $ export HG_TEST_STREAM_WALKED_FILE_3
596 $ export HG_TEST_STREAM_WALKED_FILE_3
597 # $ cat << EOF >> $HGRCPATH
597 # $ cat << EOF >> $HGRCPATH
598 # > [hooks]
598 # > [hooks]
599 # > pre-clone=rm -f "$TESTTMP/sync_file_walked_*"
599 # > pre-clone=rm -f "$TESTTMP/sync_file_walked_*"
600 # > EOF
600 # > EOF
601 $ hg serve -R repo -p $HGPORT1 -d --error errors.log --pid-file=hg.pid --config extensions.stream_steps="$RUNTESTDIR/testlib/ext-stream-clone-steps.py"
601 $ hg serve -R repo -p $HGPORT1 -d --error errors.log --pid-file=hg.pid --config extensions.stream_steps="$RUNTESTDIR/testlib/ext-stream-clone-steps.py"
602 $ cat hg.pid >> $DAEMON_PIDS
602 $ cat hg.pid >> $DAEMON_PIDS
603
603
604 clone while modifying the repo between stating file with write lock and
604 clone while modifying the repo between stating file with write lock and
605 actually serving file content
605 actually serving file content
606
606
607 $ (hg clone -q --stream -U http://localhost:$HGPORT1 clone; touch "$HG_TEST_STREAM_WALKED_FILE_3") &
607 $ (hg clone -q --stream -U http://localhost:$HGPORT1 clone; touch "$HG_TEST_STREAM_WALKED_FILE_3") &
608 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
608 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
609 $ echo >> repo/f1
609 $ echo >> repo/f1
610 $ echo >> repo/f2
610 $ echo >> repo/f2
611 $ hg -R repo ci -m "1" --config ui.timeout.warn=-1
611 $ hg -R repo ci -m "1" --config ui.timeout.warn=-1
612 $ touch $HG_TEST_STREAM_WALKED_FILE_2
612 $ touch $HG_TEST_STREAM_WALKED_FILE_2
613 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
613 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
614 $ hg -R clone id
614 $ hg -R clone id
615 000000000000
615 000000000000
616 $ cat errors.log
616 $ cat errors.log
617 $ cd ..
617 $ cd ..
618
618
619 Stream repository with bookmarks
619 Stream repository with bookmarks
620 --------------------------------
620 --------------------------------
621
621
622 (revert introduction of secret changeset)
622 (revert introduction of secret changeset)
623
623
624 $ hg -R server phase --draft 'secret()'
624 $ hg -R server phase --draft 'secret()'
625
625
626 add a bookmark
626 add a bookmark
627
627
628 $ hg -R server bookmark -r tip some-bookmark
628 $ hg -R server bookmark -r tip some-bookmark
629
629
630 clone it
630 clone it
631
631
632 #if stream-legacy
632 #if stream-legacy
633 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
633 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
634 streaming all changes
634 streaming all changes
635 1090 files to transfer, 102 KB of data (no-zstd !)
635 1090 files to transfer, 102 KB of data (no-zstd !)
636 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
636 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
637 1090 files to transfer, 98.8 KB of data (zstd !)
637 1090 files to transfer, 98.8 KB of data (zstd !)
638 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
638 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
639 searching for changes
639 searching for changes
640 no changes found
640 no changes found
641 updating to branch default
641 updating to branch default
642 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
642 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
643 #endif
643 #endif
644 #if stream-bundle2
644 #if stream-bundle2
645 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
645 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
646 streaming all changes
646 streaming all changes
647 1096 files to transfer, 102 KB of data (no-zstd !)
647 1096 files to transfer, 102 KB of data (no-zstd !)
648 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
648 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
649 1096 files to transfer, 99.1 KB of data (zstd !)
649 1096 files to transfer, 99.1 KB of data (zstd !)
650 transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !)
650 transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !)
651 updating to branch default
651 updating to branch default
652 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
652 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
653 #endif
653 #endif
654 $ hg verify -R with-bookmarks
654 $ hg verify -R with-bookmarks
655 checking changesets
655 checking changesets
656 checking manifests
656 checking manifests
657 crosschecking files in changesets and manifests
657 crosschecking files in changesets and manifests
658 checking files
658 checking files
659 checked 3 changesets with 1088 changes to 1088 files
659 checked 3 changesets with 1088 changes to 1088 files
660 $ hg -R with-bookmarks bookmarks
660 $ hg -R with-bookmarks bookmarks
661 some-bookmark 2:5223b5e3265f
661 some-bookmark 2:5223b5e3265f
662
662
663 Stream repository with phases
663 Stream repository with phases
664 -----------------------------
664 -----------------------------
665
665
666 Clone as publishing
666 Clone as publishing
667
667
668 $ hg -R server phase -r 'all()'
668 $ hg -R server phase -r 'all()'
669 0: draft
669 0: draft
670 1: draft
670 1: draft
671 2: draft
671 2: draft
672
672
673 #if stream-legacy
673 #if stream-legacy
674 $ hg clone --stream http://localhost:$HGPORT phase-publish
674 $ hg clone --stream http://localhost:$HGPORT phase-publish
675 streaming all changes
675 streaming all changes
676 1090 files to transfer, 102 KB of data (no-zstd !)
676 1090 files to transfer, 102 KB of data (no-zstd !)
677 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
677 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
678 1090 files to transfer, 98.8 KB of data (zstd !)
678 1090 files to transfer, 98.8 KB of data (zstd !)
679 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
679 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
680 searching for changes
680 searching for changes
681 no changes found
681 no changes found
682 updating to branch default
682 updating to branch default
683 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
683 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
684 #endif
684 #endif
685 #if stream-bundle2
685 #if stream-bundle2
686 $ hg clone --stream http://localhost:$HGPORT phase-publish
686 $ hg clone --stream http://localhost:$HGPORT phase-publish
687 streaming all changes
687 streaming all changes
688 1096 files to transfer, 102 KB of data (no-zstd !)
688 1096 files to transfer, 102 KB of data (no-zstd !)
689 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
689 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
690 1096 files to transfer, 99.1 KB of data (zstd !)
690 1096 files to transfer, 99.1 KB of data (zstd !)
691 transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !)
691 transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !)
692 updating to branch default
692 updating to branch default
693 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
693 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
694 #endif
694 #endif
695 $ hg verify -R phase-publish
695 $ hg verify -R phase-publish
696 checking changesets
696 checking changesets
697 checking manifests
697 checking manifests
698 crosschecking files in changesets and manifests
698 crosschecking files in changesets and manifests
699 checking files
699 checking files
700 checked 3 changesets with 1088 changes to 1088 files
700 checked 3 changesets with 1088 changes to 1088 files
701 $ hg -R phase-publish phase -r 'all()'
701 $ hg -R phase-publish phase -r 'all()'
702 0: public
702 0: public
703 1: public
703 1: public
704 2: public
704 2: public
705
705
706 Clone as non publishing
706 Clone as non publishing
707
707
708 $ cat << EOF >> server/.hg/hgrc
708 $ cat << EOF >> server/.hg/hgrc
709 > [phases]
709 > [phases]
710 > publish = False
710 > publish = False
711 > EOF
711 > EOF
712 $ killdaemons.py
712 $ killdaemons.py
713 $ hg -R server serve -p $HGPORT -d --pid-file=hg.pid
713 $ hg -R server serve -p $HGPORT -d --pid-file=hg.pid
714 $ cat hg.pid > $DAEMON_PIDS
714 $ cat hg.pid > $DAEMON_PIDS
715
715
716 #if stream-legacy
716 #if stream-legacy
717
717
718 With v1 of the stream protocol, changeset are always cloned as public. It make
718 With v1 of the stream protocol, changeset are always cloned as public. It make
719 stream v1 unsuitable for non-publishing repository.
719 stream v1 unsuitable for non-publishing repository.
720
720
721 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
721 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
722 streaming all changes
722 streaming all changes
723 1090 files to transfer, 102 KB of data (no-zstd !)
723 1090 files to transfer, 102 KB of data (no-zstd !)
724 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
724 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
725 1090 files to transfer, 98.8 KB of data (zstd !)
725 1090 files to transfer, 98.8 KB of data (zstd !)
726 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
726 transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !)
727 searching for changes
727 searching for changes
728 no changes found
728 no changes found
729 updating to branch default
729 updating to branch default
730 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
730 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
731 $ hg -R phase-no-publish phase -r 'all()'
731 $ hg -R phase-no-publish phase -r 'all()'
732 0: public
732 0: public
733 1: public
733 1: public
734 2: public
734 2: public
735 #endif
735 #endif
736 #if stream-bundle2
736 #if stream-bundle2
737 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
737 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
738 streaming all changes
738 streaming all changes
739 1097 files to transfer, 102 KB of data (no-zstd !)
739 1097 files to transfer, 102 KB of data (no-zstd !)
740 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
740 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
741 1097 files to transfer, 99.1 KB of data (zstd !)
741 1097 files to transfer, 99.1 KB of data (zstd !)
742 transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !)
742 transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !)
743 updating to branch default
743 updating to branch default
744 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
744 1088 files updated, 0 files merged, 0 files removed, 0 files unresolved
745 $ hg -R phase-no-publish phase -r 'all()'
745 $ hg -R phase-no-publish phase -r 'all()'
746 0: draft
746 0: draft
747 1: draft
747 1: draft
748 2: draft
748 2: draft
749 #endif
749 #endif
750 $ hg verify -R phase-no-publish
750 $ hg verify -R phase-no-publish
751 checking changesets
751 checking changesets
752 checking manifests
752 checking manifests
753 crosschecking files in changesets and manifests
753 crosschecking files in changesets and manifests
754 checking files
754 checking files
755 checked 3 changesets with 1088 changes to 1088 files
755 checked 3 changesets with 1088 changes to 1088 files
756
756
757 $ killdaemons.py
757 $ killdaemons.py
758
758
759 #if stream-legacy
759 #if stream-legacy
760
760
761 With v1 of the stream protocol, changeset are always cloned as public. There's
761 With v1 of the stream protocol, changeset are always cloned as public. There's
762 no obsolescence markers exchange in stream v1.
762 no obsolescence markers exchange in stream v1.
763
763
764 #endif
764 #endif
765 #if stream-bundle2
765 #if stream-bundle2
766
766
767 Stream repository with obsolescence
767 Stream repository with obsolescence
768 -----------------------------------
768 -----------------------------------
769
769
770 Clone non-publishing with obsolescence
770 Clone non-publishing with obsolescence
771
771
772 $ cat >> $HGRCPATH << EOF
772 $ cat >> $HGRCPATH << EOF
773 > [experimental]
773 > [experimental]
774 > evolution=all
774 > evolution=all
775 > EOF
775 > EOF
776
776
777 $ cd server
777 $ cd server
778 $ echo foo > foo
778 $ echo foo > foo
779 $ hg -q commit -m 'about to be pruned'
779 $ hg -q commit -m 'about to be pruned'
780 $ hg debugobsolete `hg log -r . -T '{node}'` -d '0 0' -u test --record-parents
780 $ hg debugobsolete `hg log -r . -T '{node}'` -d '0 0' -u test --record-parents
781 1 new obsolescence markers
781 1 new obsolescence markers
782 obsoleted 1 changesets
782 obsoleted 1 changesets
783 $ hg up null -q
783 $ hg up null -q
784 $ hg log -T '{rev}: {phase}\n'
784 $ hg log -T '{rev}: {phase}\n'
785 2: draft
785 2: draft
786 1: draft
786 1: draft
787 0: draft
787 0: draft
788 $ hg serve -p $HGPORT -d --pid-file=hg.pid
788 $ hg serve -p $HGPORT -d --pid-file=hg.pid
789 $ cat hg.pid > $DAEMON_PIDS
789 $ cat hg.pid > $DAEMON_PIDS
790 $ cd ..
790 $ cd ..
791
791
792 $ hg clone -U --stream http://localhost:$HGPORT with-obsolescence
792 $ hg clone -U --stream http://localhost:$HGPORT with-obsolescence
793 streaming all changes
793 streaming all changes
794 1098 files to transfer, 102 KB of data (no-zstd !)
794 1098 files to transfer, 102 KB of data (no-zstd !)
795 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
795 transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !)
796 1098 files to transfer, 99.5 KB of data (zstd !)
796 1098 files to transfer, 99.5 KB of data (zstd !)
797 transferred 99.5 KB in * seconds (* */sec) (glob) (zstd !)
797 transferred 99.5 KB in * seconds (* */sec) (glob) (zstd !)
798 $ hg -R with-obsolescence log -T '{rev}: {phase}\n'
798 $ hg -R with-obsolescence log -T '{rev}: {phase}\n'
799 2: draft
799 2: draft
800 1: draft
800 1: draft
801 0: draft
801 0: draft
802 $ hg debugobsolete -R with-obsolescence
802 $ hg debugobsolete -R with-obsolescence
803 8c206a663911c1f97f2f9d7382e417ae55872cfa 0 {5223b5e3265f0df40bb743da62249413d74ac70f} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
803 8c206a663911c1f97f2f9d7382e417ae55872cfa 0 {5223b5e3265f0df40bb743da62249413d74ac70f} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
804 $ hg verify -R with-obsolescence
804 $ hg verify -R with-obsolescence
805 checking changesets
805 checking changesets
806 checking manifests
806 checking manifests
807 crosschecking files in changesets and manifests
807 crosschecking files in changesets and manifests
808 checking files
808 checking files
809 checked 4 changesets with 1089 changes to 1088 files
809 checked 4 changesets with 1089 changes to 1088 files
810
810
811 $ hg clone -U --stream --config experimental.evolution=0 http://localhost:$HGPORT with-obsolescence-no-evolution
811 $ hg clone -U --stream --config experimental.evolution=0 http://localhost:$HGPORT with-obsolescence-no-evolution
812 streaming all changes
812 streaming all changes
813 remote: abort: server has obsolescence markers, but client cannot receive them via stream clone
813 remote: abort: server has obsolescence markers, but client cannot receive them via stream clone
814 abort: pull failed on remote
814 abort: pull failed on remote
815 [100]
815 [100]
816
816
817 $ killdaemons.py
817 $ killdaemons.py
818
818
819 #endif
819 #endif
@@ -1,2088 +1,2124 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 $ cat >> $HGRCPATH << EOF
4 $ cat >> $HGRCPATH << EOF
5 > [ui]
5 > [ui]
6 > merge=
6 > merge=
7 > [commands]
7 > [commands]
8 > merge.require-rev=True
8 > merge.require-rev=True
9 > EOF
9 > EOF
10 $ hg init repo
10 $ hg init repo
11 $ cd repo
11 $ cd repo
12
12
13 revision 0
13 revision 0
14
14
15 $ echo "revision 0" > f
15 $ echo "revision 0" > f
16 $ echo "space" >> f
16 $ echo "space" >> f
17 $ hg commit -Am "revision 0"
17 $ hg commit -Am "revision 0"
18 adding f
18 adding f
19
19
20 revision 1
20 revision 1
21
21
22 $ echo "revision 1" > f
22 $ echo "revision 1" > f
23 $ echo "space" >> f
23 $ echo "space" >> f
24 $ hg commit -Am "revision 1"
24 $ hg commit -Am "revision 1"
25 $ hg update 0 > /dev/null
25 $ hg update 0 > /dev/null
26
26
27 revision 2
27 revision 2
28
28
29 $ echo "revision 2" > f
29 $ echo "revision 2" > f
30 $ echo "space" >> f
30 $ echo "space" >> f
31 $ hg commit -Am "revision 2"
31 $ hg commit -Am "revision 2"
32 created new head
32 created new head
33 $ hg update 0 > /dev/null
33 $ hg update 0 > /dev/null
34
34
35 revision 3 - simple to merge
35 revision 3 - simple to merge
36
36
37 $ echo "revision 3" >> f
37 $ echo "revision 3" >> f
38 $ hg commit -Am "revision 3"
38 $ hg commit -Am "revision 3"
39 created new head
39 created new head
40
40
41 revision 4 - hard to merge
41 revision 4 - hard to merge
42
42
43 $ hg update 0 > /dev/null
43 $ hg update 0 > /dev/null
44 $ echo "revision 4" > f
44 $ echo "revision 4" > f
45 $ hg commit -Am "revision 4"
45 $ hg commit -Am "revision 4"
46 created new head
46 created new head
47
47
48 $ echo "[merge-tools]" > .hg/hgrc
48 $ echo "[merge-tools]" > .hg/hgrc
49
49
50 $ beforemerge() {
50 $ beforemerge() {
51 > cat .hg/hgrc
51 > cat .hg/hgrc
52 > echo "# hg update -C 1"
52 > echo "# hg update -C 1"
53 > hg update -C 1 > /dev/null
53 > hg update -C 1 > /dev/null
54 > }
54 > }
55 $ aftermerge() {
55 $ aftermerge() {
56 > echo "# cat f"
56 > echo "# cat f"
57 > cat f
57 > cat f
58 > echo "# hg stat"
58 > echo "# hg stat"
59 > hg stat
59 > hg stat
60 > echo "# hg resolve --list"
60 > echo "# hg resolve --list"
61 > hg resolve --list
61 > hg resolve --list
62 > rm -f f.orig
62 > rm -f f.orig
63 > }
63 > }
64
64
65 Tool selection
65 Tool selection
66
66
67 default is internal merge:
67 default is internal merge:
68
68
69 $ beforemerge
69 $ beforemerge
70 [merge-tools]
70 [merge-tools]
71 # hg update -C 1
71 # hg update -C 1
72
72
73 hg merge -r 2
73 hg merge -r 2
74 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
74 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
75 running from a devel copy, not a temp installation
75 running from a devel copy, not a temp installation
76
76
77 $ PATH="/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
77 $ PATH="/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
78 merging f
78 merging f
79 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
79 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
80 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
80 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
81 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
81 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
82 [1]
82 [1]
83 $ aftermerge
83 $ aftermerge
84 # cat f
84 # cat f
85 <<<<<<< working copy: ef83787e2614 - test: revision 1
85 <<<<<<< working copy: ef83787e2614 - test: revision 1
86 revision 1
86 revision 1
87 =======
87 =======
88 revision 2
88 revision 2
89 >>>>>>> merge rev: 0185f4e0cf02 - test: revision 2
89 >>>>>>> merge rev: 0185f4e0cf02 - test: revision 2
90 space
90 space
91 # hg stat
91 # hg stat
92 M f
92 M f
93 ? f.orig
93 ? f.orig
94 # hg resolve --list
94 # hg resolve --list
95 U f
95 U f
96
96
97 simplest hgrc using false for merge:
97 simplest hgrc using false for merge:
98
98
99 $ echo "false.whatever=" >> .hg/hgrc
99 $ echo "false.whatever=" >> .hg/hgrc
100 $ beforemerge
100 $ beforemerge
101 [merge-tools]
101 [merge-tools]
102 false.whatever=
102 false.whatever=
103 # hg update -C 1
103 # hg update -C 1
104 $ hg merge -r 2
104 $ hg merge -r 2
105 merging f
105 merging f
106 merging f failed!
106 merging f failed!
107 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
107 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
108 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
108 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
109 [1]
109 [1]
110 $ aftermerge
110 $ aftermerge
111 # cat f
111 # cat f
112 revision 1
112 revision 1
113 space
113 space
114 # hg stat
114 # hg stat
115 M f
115 M f
116 ? f.orig
116 ? f.orig
117 # hg resolve --list
117 # hg resolve --list
118 U f
118 U f
119
119
120 #if unix-permissions
120 #if unix-permissions
121
121
122 unexecutable file in $PATH shouldn't be found:
122 unexecutable file in $PATH shouldn't be found:
123
123
124 $ echo "echo fail" > false
124 $ echo "echo fail" > false
125 $ hg up -qC 1
125 $ hg up -qC 1
126 $ PATH="`pwd`:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
126 $ PATH="`pwd`:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
127 merging f
127 merging f
128 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
128 warning: conflicts while merging f! (edit, 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 merge --abort' to abandon
130 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
131 [1]
131 [1]
132 $ rm false
132 $ rm false
133
133
134 #endif
134 #endif
135
135
136 executable directory in $PATH shouldn't be found:
136 executable directory in $PATH shouldn't be found:
137
137
138 $ mkdir false
138 $ mkdir false
139 $ hg up -qC 1
139 $ hg up -qC 1
140 $ PATH="`pwd`:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
140 $ PATH="`pwd`:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
141 merging f
141 merging f
142 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
142 warning: conflicts while merging f! (edit, 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 merge --abort' to abandon
144 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
145 [1]
145 [1]
146 $ rmdir false
146 $ rmdir false
147
147
148 true with higher .priority gets precedence:
148 true with higher .priority gets precedence:
149
149
150 $ echo "true.priority=1" >> .hg/hgrc
150 $ echo "true.priority=1" >> .hg/hgrc
151 $ beforemerge
151 $ beforemerge
152 [merge-tools]
152 [merge-tools]
153 false.whatever=
153 false.whatever=
154 true.priority=1
154 true.priority=1
155 # hg update -C 1
155 # hg update -C 1
156 $ hg merge -r 2
156 $ hg merge -r 2
157 merging f
157 merging f
158 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
158 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
159 (branch merge, don't forget to commit)
159 (branch merge, don't forget to commit)
160 $ aftermerge
160 $ aftermerge
161 # cat f
161 # cat f
162 revision 1
162 revision 1
163 space
163 space
164 # hg stat
164 # hg stat
165 M f
165 M f
166 # hg resolve --list
166 # hg resolve --list
167 R f
167 R f
168
168
169 unless lowered on command line:
169 unless lowered on command line:
170
170
171 $ beforemerge
171 $ beforemerge
172 [merge-tools]
172 [merge-tools]
173 false.whatever=
173 false.whatever=
174 true.priority=1
174 true.priority=1
175 # hg update -C 1
175 # hg update -C 1
176 $ hg merge -r 2 --config merge-tools.true.priority=-7
176 $ hg merge -r 2 --config merge-tools.true.priority=-7
177 merging f
177 merging f
178 merging f failed!
178 merging f failed!
179 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
179 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
180 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
180 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
181 [1]
181 [1]
182 $ aftermerge
182 $ aftermerge
183 # cat f
183 # cat f
184 revision 1
184 revision 1
185 space
185 space
186 # hg stat
186 # hg stat
187 M f
187 M f
188 ? f.orig
188 ? f.orig
189 # hg resolve --list
189 # hg resolve --list
190 U f
190 U f
191
191
192 or false set higher on command line:
192 or false set higher on command line:
193
193
194 $ beforemerge
194 $ beforemerge
195 [merge-tools]
195 [merge-tools]
196 false.whatever=
196 false.whatever=
197 true.priority=1
197 true.priority=1
198 # hg update -C 1
198 # hg update -C 1
199 $ hg merge -r 2 --config merge-tools.false.priority=117
199 $ hg merge -r 2 --config merge-tools.false.priority=117
200 merging f
200 merging f
201 merging f failed!
201 merging f failed!
202 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
202 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
203 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
203 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
204 [1]
204 [1]
205 $ aftermerge
205 $ aftermerge
206 # cat f
206 # cat f
207 revision 1
207 revision 1
208 space
208 space
209 # hg stat
209 # hg stat
210 M f
210 M f
211 ? f.orig
211 ? f.orig
212 # hg resolve --list
212 # hg resolve --list
213 U f
213 U f
214
214
215 or true set to disabled:
215 or true set to disabled:
216 $ beforemerge
216 $ beforemerge
217 [merge-tools]
217 [merge-tools]
218 false.whatever=
218 false.whatever=
219 true.priority=1
219 true.priority=1
220 # hg update -C 1
220 # hg update -C 1
221 $ hg merge -r 2 --config merge-tools.true.disabled=yes
221 $ hg merge -r 2 --config merge-tools.true.disabled=yes
222 merging f
222 merging f
223 merging f failed!
223 merging f failed!
224 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
224 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
225 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
225 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
226 [1]
226 [1]
227 $ aftermerge
227 $ aftermerge
228 # cat f
228 # cat f
229 revision 1
229 revision 1
230 space
230 space
231 # hg stat
231 # hg stat
232 M f
232 M f
233 ? f.orig
233 ? f.orig
234 # hg resolve --list
234 # hg resolve --list
235 U f
235 U f
236
236
237 or true.executable not found in PATH:
237 or true.executable not found in PATH:
238
238
239 $ beforemerge
239 $ beforemerge
240 [merge-tools]
240 [merge-tools]
241 false.whatever=
241 false.whatever=
242 true.priority=1
242 true.priority=1
243 # hg update -C 1
243 # hg update -C 1
244 $ hg merge -r 2 --config merge-tools.true.executable=nonexistentmergetool
244 $ hg merge -r 2 --config merge-tools.true.executable=nonexistentmergetool
245 merging f
245 merging f
246 merging f failed!
246 merging f failed!
247 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
247 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
248 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
248 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
249 [1]
249 [1]
250 $ aftermerge
250 $ aftermerge
251 # cat f
251 # cat f
252 revision 1
252 revision 1
253 space
253 space
254 # hg stat
254 # hg stat
255 M f
255 M f
256 ? f.orig
256 ? f.orig
257 # hg resolve --list
257 # hg resolve --list
258 U f
258 U f
259
259
260 or true.executable with bogus path:
260 or true.executable with bogus path:
261
261
262 $ beforemerge
262 $ beforemerge
263 [merge-tools]
263 [merge-tools]
264 false.whatever=
264 false.whatever=
265 true.priority=1
265 true.priority=1
266 # hg update -C 1
266 # hg update -C 1
267 $ hg merge -r 2 --config merge-tools.true.executable=/nonexistent/mergetool
267 $ hg merge -r 2 --config merge-tools.true.executable=/nonexistent/mergetool
268 merging f
268 merging f
269 merging f failed!
269 merging f failed!
270 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
270 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
271 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
271 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
272 [1]
272 [1]
273 $ aftermerge
273 $ aftermerge
274 # cat f
274 # cat f
275 revision 1
275 revision 1
276 space
276 space
277 # hg stat
277 # hg stat
278 M f
278 M f
279 ? f.orig
279 ? f.orig
280 # hg resolve --list
280 # hg resolve --list
281 U f
281 U f
282
282
283 but true.executable set to cat found in PATH works:
283 but true.executable set to cat found in PATH works:
284
284
285 $ echo "true.executable=cat" >> .hg/hgrc
285 $ echo "true.executable=cat" >> .hg/hgrc
286 $ beforemerge
286 $ beforemerge
287 [merge-tools]
287 [merge-tools]
288 false.whatever=
288 false.whatever=
289 true.priority=1
289 true.priority=1
290 true.executable=cat
290 true.executable=cat
291 # hg update -C 1
291 # hg update -C 1
292 $ hg merge -r 2
292 $ hg merge -r 2
293 merging f
293 merging f
294 revision 1
294 revision 1
295 space
295 space
296 revision 0
296 revision 0
297 space
297 space
298 revision 2
298 revision 2
299 space
299 space
300 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
300 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
301 (branch merge, don't forget to commit)
301 (branch merge, don't forget to commit)
302 $ aftermerge
302 $ aftermerge
303 # cat f
303 # cat f
304 revision 1
304 revision 1
305 space
305 space
306 # hg stat
306 # hg stat
307 M f
307 M f
308 # hg resolve --list
308 # hg resolve --list
309 R f
309 R f
310
310
311 and true.executable set to cat with path works:
311 and true.executable set to cat with path works:
312
312
313 $ beforemerge
313 $ beforemerge
314 [merge-tools]
314 [merge-tools]
315 false.whatever=
315 false.whatever=
316 true.priority=1
316 true.priority=1
317 true.executable=cat
317 true.executable=cat
318 # hg update -C 1
318 # hg update -C 1
319 $ hg merge -r 2 --config merge-tools.true.executable=cat
319 $ hg merge -r 2 --config merge-tools.true.executable=cat
320 merging f
320 merging f
321 revision 1
321 revision 1
322 space
322 space
323 revision 0
323 revision 0
324 space
324 space
325 revision 2
325 revision 2
326 space
326 space
327 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
327 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
328 (branch merge, don't forget to commit)
328 (branch merge, don't forget to commit)
329 $ aftermerge
329 $ aftermerge
330 # cat f
330 # cat f
331 revision 1
331 revision 1
332 space
332 space
333 # hg stat
333 # hg stat
334 M f
334 M f
335 # hg resolve --list
335 # hg resolve --list
336 R f
336 R f
337
337
338 executable set to python script that succeeds:
338 executable set to python script that succeeds:
339
339
340 $ cat > "$TESTTMP/myworkingmerge.py" <<EOF
340 $ cat > "$TESTTMP/myworkingmerge.py" <<EOF
341 > def myworkingmergefn(ui, repo, args, **kwargs):
341 > def myworkingmergefn(ui, repo, args, **kwargs):
342 > return False
342 > return False
343 > EOF
343 > EOF
344 $ beforemerge
344 $ beforemerge
345 [merge-tools]
345 [merge-tools]
346 false.whatever=
346 false.whatever=
347 true.priority=1
347 true.priority=1
348 true.executable=cat
348 true.executable=cat
349 # hg update -C 1
349 # hg update -C 1
350 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py:myworkingmergefn"
350 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py:myworkingmergefn"
351 merging f
351 merging f
352 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
352 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
353 (branch merge, don't forget to commit)
353 (branch merge, don't forget to commit)
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 # hg resolve --list
360 # hg resolve --list
361 R f
361 R f
362
362
363 executable set to python script that fails:
363 executable set to python script that fails:
364
364
365 $ cat > "$TESTTMP/mybrokenmerge.py" <<EOF
365 $ cat > "$TESTTMP/mybrokenmerge.py" <<EOF
366 > def mybrokenmergefn(ui, repo, args, **kwargs):
366 > def mybrokenmergefn(ui, repo, args, **kwargs):
367 > ui.write(b"some fail message\n")
367 > ui.write(b"some fail message\n")
368 > return True
368 > return True
369 > EOF
369 > EOF
370 $ beforemerge
370 $ beforemerge
371 [merge-tools]
371 [merge-tools]
372 false.whatever=
372 false.whatever=
373 true.priority=1
373 true.priority=1
374 true.executable=cat
374 true.executable=cat
375 # hg update -C 1
375 # hg update -C 1
376 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/mybrokenmerge.py:mybrokenmergefn"
376 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/mybrokenmerge.py:mybrokenmergefn"
377 merging f
377 merging f
378 some fail message
378 some fail message
379 abort: $TESTTMP/mybrokenmerge.py hook failed
379 abort: $TESTTMP/mybrokenmerge.py hook failed
380 [40]
380 [40]
381 $ aftermerge
381 $ aftermerge
382 # cat f
382 # cat f
383 revision 1
383 revision 1
384 space
384 space
385 # hg stat
385 # hg stat
386 ? f.orig
386 ? f.orig
387 # hg resolve --list
387 # hg resolve --list
388 U f
388 U f
389
389
390 executable set to python script that is missing function:
390 executable set to python script that is missing function:
391
391
392 $ beforemerge
392 $ beforemerge
393 [merge-tools]
393 [merge-tools]
394 false.whatever=
394 false.whatever=
395 true.priority=1
395 true.priority=1
396 true.executable=cat
396 true.executable=cat
397 # hg update -C 1
397 # hg update -C 1
398 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py:missingFunction"
398 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py:missingFunction"
399 merging f
399 merging f
400 abort: $TESTTMP/myworkingmerge.py does not have function: missingFunction
400 abort: $TESTTMP/myworkingmerge.py does not have function: missingFunction
401 [255]
401 [255]
402 $ aftermerge
402 $ aftermerge
403 # cat f
403 # cat f
404 revision 1
404 revision 1
405 space
405 space
406 # hg stat
406 # hg stat
407 ? f.orig
407 ? f.orig
408 # hg resolve --list
408 # hg resolve --list
409 U f
409 U f
410
410
411 executable set to missing python script:
411 executable set to missing python script:
412
412
413 $ beforemerge
413 $ beforemerge
414 [merge-tools]
414 [merge-tools]
415 false.whatever=
415 false.whatever=
416 true.priority=1
416 true.priority=1
417 true.executable=cat
417 true.executable=cat
418 # hg update -C 1
418 # hg update -C 1
419 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/missingpythonscript.py:mergefn"
419 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/missingpythonscript.py:mergefn"
420 merging f
420 merging f
421 abort: loading python merge script failed: $TESTTMP/missingpythonscript.py
421 abort: loading python merge script failed: $TESTTMP/missingpythonscript.py
422 [255]
422 [255]
423 $ aftermerge
423 $ aftermerge
424 # cat f
424 # cat f
425 revision 1
425 revision 1
426 space
426 space
427 # hg stat
427 # hg stat
428 ? f.orig
428 ? f.orig
429 # hg resolve --list
429 # hg resolve --list
430 U f
430 U f
431
431
432 executable set to python script but callable function is missing:
432 executable set to python script but callable function is missing:
433
433
434 $ beforemerge
434 $ beforemerge
435 [merge-tools]
435 [merge-tools]
436 false.whatever=
436 false.whatever=
437 true.priority=1
437 true.priority=1
438 true.executable=cat
438 true.executable=cat
439 # hg update -C 1
439 # hg update -C 1
440 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py"
440 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py"
441 abort: invalid 'python:' syntax: python:$TESTTMP/myworkingmerge.py
441 abort: invalid 'python:' syntax: python:$TESTTMP/myworkingmerge.py
442 [255]
442 [255]
443 $ aftermerge
443 $ aftermerge
444 # cat f
444 # cat f
445 revision 1
445 revision 1
446 space
446 space
447 # hg stat
447 # hg stat
448 # hg resolve --list
448 # hg resolve --list
449 U f
449 U f
450
450
451 executable set to python script but callable function is empty string:
451 executable set to python script but callable function is empty string:
452
452
453 $ beforemerge
453 $ beforemerge
454 [merge-tools]
454 [merge-tools]
455 false.whatever=
455 false.whatever=
456 true.priority=1
456 true.priority=1
457 true.executable=cat
457 true.executable=cat
458 # hg update -C 1
458 # hg update -C 1
459 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py:"
459 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/myworkingmerge.py:"
460 abort: invalid 'python:' syntax: python:$TESTTMP/myworkingmerge.py:
460 abort: invalid 'python:' syntax: python:$TESTTMP/myworkingmerge.py:
461 [255]
461 [255]
462 $ aftermerge
462 $ aftermerge
463 # cat f
463 # cat f
464 revision 1
464 revision 1
465 space
465 space
466 # hg stat
466 # hg stat
467 # hg resolve --list
467 # hg resolve --list
468 U f
468 U f
469
469
470 executable set to python script but callable function is missing and path contains colon:
470 executable set to python script but callable function is missing and path contains colon:
471
471
472 $ beforemerge
472 $ beforemerge
473 [merge-tools]
473 [merge-tools]
474 false.whatever=
474 false.whatever=
475 true.priority=1
475 true.priority=1
476 true.executable=cat
476 true.executable=cat
477 # hg update -C 1
477 # hg update -C 1
478 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/some:dir/myworkingmerge.py"
478 $ hg merge -r 2 --config merge-tools.true.executable="python:$TESTTMP/some:dir/myworkingmerge.py"
479 abort: invalid 'python:' syntax: python:$TESTTMP/some:dir/myworkingmerge.py
479 abort: invalid 'python:' syntax: python:$TESTTMP/some:dir/myworkingmerge.py
480 [255]
480 [255]
481 $ aftermerge
481 $ aftermerge
482 # cat f
482 # cat f
483 revision 1
483 revision 1
484 space
484 space
485 # hg stat
485 # hg stat
486 # hg resolve --list
486 # hg resolve --list
487 U f
487 U f
488
488
489 executable set to python script filename that contains spaces:
489 executable set to python script filename that contains spaces:
490
490
491 $ mkdir -p "$TESTTMP/my path"
491 $ mkdir -p "$TESTTMP/my path"
492 $ cat > "$TESTTMP/my path/my working merge with spaces in filename.py" <<EOF
492 $ cat > "$TESTTMP/my path/my working merge with spaces in filename.py" <<EOF
493 > def myworkingmergefn(ui, repo, args, **kwargs):
493 > def myworkingmergefn(ui, repo, args, **kwargs):
494 > return False
494 > return False
495 > EOF
495 > EOF
496 $ beforemerge
496 $ beforemerge
497 [merge-tools]
497 [merge-tools]
498 false.whatever=
498 false.whatever=
499 true.priority=1
499 true.priority=1
500 true.executable=cat
500 true.executable=cat
501 # hg update -C 1
501 # hg update -C 1
502 $ hg merge -r 2 --config "merge-tools.true.executable=python:$TESTTMP/my path/my working merge with spaces in filename.py:myworkingmergefn"
502 $ hg merge -r 2 --config "merge-tools.true.executable=python:$TESTTMP/my path/my working merge with spaces in filename.py:myworkingmergefn"
503 merging f
503 merging f
504 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
504 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
505 (branch merge, don't forget to commit)
505 (branch merge, don't forget to commit)
506 $ aftermerge
506 $ aftermerge
507 # cat f
507 # cat f
508 revision 1
508 revision 1
509 space
509 space
510 # hg stat
510 # hg stat
511 M f
511 M f
512 # hg resolve --list
512 # hg resolve --list
513 R f
513 R f
514
514
515 #if unix-permissions
515 #if unix-permissions
516
516
517 environment variables in true.executable are handled:
517 environment variables in true.executable are handled:
518
518
519 $ echo 'echo "custom merge tool"' > .hg/merge.sh
519 $ echo 'echo "custom merge tool"' > .hg/merge.sh
520 $ beforemerge
520 $ beforemerge
521 [merge-tools]
521 [merge-tools]
522 false.whatever=
522 false.whatever=
523 true.priority=1
523 true.priority=1
524 true.executable=cat
524 true.executable=cat
525 # hg update -C 1
525 # hg update -C 1
526 $ hg --config merge-tools.true.executable='sh' \
526 $ hg --config merge-tools.true.executable='sh' \
527 > --config merge-tools.true.args=.hg/merge.sh \
527 > --config merge-tools.true.args=.hg/merge.sh \
528 > merge -r 2
528 > merge -r 2
529 merging f
529 merging f
530 custom merge tool
530 custom merge tool
531 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
531 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
532 (branch merge, don't forget to commit)
532 (branch merge, don't forget to commit)
533 $ aftermerge
533 $ aftermerge
534 # cat f
534 # cat f
535 revision 1
535 revision 1
536 space
536 space
537 # hg stat
537 # hg stat
538 M f
538 M f
539 # hg resolve --list
539 # hg resolve --list
540 R f
540 R f
541
541
542 #endif
542 #endif
543
543
544 Tool selection and merge-patterns
544 Tool selection and merge-patterns
545
545
546 merge-patterns specifies new tool false:
546 merge-patterns specifies new tool false:
547
547
548 $ beforemerge
548 $ beforemerge
549 [merge-tools]
549 [merge-tools]
550 false.whatever=
550 false.whatever=
551 true.priority=1
551 true.priority=1
552 true.executable=cat
552 true.executable=cat
553 # hg update -C 1
553 # hg update -C 1
554 $ hg merge -r 2 --config merge-patterns.f=false
554 $ hg merge -r 2 --config merge-patterns.f=false
555 merging f
555 merging f
556 merging f failed!
556 merging f failed!
557 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
557 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
558 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
558 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
559 [1]
559 [1]
560 $ aftermerge
560 $ aftermerge
561 # cat f
561 # cat f
562 revision 1
562 revision 1
563 space
563 space
564 # hg stat
564 # hg stat
565 M f
565 M f
566 ? f.orig
566 ? f.orig
567 # hg resolve --list
567 # hg resolve --list
568 U f
568 U f
569
569
570 merge-patterns specifies executable not found in PATH and gets warning:
570 merge-patterns specifies executable not found in PATH and gets warning:
571
571
572 $ beforemerge
572 $ beforemerge
573 [merge-tools]
573 [merge-tools]
574 false.whatever=
574 false.whatever=
575 true.priority=1
575 true.priority=1
576 true.executable=cat
576 true.executable=cat
577 # hg update -C 1
577 # hg update -C 1
578 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool
578 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool
579 couldn't find merge tool true (for pattern f)
579 couldn't find merge tool true (for pattern f)
580 merging f
580 merging f
581 merging f failed!
581 merging f failed!
582 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
582 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
583 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
583 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
584 [1]
584 [1]
585 $ aftermerge
585 $ aftermerge
586 # cat f
586 # cat f
587 revision 1
587 revision 1
588 space
588 space
589 # hg stat
589 # hg stat
590 M f
590 M f
591 ? f.orig
591 ? f.orig
592 # hg resolve --list
592 # hg resolve --list
593 U f
593 U f
594
594
595 merge-patterns specifies executable with bogus path and gets warning:
595 merge-patterns specifies executable with bogus path and gets warning:
596
596
597 $ beforemerge
597 $ beforemerge
598 [merge-tools]
598 [merge-tools]
599 false.whatever=
599 false.whatever=
600 true.priority=1
600 true.priority=1
601 true.executable=cat
601 true.executable=cat
602 # hg update -C 1
602 # hg update -C 1
603 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexistent/mergetool
603 $ hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexistent/mergetool
604 couldn't find merge tool true (for pattern f)
604 couldn't find merge tool true (for pattern f)
605 merging f
605 merging f
606 merging f failed!
606 merging f failed!
607 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
607 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
608 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
608 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
609 [1]
609 [1]
610 $ aftermerge
610 $ aftermerge
611 # cat f
611 # cat f
612 revision 1
612 revision 1
613 space
613 space
614 # hg stat
614 # hg stat
615 M f
615 M f
616 ? f.orig
616 ? f.orig
617 # hg resolve --list
617 # hg resolve --list
618 U f
618 U f
619
619
620 ui.merge overrules priority
620 ui.merge overrules priority
621
621
622 ui.merge specifies false:
622 ui.merge specifies false:
623
623
624 $ beforemerge
624 $ beforemerge
625 [merge-tools]
625 [merge-tools]
626 false.whatever=
626 false.whatever=
627 true.priority=1
627 true.priority=1
628 true.executable=cat
628 true.executable=cat
629 # hg update -C 1
629 # hg update -C 1
630 $ hg merge -r 2 --config ui.merge=false
630 $ hg merge -r 2 --config ui.merge=false
631 merging f
631 merging f
632 merging f failed!
632 merging f failed!
633 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
633 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
634 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
634 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
635 [1]
635 [1]
636 $ aftermerge
636 $ aftermerge
637 # cat f
637 # cat f
638 revision 1
638 revision 1
639 space
639 space
640 # hg stat
640 # hg stat
641 M f
641 M f
642 ? f.orig
642 ? f.orig
643 # hg resolve --list
643 # hg resolve --list
644 U f
644 U f
645
645
646 ui.merge specifies internal:fail:
646 ui.merge specifies internal:fail:
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 2 --config ui.merge=internal:fail
654 $ hg merge -r 2 --config ui.merge=internal:fail
655 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
655 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
656 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
656 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
657 [1]
657 [1]
658 $ aftermerge
658 $ aftermerge
659 # cat f
659 # cat f
660 revision 1
660 revision 1
661 space
661 space
662 # hg stat
662 # hg stat
663 M f
663 M f
664 # hg resolve --list
664 # hg resolve --list
665 U f
665 U f
666
666
667 ui.merge specifies :local (without internal prefix):
667 ui.merge specifies :local (without internal prefix):
668
668
669 $ beforemerge
669 $ beforemerge
670 [merge-tools]
670 [merge-tools]
671 false.whatever=
671 false.whatever=
672 true.priority=1
672 true.priority=1
673 true.executable=cat
673 true.executable=cat
674 # hg update -C 1
674 # hg update -C 1
675 $ hg merge -r 2 --config ui.merge=:local
675 $ hg merge -r 2 --config ui.merge=:local
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 # hg stat
682 # hg stat
683 M f
683 M f
684 # hg resolve --list
684 # hg resolve --list
685 R f
685 R f
686
686
687 ui.merge specifies internal:other:
687 ui.merge specifies internal:other:
688
688
689 $ beforemerge
689 $ beforemerge
690 [merge-tools]
690 [merge-tools]
691 false.whatever=
691 false.whatever=
692 true.priority=1
692 true.priority=1
693 true.executable=cat
693 true.executable=cat
694 # hg update -C 1
694 # hg update -C 1
695 $ hg merge -r 2 --config ui.merge=internal:other
695 $ hg merge -r 2 --config ui.merge=internal:other
696 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
696 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
697 (branch merge, don't forget to commit)
697 (branch merge, don't forget to commit)
698 $ aftermerge
698 $ aftermerge
699 # cat f
699 # cat f
700 revision 2
700 revision 2
701 space
701 space
702 # hg stat
702 # hg stat
703 M f
703 M f
704 # hg resolve --list
704 # hg resolve --list
705 R f
705 R f
706
706
707 ui.merge specifies internal:prompt:
707 ui.merge specifies internal:prompt:
708
708
709 $ beforemerge
709 $ beforemerge
710 [merge-tools]
710 [merge-tools]
711 false.whatever=
711 false.whatever=
712 true.priority=1
712 true.priority=1
713 true.executable=cat
713 true.executable=cat
714 # hg update -C 1
714 # hg update -C 1
715 $ hg merge -r 2 --config ui.merge=internal:prompt
715 $ hg merge -r 2 --config ui.merge=internal:prompt
716 file 'f' needs to be resolved.
716 file 'f' needs to be resolved.
717 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
717 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
718 What do you want to do? u
718 What do you want to do? u
719 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
719 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
720 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
720 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
721 [1]
721 [1]
722 $ aftermerge
722 $ aftermerge
723 # cat f
723 # cat f
724 revision 1
724 revision 1
725 space
725 space
726 # hg stat
726 # hg stat
727 M f
727 M f
728 # hg resolve --list
728 # hg resolve --list
729 U f
729 U f
730
730
731 ui.merge specifies :prompt, with 'leave unresolved' chosen
731 ui.merge specifies :prompt, with 'leave unresolved' chosen
732
732
733 $ beforemerge
733 $ beforemerge
734 [merge-tools]
734 [merge-tools]
735 false.whatever=
735 false.whatever=
736 true.priority=1
736 true.priority=1
737 true.executable=cat
737 true.executable=cat
738 # hg update -C 1
738 # hg update -C 1
739 $ hg merge -r 2 --config ui.merge=:prompt --config ui.interactive=True << EOF
739 $ hg merge -r 2 --config ui.merge=:prompt --config ui.interactive=True << EOF
740 > u
740 > u
741 > EOF
741 > EOF
742 file 'f' needs to be resolved.
742 file 'f' needs to be resolved.
743 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
743 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
744 What do you want to do? u
744 What do you want to do? u
745 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
745 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
746 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
746 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
747 [1]
747 [1]
748 $ aftermerge
748 $ aftermerge
749 # cat f
749 # cat f
750 revision 1
750 revision 1
751 space
751 space
752 # hg stat
752 # hg stat
753 M f
753 M f
754 # hg resolve --list
754 # hg resolve --list
755 U f
755 U f
756
756
757 prompt with EOF
757 prompt with EOF
758
758
759 $ beforemerge
759 $ beforemerge
760 [merge-tools]
760 [merge-tools]
761 false.whatever=
761 false.whatever=
762 true.priority=1
762 true.priority=1
763 true.executable=cat
763 true.executable=cat
764 # hg update -C 1
764 # hg update -C 1
765 $ hg merge -r 2 --config ui.merge=internal:prompt --config ui.interactive=true
765 $ hg merge -r 2 --config ui.merge=internal:prompt --config ui.interactive=true
766 file 'f' needs to be resolved.
766 file 'f' needs to be resolved.
767 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
767 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
768 What do you want to do?
768 What do you want to do?
769 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
769 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
770 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
770 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
771 [1]
771 [1]
772 $ aftermerge
772 $ aftermerge
773 # cat f
773 # cat f
774 revision 1
774 revision 1
775 space
775 space
776 # hg stat
776 # hg stat
777 M f
777 M f
778 # hg resolve --list
778 # hg resolve --list
779 U f
779 U f
780 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
780 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
781 file 'f' needs to be resolved.
781 file 'f' needs to be resolved.
782 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
782 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
783 What do you want to do?
783 What do you want to do?
784 [1]
784 [1]
785 $ aftermerge
785 $ aftermerge
786 # cat f
786 # cat f
787 revision 1
787 revision 1
788 space
788 space
789 # hg stat
789 # hg stat
790 M f
790 M f
791 ? f.orig
791 ? f.orig
792 # hg resolve --list
792 # hg resolve --list
793 U f
793 U f
794 $ rm f
794 $ rm f
795 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
795 $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
796 file 'f' needs to be resolved.
796 file 'f' needs to be resolved.
797 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
797 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
798 What do you want to do?
798 What do you want to do?
799 [1]
799 [1]
800 $ aftermerge
800 $ aftermerge
801 # cat f
801 # cat f
802 revision 1
802 revision 1
803 space
803 space
804 # hg stat
804 # hg stat
805 M f
805 M f
806 # hg resolve --list
806 # hg resolve --list
807 U f
807 U f
808 $ hg resolve --all --config ui.merge=internal:prompt
808 $ hg resolve --all --config ui.merge=internal:prompt
809 file 'f' needs to be resolved.
809 file 'f' needs to be resolved.
810 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
810 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
811 What do you want to do? u
811 What do you want to do? u
812 [1]
812 [1]
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 ? f.orig
819 ? f.orig
820 # hg resolve --list
820 # hg resolve --list
821 U f
821 U f
822
822
823 ui.merge specifies internal:dump:
823 ui.merge specifies internal:dump:
824
824
825 $ beforemerge
825 $ beforemerge
826 [merge-tools]
826 [merge-tools]
827 false.whatever=
827 false.whatever=
828 true.priority=1
828 true.priority=1
829 true.executable=cat
829 true.executable=cat
830 # hg update -C 1
830 # hg update -C 1
831 $ hg merge -r 2 --config ui.merge=internal:dump
831 $ hg merge -r 2 --config ui.merge=internal:dump
832 merging f
832 merging f
833 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
833 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
834 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
834 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
835 [1]
835 [1]
836 $ aftermerge
836 $ aftermerge
837 # cat f
837 # cat f
838 revision 1
838 revision 1
839 space
839 space
840 # hg stat
840 # hg stat
841 M f
841 M f
842 ? f.base
842 ? f.base
843 ? f.local
843 ? f.local
844 ? f.orig
844 ? f.orig
845 ? f.other
845 ? f.other
846 # hg resolve --list
846 # hg resolve --list
847 U f
847 U f
848
848
849 f.base:
849 f.base:
850
850
851 $ cat f.base
851 $ cat f.base
852 revision 0
852 revision 0
853 space
853 space
854
854
855 f.local:
855 f.local:
856
856
857 $ cat f.local
857 $ cat f.local
858 revision 1
858 revision 1
859 space
859 space
860
860
861 f.other:
861 f.other:
862
862
863 $ cat f.other
863 $ cat f.other
864 revision 2
864 revision 2
865 space
865 space
866 $ rm f.base f.local f.other
866 $ rm f.base f.local f.other
867
867
868 check that internal:dump doesn't dump files if premerge runs
868 check that internal:dump doesn't dump files if premerge runs
869 successfully
869 successfully
870
870
871 $ beforemerge
871 $ beforemerge
872 [merge-tools]
872 [merge-tools]
873 false.whatever=
873 false.whatever=
874 true.priority=1
874 true.priority=1
875 true.executable=cat
875 true.executable=cat
876 # hg update -C 1
876 # hg update -C 1
877 $ hg merge -r 3 --config ui.merge=internal:dump
877 $ hg merge -r 3 --config ui.merge=internal:dump
878 merging f
878 merging f
879 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
879 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
880 (branch merge, don't forget to commit)
880 (branch merge, don't forget to commit)
881
881
882 $ aftermerge
882 $ aftermerge
883 # cat f
883 # cat f
884 revision 1
884 revision 1
885 space
885 space
886 revision 3
886 revision 3
887 # hg stat
887 # hg stat
888 M f
888 M f
889 # hg resolve --list
889 # hg resolve --list
890 R f
890 R f
891
891
892 check that internal:forcedump dumps files, even if local and other can
892 check that internal:forcedump dumps files, even if local and other can
893 be merged easily
893 be merged easily
894
894
895 $ beforemerge
895 $ beforemerge
896 [merge-tools]
896 [merge-tools]
897 false.whatever=
897 false.whatever=
898 true.priority=1
898 true.priority=1
899 true.executable=cat
899 true.executable=cat
900 # hg update -C 1
900 # hg update -C 1
901 $ hg merge -r 3 --config ui.merge=internal:forcedump
901 $ hg merge -r 3 --config ui.merge=internal:forcedump
902 merging f
902 merging f
903 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
903 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
904 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
904 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
905 [1]
905 [1]
906 $ aftermerge
906 $ aftermerge
907 # cat f
907 # cat f
908 revision 1
908 revision 1
909 space
909 space
910 # hg stat
910 # hg stat
911 M f
911 M f
912 ? f.base
912 ? f.base
913 ? f.local
913 ? f.local
914 ? f.orig
914 ? f.orig
915 ? f.other
915 ? f.other
916 # hg resolve --list
916 # hg resolve --list
917 U f
917 U f
918
918
919 $ cat f.base
919 $ cat f.base
920 revision 0
920 revision 0
921 space
921 space
922
922
923 $ cat f.local
923 $ cat f.local
924 revision 1
924 revision 1
925 space
925 space
926
926
927 $ cat f.other
927 $ cat f.other
928 revision 0
928 revision 0
929 space
929 space
930 revision 3
930 revision 3
931
931
932 $ rm -f f.base f.local f.other
932 $ rm -f f.base f.local f.other
933
933
934 ui.merge specifies internal:other but is overruled by pattern for false:
934 ui.merge specifies internal:other but is overruled by pattern for false:
935
935
936 $ beforemerge
936 $ beforemerge
937 [merge-tools]
937 [merge-tools]
938 false.whatever=
938 false.whatever=
939 true.priority=1
939 true.priority=1
940 true.executable=cat
940 true.executable=cat
941 # hg update -C 1
941 # hg update -C 1
942 $ hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
942 $ hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
943 merging f
943 merging f
944 merging f failed!
944 merging f failed!
945 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
945 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
946 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
946 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
947 [1]
947 [1]
948 $ aftermerge
948 $ aftermerge
949 # cat f
949 # cat f
950 revision 1
950 revision 1
951 space
951 space
952 # hg stat
952 # hg stat
953 M f
953 M f
954 ? f.orig
954 ? f.orig
955 # hg resolve --list
955 # hg resolve --list
956 U f
956 U f
957
957
958 Premerge
958 Premerge
959
959
960 ui.merge specifies internal:other but is overruled by --tool=false
960 ui.merge specifies internal:other but is overruled by --tool=false
961
961
962 $ beforemerge
962 $ beforemerge
963 [merge-tools]
963 [merge-tools]
964 false.whatever=
964 false.whatever=
965 true.priority=1
965 true.priority=1
966 true.executable=cat
966 true.executable=cat
967 # hg update -C 1
967 # hg update -C 1
968 $ hg merge -r 2 --config ui.merge=internal:other --tool=false
968 $ hg merge -r 2 --config ui.merge=internal:other --tool=false
969 merging f
969 merging f
970 merging f failed!
970 merging f failed!
971 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
971 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
972 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
972 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
973 [1]
973 [1]
974 $ aftermerge
974 $ aftermerge
975 # cat f
975 # cat f
976 revision 1
976 revision 1
977 space
977 space
978 # hg stat
978 # hg stat
979 M f
979 M f
980 ? f.orig
980 ? f.orig
981 # hg resolve --list
981 # hg resolve --list
982 U f
982 U f
983
983
984 HGMERGE specifies internal:other but is overruled by --tool=false
984 HGMERGE specifies internal:other but is overruled by --tool=false
985
985
986 $ HGMERGE=internal:other ; export HGMERGE
986 $ HGMERGE=internal:other ; export HGMERGE
987 $ beforemerge
987 $ beforemerge
988 [merge-tools]
988 [merge-tools]
989 false.whatever=
989 false.whatever=
990 true.priority=1
990 true.priority=1
991 true.executable=cat
991 true.executable=cat
992 # hg update -C 1
992 # hg update -C 1
993 $ hg merge -r 2 --tool=false
993 $ hg merge -r 2 --tool=false
994 merging f
994 merging f
995 merging f failed!
995 merging f failed!
996 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
996 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
997 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
997 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
998 [1]
998 [1]
999 $ aftermerge
999 $ aftermerge
1000 # cat f
1000 # cat f
1001 revision 1
1001 revision 1
1002 space
1002 space
1003 # hg stat
1003 # hg stat
1004 M f
1004 M f
1005 ? f.orig
1005 ? f.orig
1006 # hg resolve --list
1006 # hg resolve --list
1007 U f
1007 U f
1008
1008
1009 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
1009 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
1010
1010
1011 update is a merge ...
1011 update is a merge ...
1012
1012
1013 (this also tests that files reverted with '--rev REV' are treated as
1013 (this also tests that files reverted with '--rev REV' are treated as
1014 "modified", even if none of mode, size and timestamp of them isn't
1014 "modified", even if none of mode, size and timestamp of them isn't
1015 changed on the filesystem (see also issue4583))
1015 changed on the filesystem (see also issue4583))
1016
1016
1017 $ cat >> $HGRCPATH <<EOF
1017 $ cat >> $HGRCPATH <<EOF
1018 > [fakedirstatewritetime]
1018 > [fakedirstatewritetime]
1019 > # emulate invoking dirstate.write() via repo.status()
1019 > # emulate invoking dirstate.write() via repo.status()
1020 > # at 2000-01-01 00:00
1020 > # at 2000-01-01 00:00
1021 > fakenow = 200001010000
1021 > fakenow = 200001010000
1022 > EOF
1022 > EOF
1023
1023
1024 $ beforemerge
1024 $ beforemerge
1025 [merge-tools]
1025 [merge-tools]
1026 false.whatever=
1026 false.whatever=
1027 true.priority=1
1027 true.priority=1
1028 true.executable=cat
1028 true.executable=cat
1029 # hg update -C 1
1029 # hg update -C 1
1030 $ hg update -q 0
1030 $ hg update -q 0
1031 $ f -s f
1031 $ f -s f
1032 f: size=17
1032 f: size=17
1033 $ touch -t 200001010000 f
1033 $ touch -t 200001010000 f
1034 $ hg debugrebuildstate
1034 $ hg debugrebuildstate
1035 $ cat >> $HGRCPATH <<EOF
1035 $ cat >> $HGRCPATH <<EOF
1036 > [extensions]
1036 > [extensions]
1037 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
1037 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
1038 > EOF
1038 > EOF
1039 $ hg revert -q -r 1 .
1039 $ hg revert -q -r 1 .
1040 $ cat >> $HGRCPATH <<EOF
1040 $ cat >> $HGRCPATH <<EOF
1041 > [extensions]
1041 > [extensions]
1042 > fakedirstatewritetime = !
1042 > fakedirstatewritetime = !
1043 > EOF
1043 > EOF
1044 $ f -s f
1044 $ f -s f
1045 f: size=17
1045 f: size=17
1046 $ touch -t 200001010000 f
1046 $ touch -t 200001010000 f
1047 $ hg status f
1047 $ hg status f
1048 M f
1048 M f
1049 $ hg update -r 2
1049 $ hg update -r 2
1050 merging f
1050 merging f
1051 revision 1
1051 revision 1
1052 space
1052 space
1053 revision 0
1053 revision 0
1054 space
1054 space
1055 revision 2
1055 revision 2
1056 space
1056 space
1057 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1057 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1058 $ aftermerge
1058 $ aftermerge
1059 # cat f
1059 # cat f
1060 revision 1
1060 revision 1
1061 space
1061 space
1062 # hg stat
1062 # hg stat
1063 M f
1063 M f
1064 # hg resolve --list
1064 # hg resolve --list
1065 R f
1065 R f
1066
1066
1067 update should also have --tool
1067 update should also have --tool
1068
1068
1069 $ beforemerge
1069 $ beforemerge
1070 [merge-tools]
1070 [merge-tools]
1071 false.whatever=
1071 false.whatever=
1072 true.priority=1
1072 true.priority=1
1073 true.executable=cat
1073 true.executable=cat
1074 # hg update -C 1
1074 # hg update -C 1
1075 $ hg update -q 0
1075 $ hg update -q 0
1076 $ f -s f
1076 $ f -s f
1077 f: size=17
1077 f: size=17
1078 $ touch -t 200001010000 f
1078 $ touch -t 200001010000 f
1079 $ hg debugrebuildstate
1079 $ hg debugrebuildstate
1080 $ cat >> $HGRCPATH <<EOF
1080 $ cat >> $HGRCPATH <<EOF
1081 > [extensions]
1081 > [extensions]
1082 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
1082 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
1083 > EOF
1083 > EOF
1084 $ hg revert -q -r 1 .
1084 $ hg revert -q -r 1 .
1085 $ cat >> $HGRCPATH <<EOF
1085 $ cat >> $HGRCPATH <<EOF
1086 > [extensions]
1086 > [extensions]
1087 > fakedirstatewritetime = !
1087 > fakedirstatewritetime = !
1088 > EOF
1088 > EOF
1089 $ f -s f
1089 $ f -s f
1090 f: size=17
1090 f: size=17
1091 $ touch -t 200001010000 f
1091 $ touch -t 200001010000 f
1092 $ hg status f
1092 $ hg status f
1093 M f
1093 M f
1094 $ hg update -r 2 --tool false
1094 $ hg update -r 2 --tool false
1095 merging f
1095 merging f
1096 merging f failed!
1096 merging f failed!
1097 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1097 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1098 use 'hg resolve' to retry unresolved file merges
1098 use 'hg resolve' to retry unresolved file merges
1099 [1]
1099 [1]
1100 $ aftermerge
1100 $ aftermerge
1101 # cat f
1101 # cat f
1102 revision 1
1102 revision 1
1103 space
1103 space
1104 # hg stat
1104 # hg stat
1105 M f
1105 M f
1106 ? f.orig
1106 ? f.orig
1107 # hg resolve --list
1107 # hg resolve --list
1108 U f
1108 U f
1109
1109
1110 Default is silent simplemerge:
1110 Default is silent simplemerge:
1111
1111
1112 $ beforemerge
1112 $ beforemerge
1113 [merge-tools]
1113 [merge-tools]
1114 false.whatever=
1114 false.whatever=
1115 true.priority=1
1115 true.priority=1
1116 true.executable=cat
1116 true.executable=cat
1117 # hg update -C 1
1117 # hg update -C 1
1118 $ hg merge -r 3
1118 $ hg merge -r 3
1119 merging f
1119 merging f
1120 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1120 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1121 (branch merge, don't forget to commit)
1121 (branch merge, don't forget to commit)
1122 $ aftermerge
1122 $ aftermerge
1123 # cat f
1123 # cat f
1124 revision 1
1124 revision 1
1125 space
1125 space
1126 revision 3
1126 revision 3
1127 # hg stat
1127 # hg stat
1128 M f
1128 M f
1129 # hg resolve --list
1129 # hg resolve --list
1130 R f
1130 R f
1131
1131
1132 .premerge=True is same:
1132 .premerge=True is same:
1133
1133
1134 $ beforemerge
1134 $ beforemerge
1135 [merge-tools]
1135 [merge-tools]
1136 false.whatever=
1136 false.whatever=
1137 true.priority=1
1137 true.priority=1
1138 true.executable=cat
1138 true.executable=cat
1139 # hg update -C 1
1139 # hg update -C 1
1140 $ hg merge -r 3 --config merge-tools.true.premerge=True
1140 $ hg merge -r 3 --config merge-tools.true.premerge=True
1141 merging f
1141 merging f
1142 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1142 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1143 (branch merge, don't forget to commit)
1143 (branch merge, don't forget to commit)
1144 $ aftermerge
1144 $ aftermerge
1145 # cat f
1145 # cat f
1146 revision 1
1146 revision 1
1147 space
1147 space
1148 revision 3
1148 revision 3
1149 # hg stat
1149 # hg stat
1150 M f
1150 M f
1151 # hg resolve --list
1151 # hg resolve --list
1152 R f
1152 R f
1153
1153
1154 .premerge=False executes merge-tool:
1154 .premerge=False executes merge-tool:
1155
1155
1156 $ beforemerge
1156 $ beforemerge
1157 [merge-tools]
1157 [merge-tools]
1158 false.whatever=
1158 false.whatever=
1159 true.priority=1
1159 true.priority=1
1160 true.executable=cat
1160 true.executable=cat
1161 # hg update -C 1
1161 # hg update -C 1
1162 $ hg merge -r 3 --config merge-tools.true.premerge=False
1162 $ hg merge -r 3 --config merge-tools.true.premerge=False
1163 merging f
1163 merging f
1164 revision 1
1164 revision 1
1165 space
1165 space
1166 revision 0
1166 revision 0
1167 space
1167 space
1168 revision 0
1168 revision 0
1169 space
1169 space
1170 revision 3
1170 revision 3
1171 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1171 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1172 (branch merge, don't forget to commit)
1172 (branch merge, don't forget to commit)
1173 $ aftermerge
1173 $ aftermerge
1174 # cat f
1174 # cat f
1175 revision 1
1175 revision 1
1176 space
1176 space
1177 # hg stat
1177 # hg stat
1178 M f
1178 M f
1179 # hg resolve --list
1179 # hg resolve --list
1180 R f
1180 R f
1181
1181
1182 premerge=keep keeps conflict markers in:
1182 premerge=keep keeps conflict markers in:
1183
1183
1184 $ beforemerge
1184 $ beforemerge
1185 [merge-tools]
1185 [merge-tools]
1186 false.whatever=
1186 false.whatever=
1187 true.priority=1
1187 true.priority=1
1188 true.executable=cat
1188 true.executable=cat
1189 # hg update -C 1
1189 # hg update -C 1
1190 $ hg merge -r 4 --config merge-tools.true.premerge=keep
1190 $ hg merge -r 4 --config merge-tools.true.premerge=keep
1191 merging f
1191 merging f
1192 <<<<<<< working copy: ef83787e2614 - test: revision 1
1192 <<<<<<< working copy: ef83787e2614 - test: revision 1
1193 revision 1
1193 revision 1
1194 space
1194 space
1195 =======
1195 =======
1196 revision 4
1196 revision 4
1197 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1197 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1198 revision 0
1198 revision 0
1199 space
1199 space
1200 revision 4
1200 revision 4
1201 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1201 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1202 (branch merge, don't forget to commit)
1202 (branch merge, don't forget to commit)
1203 $ aftermerge
1203 $ aftermerge
1204 # cat f
1204 # cat f
1205 <<<<<<< working copy: ef83787e2614 - test: revision 1
1205 <<<<<<< working copy: ef83787e2614 - test: revision 1
1206 revision 1
1206 revision 1
1207 space
1207 space
1208 =======
1208 =======
1209 revision 4
1209 revision 4
1210 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1210 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1211 # hg stat
1211 # hg stat
1212 M f
1212 M f
1213 # hg resolve --list
1213 # hg resolve --list
1214 R f
1214 R f
1215
1215
1216 with premerge=keep and $output in tool args, $local does not have markers:
1217
1218 $ beforemerge
1219 [merge-tools]
1220 false.whatever=
1221 true.priority=1
1222 true.executable=cat
1223 # hg update -C 1
1224 $ hg merge -r 4 --config merge-tools.true.premerge=keep --config 'merge-tools.true.args=$base $local $other $output'
1225 merging f
1226 revision 0
1227 space
1228 revision 1
1229 space
1230 revision 4
1231 <<<<<<< working copy: ef83787e2614 - test: revision 1
1232 revision 1
1233 space
1234 =======
1235 revision 4
1236 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1237 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1238 (branch merge, don't forget to commit)
1239 $ aftermerge
1240 # cat f
1241 <<<<<<< working copy: ef83787e2614 - test: revision 1
1242 revision 1
1243 space
1244 =======
1245 revision 4
1246 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1247 # hg stat
1248 M f
1249 # hg resolve --list
1250 R f
1251
1216 premerge=keep-merge3 keeps conflict markers with base content:
1252 premerge=keep-merge3 keeps conflict markers with base content:
1217
1253
1218 $ beforemerge
1254 $ beforemerge
1219 [merge-tools]
1255 [merge-tools]
1220 false.whatever=
1256 false.whatever=
1221 true.priority=1
1257 true.priority=1
1222 true.executable=cat
1258 true.executable=cat
1223 # hg update -C 1
1259 # hg update -C 1
1224 $ hg merge -r 4 --config merge-tools.true.premerge=keep-merge3
1260 $ hg merge -r 4 --config merge-tools.true.premerge=keep-merge3
1225 merging f
1261 merging f
1226 <<<<<<< working copy: ef83787e2614 - test: revision 1
1262 <<<<<<< working copy: ef83787e2614 - test: revision 1
1227 revision 1
1263 revision 1
1228 space
1264 space
1229 ||||||| common ancestor: ffd2bda21d6e - test: revision 0
1265 ||||||| common ancestor: ffd2bda21d6e - test: revision 0
1230 revision 0
1266 revision 0
1231 space
1267 space
1232 =======
1268 =======
1233 revision 4
1269 revision 4
1234 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1270 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1235 revision 0
1271 revision 0
1236 space
1272 space
1237 revision 4
1273 revision 4
1238 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1274 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1239 (branch merge, don't forget to commit)
1275 (branch merge, don't forget to commit)
1240 $ aftermerge
1276 $ aftermerge
1241 # cat f
1277 # cat f
1242 <<<<<<< working copy: ef83787e2614 - test: revision 1
1278 <<<<<<< working copy: ef83787e2614 - test: revision 1
1243 revision 1
1279 revision 1
1244 space
1280 space
1245 ||||||| common ancestor: ffd2bda21d6e - test: revision 0
1281 ||||||| common ancestor: ffd2bda21d6e - test: revision 0
1246 revision 0
1282 revision 0
1247 space
1283 space
1248 =======
1284 =======
1249 revision 4
1285 revision 4
1250 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1286 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1251 # hg stat
1287 # hg stat
1252 M f
1288 M f
1253 # hg resolve --list
1289 # hg resolve --list
1254 R f
1290 R f
1255
1291
1256 premerge=keep-mergediff keeps conflict markers with base content:
1292 premerge=keep-mergediff keeps conflict markers with base content:
1257
1293
1258 $ beforemerge
1294 $ beforemerge
1259 [merge-tools]
1295 [merge-tools]
1260 false.whatever=
1296 false.whatever=
1261 true.priority=1
1297 true.priority=1
1262 true.executable=cat
1298 true.executable=cat
1263 # hg update -C 1
1299 # hg update -C 1
1264 $ hg merge -r 4 --config merge-tools.true.premerge=keep-mergediff
1300 $ hg merge -r 4 --config merge-tools.true.premerge=keep-mergediff
1265 merging f
1301 merging f
1266 <<<<<<<
1302 <<<<<<<
1267 ------- common ancestor: ffd2bda21d6e - test: revision 0
1303 ------- common ancestor: ffd2bda21d6e - test: revision 0
1268 +++++++ working copy: ef83787e2614 - test: revision 1
1304 +++++++ working copy: ef83787e2614 - test: revision 1
1269 -revision 0
1305 -revision 0
1270 +revision 1
1306 +revision 1
1271 space
1307 space
1272 ======= merge rev: 81448d39c9a0 - test: revision 4
1308 ======= merge rev: 81448d39c9a0 - test: revision 4
1273 revision 4
1309 revision 4
1274 >>>>>>>
1310 >>>>>>>
1275 revision 0
1311 revision 0
1276 space
1312 space
1277 revision 4
1313 revision 4
1278 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1314 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1279 (branch merge, don't forget to commit)
1315 (branch merge, don't forget to commit)
1280 $ aftermerge
1316 $ aftermerge
1281 # cat f
1317 # cat f
1282 <<<<<<<
1318 <<<<<<<
1283 ------- common ancestor: ffd2bda21d6e - test: revision 0
1319 ------- common ancestor: ffd2bda21d6e - test: revision 0
1284 +++++++ working copy: ef83787e2614 - test: revision 1
1320 +++++++ working copy: ef83787e2614 - test: revision 1
1285 -revision 0
1321 -revision 0
1286 +revision 1
1322 +revision 1
1287 space
1323 space
1288 ======= merge rev: 81448d39c9a0 - test: revision 4
1324 ======= merge rev: 81448d39c9a0 - test: revision 4
1289 revision 4
1325 revision 4
1290 >>>>>>>
1326 >>>>>>>
1291 # hg stat
1327 # hg stat
1292 M f
1328 M f
1293 # hg resolve --list
1329 # hg resolve --list
1294 R f
1330 R f
1295
1331
1296 premerge=keep respects ui.mergemarkers=basic:
1332 premerge=keep respects ui.mergemarkers=basic:
1297
1333
1298 $ beforemerge
1334 $ beforemerge
1299 [merge-tools]
1335 [merge-tools]
1300 false.whatever=
1336 false.whatever=
1301 true.priority=1
1337 true.priority=1
1302 true.executable=cat
1338 true.executable=cat
1303 # hg update -C 1
1339 # hg update -C 1
1304 $ hg merge -r 4 --config merge-tools.true.premerge=keep --config ui.mergemarkers=basic
1340 $ hg merge -r 4 --config merge-tools.true.premerge=keep --config ui.mergemarkers=basic
1305 merging f
1341 merging f
1306 <<<<<<< working copy
1342 <<<<<<< working copy
1307 revision 1
1343 revision 1
1308 space
1344 space
1309 =======
1345 =======
1310 revision 4
1346 revision 4
1311 >>>>>>> merge rev
1347 >>>>>>> merge rev
1312 revision 0
1348 revision 0
1313 space
1349 space
1314 revision 4
1350 revision 4
1315 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1351 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1316 (branch merge, don't forget to commit)
1352 (branch merge, don't forget to commit)
1317 $ aftermerge
1353 $ aftermerge
1318 # cat f
1354 # cat f
1319 <<<<<<< working copy
1355 <<<<<<< working copy
1320 revision 1
1356 revision 1
1321 space
1357 space
1322 =======
1358 =======
1323 revision 4
1359 revision 4
1324 >>>>>>> merge rev
1360 >>>>>>> merge rev
1325 # hg stat
1361 # hg stat
1326 M f
1362 M f
1327 # hg resolve --list
1363 # hg resolve --list
1328 R f
1364 R f
1329
1365
1330 premerge=keep ignores ui.mergemarkers=basic if true.mergemarkers=detailed:
1366 premerge=keep ignores ui.mergemarkers=basic if true.mergemarkers=detailed:
1331
1367
1332 $ beforemerge
1368 $ beforemerge
1333 [merge-tools]
1369 [merge-tools]
1334 false.whatever=
1370 false.whatever=
1335 true.priority=1
1371 true.priority=1
1336 true.executable=cat
1372 true.executable=cat
1337 # hg update -C 1
1373 # hg update -C 1
1338 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1374 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1339 > --config ui.mergemarkers=basic \
1375 > --config ui.mergemarkers=basic \
1340 > --config merge-tools.true.mergemarkers=detailed
1376 > --config merge-tools.true.mergemarkers=detailed
1341 merging f
1377 merging f
1342 <<<<<<< working copy: ef83787e2614 - test: revision 1
1378 <<<<<<< working copy: ef83787e2614 - test: revision 1
1343 revision 1
1379 revision 1
1344 space
1380 space
1345 =======
1381 =======
1346 revision 4
1382 revision 4
1347 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1383 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1348 revision 0
1384 revision 0
1349 space
1385 space
1350 revision 4
1386 revision 4
1351 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1387 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1352 (branch merge, don't forget to commit)
1388 (branch merge, don't forget to commit)
1353 $ aftermerge
1389 $ aftermerge
1354 # cat f
1390 # cat f
1355 <<<<<<< working copy: ef83787e2614 - test: revision 1
1391 <<<<<<< working copy: ef83787e2614 - test: revision 1
1356 revision 1
1392 revision 1
1357 space
1393 space
1358 =======
1394 =======
1359 revision 4
1395 revision 4
1360 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1396 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1361 # hg stat
1397 # hg stat
1362 M f
1398 M f
1363 # hg resolve --list
1399 # hg resolve --list
1364 R f
1400 R f
1365
1401
1366 premerge=keep respects ui.mergemarkertemplate instead of
1402 premerge=keep respects ui.mergemarkertemplate instead of
1367 true.mergemarkertemplate if true.mergemarkers=basic:
1403 true.mergemarkertemplate if true.mergemarkers=basic:
1368
1404
1369 $ beforemerge
1405 $ beforemerge
1370 [merge-tools]
1406 [merge-tools]
1371 false.whatever=
1407 false.whatever=
1372 true.priority=1
1408 true.priority=1
1373 true.executable=cat
1409 true.executable=cat
1374 # hg update -C 1
1410 # hg update -C 1
1375 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1411 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1376 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1412 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1377 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}'
1413 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}'
1378 merging f
1414 merging f
1379 <<<<<<< working copy: uitmpl 1
1415 <<<<<<< working copy: uitmpl 1
1380 revision 1
1416 revision 1
1381 space
1417 space
1382 =======
1418 =======
1383 revision 4
1419 revision 4
1384 >>>>>>> merge rev: uitmpl 4
1420 >>>>>>> merge rev: uitmpl 4
1385 revision 0
1421 revision 0
1386 space
1422 space
1387 revision 4
1423 revision 4
1388 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1424 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1389 (branch merge, don't forget to commit)
1425 (branch merge, don't forget to commit)
1390 $ aftermerge
1426 $ aftermerge
1391 # cat f
1427 # cat f
1392 <<<<<<< working copy: uitmpl 1
1428 <<<<<<< working copy: uitmpl 1
1393 revision 1
1429 revision 1
1394 space
1430 space
1395 =======
1431 =======
1396 revision 4
1432 revision 4
1397 >>>>>>> merge rev: uitmpl 4
1433 >>>>>>> merge rev: uitmpl 4
1398 # hg stat
1434 # hg stat
1399 M f
1435 M f
1400 # hg resolve --list
1436 # hg resolve --list
1401 R f
1437 R f
1402
1438
1403 premerge=keep respects true.mergemarkertemplate instead of
1439 premerge=keep respects true.mergemarkertemplate instead of
1404 true.mergemarkertemplate if true.mergemarkers=detailed:
1440 true.mergemarkertemplate if true.mergemarkers=detailed:
1405
1441
1406 $ beforemerge
1442 $ beforemerge
1407 [merge-tools]
1443 [merge-tools]
1408 false.whatever=
1444 false.whatever=
1409 true.priority=1
1445 true.priority=1
1410 true.executable=cat
1446 true.executable=cat
1411 # hg update -C 1
1447 # hg update -C 1
1412 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1448 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1413 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1449 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1414 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1450 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1415 > --config merge-tools.true.mergemarkers=detailed
1451 > --config merge-tools.true.mergemarkers=detailed
1416 merging f
1452 merging f
1417 <<<<<<< working copy: tooltmpl ef83787e2614
1453 <<<<<<< working copy: tooltmpl ef83787e2614
1418 revision 1
1454 revision 1
1419 space
1455 space
1420 =======
1456 =======
1421 revision 4
1457 revision 4
1422 >>>>>>> merge rev: tooltmpl 81448d39c9a0
1458 >>>>>>> merge rev: tooltmpl 81448d39c9a0
1423 revision 0
1459 revision 0
1424 space
1460 space
1425 revision 4
1461 revision 4
1426 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1462 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1427 (branch merge, don't forget to commit)
1463 (branch merge, don't forget to commit)
1428 $ aftermerge
1464 $ aftermerge
1429 # cat f
1465 # cat f
1430 <<<<<<< working copy: tooltmpl ef83787e2614
1466 <<<<<<< working copy: tooltmpl ef83787e2614
1431 revision 1
1467 revision 1
1432 space
1468 space
1433 =======
1469 =======
1434 revision 4
1470 revision 4
1435 >>>>>>> merge rev: tooltmpl 81448d39c9a0
1471 >>>>>>> merge rev: tooltmpl 81448d39c9a0
1436 # hg stat
1472 # hg stat
1437 M f
1473 M f
1438 # hg resolve --list
1474 # hg resolve --list
1439 R f
1475 R f
1440
1476
1441 Tool execution
1477 Tool execution
1442
1478
1443 set tools.args explicit to include $base $local $other $output:
1479 set tools.args explicit to include $base $local $other $output:
1444
1480
1445 $ beforemerge
1481 $ beforemerge
1446 [merge-tools]
1482 [merge-tools]
1447 false.whatever=
1483 false.whatever=
1448 true.priority=1
1484 true.priority=1
1449 true.executable=cat
1485 true.executable=cat
1450 # hg update -C 1
1486 # hg update -C 1
1451 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
1487 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
1452 > | sed 's,==> .* <==,==> ... <==,g'
1488 > | sed 's,==> .* <==,==> ... <==,g'
1453 merging f
1489 merging f
1454 ==> ... <==
1490 ==> ... <==
1455 revision 0
1491 revision 0
1456 space
1492 space
1457
1493
1458 ==> ... <==
1494 ==> ... <==
1459 revision 1
1495 revision 1
1460 space
1496 space
1461
1497
1462 ==> ... <==
1498 ==> ... <==
1463 revision 2
1499 revision 2
1464 space
1500 space
1465
1501
1466 ==> ... <==
1502 ==> ... <==
1467 revision 1
1503 revision 1
1468 space
1504 space
1469 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1505 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1470 (branch merge, don't forget to commit)
1506 (branch merge, don't forget to commit)
1471 $ aftermerge
1507 $ aftermerge
1472 # cat f
1508 # cat f
1473 revision 1
1509 revision 1
1474 space
1510 space
1475 # hg stat
1511 # hg stat
1476 M f
1512 M f
1477 # hg resolve --list
1513 # hg resolve --list
1478 R f
1514 R f
1479
1515
1480 Merge with "echo mergeresult > $local":
1516 Merge with "echo mergeresult > $local":
1481
1517
1482 $ beforemerge
1518 $ beforemerge
1483 [merge-tools]
1519 [merge-tools]
1484 false.whatever=
1520 false.whatever=
1485 true.priority=1
1521 true.priority=1
1486 true.executable=cat
1522 true.executable=cat
1487 # hg update -C 1
1523 # hg update -C 1
1488 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
1524 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
1489 merging f
1525 merging f
1490 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1526 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1491 (branch merge, don't forget to commit)
1527 (branch merge, don't forget to commit)
1492 $ aftermerge
1528 $ aftermerge
1493 # cat f
1529 # cat f
1494 mergeresult
1530 mergeresult
1495 # hg stat
1531 # hg stat
1496 M f
1532 M f
1497 # hg resolve --list
1533 # hg resolve --list
1498 R f
1534 R f
1499
1535
1500 - and $local is the file f:
1536 - and $local is the file f:
1501
1537
1502 $ beforemerge
1538 $ beforemerge
1503 [merge-tools]
1539 [merge-tools]
1504 false.whatever=
1540 false.whatever=
1505 true.priority=1
1541 true.priority=1
1506 true.executable=cat
1542 true.executable=cat
1507 # hg update -C 1
1543 # hg update -C 1
1508 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
1544 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
1509 merging f
1545 merging f
1510 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1546 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1511 (branch merge, don't forget to commit)
1547 (branch merge, don't forget to commit)
1512 $ aftermerge
1548 $ aftermerge
1513 # cat f
1549 # cat f
1514 mergeresult
1550 mergeresult
1515 # hg stat
1551 # hg stat
1516 M f
1552 M f
1517 # hg resolve --list
1553 # hg resolve --list
1518 R f
1554 R f
1519
1555
1520 Merge with "echo mergeresult > $output" - the variable is a bit magic:
1556 Merge with "echo mergeresult > $output" - the variable is a bit magic:
1521
1557
1522 $ beforemerge
1558 $ beforemerge
1523 [merge-tools]
1559 [merge-tools]
1524 false.whatever=
1560 false.whatever=
1525 true.priority=1
1561 true.priority=1
1526 true.executable=cat
1562 true.executable=cat
1527 # hg update -C 1
1563 # hg update -C 1
1528 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
1564 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
1529 merging f
1565 merging f
1530 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1566 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1531 (branch merge, don't forget to commit)
1567 (branch merge, don't forget to commit)
1532 $ aftermerge
1568 $ aftermerge
1533 # cat f
1569 # cat f
1534 mergeresult
1570 mergeresult
1535 # hg stat
1571 # hg stat
1536 M f
1572 M f
1537 # hg resolve --list
1573 # hg resolve --list
1538 R f
1574 R f
1539
1575
1540 Merge using tool with a path that must be quoted:
1576 Merge using tool with a path that must be quoted:
1541
1577
1542 $ beforemerge
1578 $ beforemerge
1543 [merge-tools]
1579 [merge-tools]
1544 false.whatever=
1580 false.whatever=
1545 true.priority=1
1581 true.priority=1
1546 true.executable=cat
1582 true.executable=cat
1547 # hg update -C 1
1583 # hg update -C 1
1548 $ cat <<EOF > 'my merge tool'
1584 $ cat <<EOF > 'my merge tool'
1549 > cat "\$1" "\$2" "\$3" > "\$4"
1585 > cat "\$1" "\$2" "\$3" > "\$4"
1550 > EOF
1586 > EOF
1551 $ hg --config merge-tools.true.executable='sh' \
1587 $ hg --config merge-tools.true.executable='sh' \
1552 > --config merge-tools.true.args='"./my merge tool" $base $local $other $output' \
1588 > --config merge-tools.true.args='"./my merge tool" $base $local $other $output' \
1553 > merge -r 2
1589 > merge -r 2
1554 merging f
1590 merging f
1555 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1591 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1556 (branch merge, don't forget to commit)
1592 (branch merge, don't forget to commit)
1557 $ rm -f 'my merge tool'
1593 $ rm -f 'my merge tool'
1558 $ aftermerge
1594 $ aftermerge
1559 # cat f
1595 # cat f
1560 revision 0
1596 revision 0
1561 space
1597 space
1562 revision 1
1598 revision 1
1563 space
1599 space
1564 revision 2
1600 revision 2
1565 space
1601 space
1566 # hg stat
1602 # hg stat
1567 M f
1603 M f
1568 # hg resolve --list
1604 # hg resolve --list
1569 R f
1605 R f
1570
1606
1571 Merge using a tool that supports labellocal, labelother, and labelbase, checking
1607 Merge using a tool that supports labellocal, labelother, and labelbase, checking
1572 that they're quoted properly as well. This is using the default 'basic'
1608 that they're quoted properly as well. This is using the default 'basic'
1573 mergemarkers even though ui.mergemarkers is 'detailed', so it's ignoring both
1609 mergemarkers even though ui.mergemarkers is 'detailed', so it's ignoring both
1574 mergemarkertemplate settings:
1610 mergemarkertemplate settings:
1575
1611
1576 $ beforemerge
1612 $ beforemerge
1577 [merge-tools]
1613 [merge-tools]
1578 false.whatever=
1614 false.whatever=
1579 true.priority=1
1615 true.priority=1
1580 true.executable=cat
1616 true.executable=cat
1581 # hg update -C 1
1617 # hg update -C 1
1582 $ cat <<EOF > printargs_merge_tool
1618 $ cat <<EOF > printargs_merge_tool
1583 > while test \$# -gt 0; do echo arg: \""\$1"\"; shift; done
1619 > while test \$# -gt 0; do echo arg: \""\$1"\"; shift; done
1584 > EOF
1620 > EOF
1585 $ hg --config merge-tools.true.executable='sh' \
1621 $ hg --config merge-tools.true.executable='sh' \
1586 > --config merge-tools.true.args='./printargs_merge_tool ll:$labellocal lo: $labelother lb:$labelbase": "$base' \
1622 > --config merge-tools.true.args='./printargs_merge_tool ll:$labellocal lo: $labelother lb:$labelbase": "$base' \
1587 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1623 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1588 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1624 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1589 > --config ui.mergemarkers=detailed \
1625 > --config ui.mergemarkers=detailed \
1590 > merge -r 2
1626 > merge -r 2
1591 merging f
1627 merging f
1592 arg: "ll:working copy"
1628 arg: "ll:working copy"
1593 arg: "lo:"
1629 arg: "lo:"
1594 arg: "merge rev"
1630 arg: "merge rev"
1595 arg: "lb:common ancestor*/f~base" (glob) (no-windows !)
1631 arg: "lb:common ancestor*/f~base" (glob) (no-windows !)
1596 arg: "lb:common ancestor*\f~base" (glob) (windows !)
1632 arg: "lb:common ancestor*\f~base" (glob) (windows !)
1597 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1633 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1598 (branch merge, don't forget to commit)
1634 (branch merge, don't forget to commit)
1599 $ rm -f 'printargs_merge_tool'
1635 $ rm -f 'printargs_merge_tool'
1600
1636
1601 Merge using a tool that supports labellocal, labelother, and labelbase, checking
1637 Merge using a tool that supports labellocal, labelother, and labelbase, checking
1602 that they're quoted properly as well. This is using 'detailed' mergemarkers,
1638 that they're quoted properly as well. This is using 'detailed' mergemarkers,
1603 even though ui.mergemarkers is 'basic', and using the tool's
1639 even though ui.mergemarkers is 'basic', and using the tool's
1604 mergemarkertemplate:
1640 mergemarkertemplate:
1605
1641
1606 $ beforemerge
1642 $ beforemerge
1607 [merge-tools]
1643 [merge-tools]
1608 false.whatever=
1644 false.whatever=
1609 true.priority=1
1645 true.priority=1
1610 true.executable=cat
1646 true.executable=cat
1611 # hg update -C 1
1647 # hg update -C 1
1612 $ cat <<EOF > printargs_merge_tool
1648 $ cat <<EOF > printargs_merge_tool
1613 > while test \$# -gt 0; do echo arg: \""\$1"\"; shift; done
1649 > while test \$# -gt 0; do echo arg: \""\$1"\"; shift; done
1614 > EOF
1650 > EOF
1615 $ hg --config merge-tools.true.executable='sh' \
1651 $ hg --config merge-tools.true.executable='sh' \
1616 > --config merge-tools.true.args='./printargs_merge_tool ll:$labellocal lo: $labelother lb:$labelbase": "$base' \
1652 > --config merge-tools.true.args='./printargs_merge_tool ll:$labellocal lo: $labelother lb:$labelbase": "$base' \
1617 > --config merge-tools.true.mergemarkers=detailed \
1653 > --config merge-tools.true.mergemarkers=detailed \
1618 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1654 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1619 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1655 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1620 > --config ui.mergemarkers=basic \
1656 > --config ui.mergemarkers=basic \
1621 > merge -r 2
1657 > merge -r 2
1622 merging f
1658 merging f
1623 arg: "ll:working copy: tooltmpl ef83787e2614"
1659 arg: "ll:working copy: tooltmpl ef83787e2614"
1624 arg: "lo:"
1660 arg: "lo:"
1625 arg: "merge rev: tooltmpl 0185f4e0cf02"
1661 arg: "merge rev: tooltmpl 0185f4e0cf02"
1626 arg: "lb:common ancestor*/f~base" (glob) (no-windows !)
1662 arg: "lb:common ancestor*/f~base" (glob) (no-windows !)
1627 arg: "lb:common ancestor*\f~base" (glob) (windows !)
1663 arg: "lb:common ancestor*\f~base" (glob) (windows !)
1628 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1664 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1629 (branch merge, don't forget to commit)
1665 (branch merge, don't forget to commit)
1630 $ rm -f 'printargs_merge_tool'
1666 $ rm -f 'printargs_merge_tool'
1631
1667
1632 The merge tool still gets labellocal and labelother as 'basic' even when
1668 The merge tool still gets labellocal and labelother as 'basic' even when
1633 premerge=keep is used and has 'detailed' markers:
1669 premerge=keep is used and has 'detailed' markers:
1634
1670
1635 $ beforemerge
1671 $ beforemerge
1636 [merge-tools]
1672 [merge-tools]
1637 false.whatever=
1673 false.whatever=
1638 true.priority=1
1674 true.priority=1
1639 true.executable=cat
1675 true.executable=cat
1640 # hg update -C 1
1676 # hg update -C 1
1641 $ cat <<EOF > mytool
1677 $ cat <<EOF > mytool
1642 > echo labellocal: \""\$1"\"
1678 > echo labellocal: \""\$1"\"
1643 > echo labelother: \""\$2"\"
1679 > echo labelother: \""\$2"\"
1644 > echo "output (arg)": \""\$3"\"
1680 > echo "output (arg)": \""\$3"\"
1645 > echo "output (contents)":
1681 > echo "output (contents)":
1646 > cat "\$3"
1682 > cat "\$3"
1647 > EOF
1683 > EOF
1648 $ hg --config merge-tools.true.executable='sh' \
1684 $ hg --config merge-tools.true.executable='sh' \
1649 > --config merge-tools.true.args='mytool $labellocal $labelother $output' \
1685 > --config merge-tools.true.args='mytool $labellocal $labelother $output' \
1650 > --config merge-tools.true.premerge=keep \
1686 > --config merge-tools.true.premerge=keep \
1651 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1687 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1652 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1688 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1653 > --config ui.mergemarkers=detailed \
1689 > --config ui.mergemarkers=detailed \
1654 > merge -r 2
1690 > merge -r 2
1655 merging f
1691 merging f
1656 labellocal: "working copy"
1692 labellocal: "working copy"
1657 labelother: "merge rev"
1693 labelother: "merge rev"
1658 output (arg): "$TESTTMP/repo/f"
1694 output (arg): "$TESTTMP/repo/f"
1659 output (contents):
1695 output (contents):
1660 <<<<<<< working copy: uitmpl 1
1696 <<<<<<< working copy: uitmpl 1
1661 revision 1
1697 revision 1
1662 =======
1698 =======
1663 revision 2
1699 revision 2
1664 >>>>>>> merge rev: uitmpl 2
1700 >>>>>>> merge rev: uitmpl 2
1665 space
1701 space
1666 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1702 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1667 (branch merge, don't forget to commit)
1703 (branch merge, don't forget to commit)
1668 $ rm -f 'mytool'
1704 $ rm -f 'mytool'
1669
1705
1670 premerge=keep uses the *tool's* mergemarkertemplate if tool's
1706 premerge=keep uses the *tool's* mergemarkertemplate if tool's
1671 mergemarkers=detailed; labellocal and labelother also use the tool's template
1707 mergemarkers=detailed; labellocal and labelother also use the tool's template
1672
1708
1673 $ beforemerge
1709 $ beforemerge
1674 [merge-tools]
1710 [merge-tools]
1675 false.whatever=
1711 false.whatever=
1676 true.priority=1
1712 true.priority=1
1677 true.executable=cat
1713 true.executable=cat
1678 # hg update -C 1
1714 # hg update -C 1
1679 $ cat <<EOF > mytool
1715 $ cat <<EOF > mytool
1680 > echo labellocal: \""\$1"\"
1716 > echo labellocal: \""\$1"\"
1681 > echo labelother: \""\$2"\"
1717 > echo labelother: \""\$2"\"
1682 > echo "output (arg)": \""\$3"\"
1718 > echo "output (arg)": \""\$3"\"
1683 > echo "output (contents)":
1719 > echo "output (contents)":
1684 > cat "\$3"
1720 > cat "\$3"
1685 > EOF
1721 > EOF
1686 $ hg --config merge-tools.true.executable='sh' \
1722 $ hg --config merge-tools.true.executable='sh' \
1687 > --config merge-tools.true.args='mytool $labellocal $labelother $output' \
1723 > --config merge-tools.true.args='mytool $labellocal $labelother $output' \
1688 > --config merge-tools.true.premerge=keep \
1724 > --config merge-tools.true.premerge=keep \
1689 > --config merge-tools.true.mergemarkers=detailed \
1725 > --config merge-tools.true.mergemarkers=detailed \
1690 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1726 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1691 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1727 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1692 > --config ui.mergemarkers=detailed \
1728 > --config ui.mergemarkers=detailed \
1693 > merge -r 2
1729 > merge -r 2
1694 merging f
1730 merging f
1695 labellocal: "working copy: tooltmpl ef83787e2614"
1731 labellocal: "working copy: tooltmpl ef83787e2614"
1696 labelother: "merge rev: tooltmpl 0185f4e0cf02"
1732 labelother: "merge rev: tooltmpl 0185f4e0cf02"
1697 output (arg): "$TESTTMP/repo/f"
1733 output (arg): "$TESTTMP/repo/f"
1698 output (contents):
1734 output (contents):
1699 <<<<<<< working copy: tooltmpl ef83787e2614
1735 <<<<<<< working copy: tooltmpl ef83787e2614
1700 revision 1
1736 revision 1
1701 =======
1737 =======
1702 revision 2
1738 revision 2
1703 >>>>>>> merge rev: tooltmpl 0185f4e0cf02
1739 >>>>>>> merge rev: tooltmpl 0185f4e0cf02
1704 space
1740 space
1705 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1741 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1706 (branch merge, don't forget to commit)
1742 (branch merge, don't forget to commit)
1707 $ rm -f 'mytool'
1743 $ rm -f 'mytool'
1708
1744
1709 Issue3581: Merging a filename that needs to be quoted
1745 Issue3581: Merging a filename that needs to be quoted
1710 (This test doesn't work on Windows filesystems even on Linux, so check
1746 (This test doesn't work on Windows filesystems even on Linux, so check
1711 for Unix-like permission)
1747 for Unix-like permission)
1712
1748
1713 #if unix-permissions
1749 #if unix-permissions
1714 $ beforemerge
1750 $ beforemerge
1715 [merge-tools]
1751 [merge-tools]
1716 false.whatever=
1752 false.whatever=
1717 true.priority=1
1753 true.priority=1
1718 true.executable=cat
1754 true.executable=cat
1719 # hg update -C 1
1755 # hg update -C 1
1720 $ echo "revision 5" > '"; exit 1; echo "'
1756 $ echo "revision 5" > '"; exit 1; echo "'
1721 $ hg commit -Am "revision 5"
1757 $ hg commit -Am "revision 5"
1722 adding "; exit 1; echo "
1758 adding "; exit 1; echo "
1723 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1759 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1724 $ hg update -C 1 > /dev/null
1760 $ hg update -C 1 > /dev/null
1725 $ echo "revision 6" > '"; exit 1; echo "'
1761 $ echo "revision 6" > '"; exit 1; echo "'
1726 $ hg commit -Am "revision 6"
1762 $ hg commit -Am "revision 6"
1727 adding "; exit 1; echo "
1763 adding "; exit 1; echo "
1728 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1764 warning: filename contains '"', which is reserved on Windows: '"; exit 1; echo "'
1729 created new head
1765 created new head
1730 $ hg merge --config merge-tools.true.executable="true" -r 5
1766 $ hg merge --config merge-tools.true.executable="true" -r 5
1731 merging "; exit 1; echo "
1767 merging "; exit 1; echo "
1732 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1768 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1733 (branch merge, don't forget to commit)
1769 (branch merge, don't forget to commit)
1734 $ hg update -C 1 > /dev/null
1770 $ hg update -C 1 > /dev/null
1735
1771
1736 #else
1772 #else
1737
1773
1738 Match the non-portable filename commits above for test stability
1774 Match the non-portable filename commits above for test stability
1739
1775
1740 $ hg import --bypass -q - << EOF
1776 $ hg import --bypass -q - << EOF
1741 > # HG changeset patch
1777 > # HG changeset patch
1742 > revision 5
1778 > revision 5
1743 >
1779 >
1744 > diff --git a/"; exit 1; echo " b/"; exit 1; echo "
1780 > diff --git a/"; exit 1; echo " b/"; exit 1; echo "
1745 > new file mode 100644
1781 > new file mode 100644
1746 > --- /dev/null
1782 > --- /dev/null
1747 > +++ b/"; exit 1; echo "
1783 > +++ b/"; exit 1; echo "
1748 > @@ -0,0 +1,1 @@
1784 > @@ -0,0 +1,1 @@
1749 > +revision 5
1785 > +revision 5
1750 > EOF
1786 > EOF
1751
1787
1752 $ hg import --bypass -q - << EOF
1788 $ hg import --bypass -q - << EOF
1753 > # HG changeset patch
1789 > # HG changeset patch
1754 > revision 6
1790 > revision 6
1755 >
1791 >
1756 > diff --git a/"; exit 1; echo " b/"; exit 1; echo "
1792 > diff --git a/"; exit 1; echo " b/"; exit 1; echo "
1757 > new file mode 100644
1793 > new file mode 100644
1758 > --- /dev/null
1794 > --- /dev/null
1759 > +++ b/"; exit 1; echo "
1795 > +++ b/"; exit 1; echo "
1760 > @@ -0,0 +1,1 @@
1796 > @@ -0,0 +1,1 @@
1761 > +revision 6
1797 > +revision 6
1762 > EOF
1798 > EOF
1763
1799
1764 #endif
1800 #endif
1765
1801
1766 Merge post-processing
1802 Merge post-processing
1767
1803
1768 cat is a bad merge-tool and doesn't change:
1804 cat is a bad merge-tool and doesn't change:
1769
1805
1770 $ beforemerge
1806 $ beforemerge
1771 [merge-tools]
1807 [merge-tools]
1772 false.whatever=
1808 false.whatever=
1773 true.priority=1
1809 true.priority=1
1774 true.executable=cat
1810 true.executable=cat
1775 # hg update -C 1
1811 # hg update -C 1
1776 $ hg merge -y -r 2 --config merge-tools.true.checkchanged=1
1812 $ hg merge -y -r 2 --config merge-tools.true.checkchanged=1
1777 merging f
1813 merging f
1778 revision 1
1814 revision 1
1779 space
1815 space
1780 revision 0
1816 revision 0
1781 space
1817 space
1782 revision 2
1818 revision 2
1783 space
1819 space
1784 output file f appears unchanged
1820 output file f appears unchanged
1785 was merge successful (yn)? n
1821 was merge successful (yn)? n
1786 merging f failed!
1822 merging f failed!
1787 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1823 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1788 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1824 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1789 [1]
1825 [1]
1790 $ aftermerge
1826 $ aftermerge
1791 # cat f
1827 # cat f
1792 revision 1
1828 revision 1
1793 space
1829 space
1794 # hg stat
1830 # hg stat
1795 M f
1831 M f
1796 ? f.orig
1832 ? f.orig
1797 # hg resolve --list
1833 # hg resolve --list
1798 U f
1834 U f
1799
1835
1800 missingbinary is a merge-tool that doesn't exist:
1836 missingbinary is a merge-tool that doesn't exist:
1801
1837
1802 $ echo "missingbinary.executable=doesnotexist" >> .hg/hgrc
1838 $ echo "missingbinary.executable=doesnotexist" >> .hg/hgrc
1803 $ beforemerge
1839 $ beforemerge
1804 [merge-tools]
1840 [merge-tools]
1805 false.whatever=
1841 false.whatever=
1806 true.priority=1
1842 true.priority=1
1807 true.executable=cat
1843 true.executable=cat
1808 missingbinary.executable=doesnotexist
1844 missingbinary.executable=doesnotexist
1809 # hg update -C 1
1845 # hg update -C 1
1810 $ hg merge -y -r 2 --config ui.merge=missingbinary
1846 $ hg merge -y -r 2 --config ui.merge=missingbinary
1811 couldn't find merge tool missingbinary (for pattern f)
1847 couldn't find merge tool missingbinary (for pattern f)
1812 merging f
1848 merging f
1813 revision 1
1849 revision 1
1814 space
1850 space
1815 revision 0
1851 revision 0
1816 space
1852 space
1817 revision 2
1853 revision 2
1818 space
1854 space
1819 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1855 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1820 (branch merge, don't forget to commit)
1856 (branch merge, don't forget to commit)
1821
1857
1822 $ hg update -q -C 1
1858 $ hg update -q -C 1
1823 $ rm f
1859 $ rm f
1824
1860
1825 internal merge cannot handle symlinks and shouldn't try:
1861 internal merge cannot handle symlinks and shouldn't try:
1826
1862
1827 #if symlink
1863 #if symlink
1828
1864
1829 $ ln -s symlink f
1865 $ ln -s symlink f
1830 $ hg commit -qm 'f is symlink'
1866 $ hg commit -qm 'f is symlink'
1831
1867
1832 #else
1868 #else
1833
1869
1834 $ hg import --bypass -q - << EOF
1870 $ hg import --bypass -q - << EOF
1835 > # HG changeset patch
1871 > # HG changeset patch
1836 > f is symlink
1872 > f is symlink
1837 >
1873 >
1838 > diff --git a/f b/f
1874 > diff --git a/f b/f
1839 > old mode 100644
1875 > old mode 100644
1840 > new mode 120000
1876 > new mode 120000
1841 > --- a/f
1877 > --- a/f
1842 > +++ b/f
1878 > +++ b/f
1843 > @@ -1,2 +1,1 @@
1879 > @@ -1,2 +1,1 @@
1844 > -revision 1
1880 > -revision 1
1845 > -space
1881 > -space
1846 > +symlink
1882 > +symlink
1847 > \ No newline at end of file
1883 > \ No newline at end of file
1848 > EOF
1884 > EOF
1849
1885
1850 Resolve 'other [destination] changed f which local [working copy] deleted' prompt
1886 Resolve 'other [destination] changed f which local [working copy] deleted' prompt
1851 $ hg up -q -C --config ui.interactive=True << EOF
1887 $ hg up -q -C --config ui.interactive=True << EOF
1852 > c
1888 > c
1853 > EOF
1889 > EOF
1854
1890
1855 #endif
1891 #endif
1856
1892
1857 $ hg merge -r 2 --tool internal:merge
1893 $ hg merge -r 2 --tool internal:merge
1858 merging f
1894 merging f
1859 warning: internal :merge cannot merge symlinks for f
1895 warning: internal :merge cannot merge symlinks for f
1860 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
1896 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
1861 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1897 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1862 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1898 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1863 [1]
1899 [1]
1864
1900
1865 Verify naming of temporary files and that extension is preserved:
1901 Verify naming of temporary files and that extension is preserved:
1866
1902
1867 $ hg update -q -C 1
1903 $ hg update -q -C 1
1868 $ hg mv f f.txt
1904 $ hg mv f f.txt
1869 $ hg ci -qm "f.txt"
1905 $ hg ci -qm "f.txt"
1870 $ hg update -q -C 2
1906 $ hg update -q -C 2
1871 $ hg merge -y -r tip --tool echo --config merge-tools.echo.args='$base $local $other $output'
1907 $ hg merge -y -r tip --tool echo --config merge-tools.echo.args='$base $local $other $output'
1872 merging f and f.txt to f.txt
1908 merging f and f.txt to f.txt
1873 */hgmerge-*/f~base */hgmerge-*/f~local.txt */hgmerge-*/f~other.txt */repo/f.txt (glob)
1909 */hgmerge-*/f~base */hgmerge-*/f~local.txt */hgmerge-*/f~other.txt */repo/f.txt (glob)
1874 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1910 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1875 (branch merge, don't forget to commit)
1911 (branch merge, don't forget to commit)
1876
1912
1877 Binary files capability checking
1913 Binary files capability checking
1878
1914
1879 $ hg update -q -C 0
1915 $ hg update -q -C 0
1880 $ "$PYTHON" <<EOF
1916 $ "$PYTHON" <<EOF
1881 > with open('b', 'wb') as fp:
1917 > with open('b', 'wb') as fp:
1882 > fp.write(b'\x00\x01\x02\x03')
1918 > fp.write(b'\x00\x01\x02\x03')
1883 > EOF
1919 > EOF
1884 $ hg add b
1920 $ hg add b
1885 $ hg commit -qm "add binary file (#1)"
1921 $ hg commit -qm "add binary file (#1)"
1886
1922
1887 $ hg update -q -C 0
1923 $ hg update -q -C 0
1888 $ "$PYTHON" <<EOF
1924 $ "$PYTHON" <<EOF
1889 > with open('b', 'wb') as fp:
1925 > with open('b', 'wb') as fp:
1890 > fp.write(b'\x03\x02\x01\x00')
1926 > fp.write(b'\x03\x02\x01\x00')
1891 > EOF
1927 > EOF
1892 $ hg add b
1928 $ hg add b
1893 $ hg commit -qm "add binary file (#2)"
1929 $ hg commit -qm "add binary file (#2)"
1894
1930
1895 By default, binary files capability of internal merge tools is not
1931 By default, binary files capability of internal merge tools is not
1896 checked strictly.
1932 checked strictly.
1897
1933
1898 (for merge-patterns, chosen unintentionally)
1934 (for merge-patterns, chosen unintentionally)
1899
1935
1900 $ hg merge 9 \
1936 $ hg merge 9 \
1901 > --config merge-patterns.b=:merge-other \
1937 > --config merge-patterns.b=:merge-other \
1902 > --config merge-patterns.re:[a-z]=:other
1938 > --config merge-patterns.re:[a-z]=:other
1903 warning: check merge-patterns configurations, if ':merge-other' for binary file 'b' is unintentional
1939 warning: check merge-patterns configurations, if ':merge-other' for binary file 'b' is unintentional
1904 (see 'hg help merge-tools' for binary files capability)
1940 (see 'hg help merge-tools' for binary files capability)
1905 merging b
1941 merging b
1906 warning: b looks like a binary file.
1942 warning: b looks like a binary file.
1907 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1943 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1908 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1944 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1909 [1]
1945 [1]
1910 (Testing that commands.merge.require-rev doesn't break --abort)
1946 (Testing that commands.merge.require-rev doesn't break --abort)
1911 $ hg merge --abort -q
1947 $ hg merge --abort -q
1912
1948
1913 (for ui.merge, ignored unintentionally)
1949 (for ui.merge, ignored unintentionally)
1914
1950
1915 $ hg merge 9 \
1951 $ hg merge 9 \
1916 > --config merge-tools.:other.binary=true \
1952 > --config merge-tools.:other.binary=true \
1917 > --config ui.merge=:other
1953 > --config ui.merge=:other
1918 tool :other (for pattern b) can't handle binary
1954 tool :other (for pattern b) can't handle binary
1919 tool true can't handle binary
1955 tool true can't handle binary
1920 tool :other can't handle binary
1956 tool :other can't handle binary
1921 tool false can't handle binary
1957 tool false can't handle binary
1922 no tool found to merge b
1958 no tool found to merge b
1923 file 'b' needs to be resolved.
1959 file 'b' needs to be resolved.
1924 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
1960 You can keep (l)ocal [working copy], take (o)ther [merge rev], or leave (u)nresolved.
1925 What do you want to do? u
1961 What do you want to do? u
1926 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1962 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1927 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1963 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1928 [1]
1964 [1]
1929 $ hg merge --abort -q
1965 $ hg merge --abort -q
1930
1966
1931 With merge.strict-capability-check=true, binary files capability of
1967 With merge.strict-capability-check=true, binary files capability of
1932 internal merge tools is checked strictly.
1968 internal merge tools is checked strictly.
1933
1969
1934 $ f --hexdump b
1970 $ f --hexdump b
1935 b:
1971 b:
1936 0000: 03 02 01 00 |....|
1972 0000: 03 02 01 00 |....|
1937
1973
1938 (for merge-patterns)
1974 (for merge-patterns)
1939
1975
1940 $ hg merge 9 --config merge.strict-capability-check=true \
1976 $ hg merge 9 --config merge.strict-capability-check=true \
1941 > --config merge-tools.:merge-other.binary=true \
1977 > --config merge-tools.:merge-other.binary=true \
1942 > --config merge-patterns.b=:merge-other \
1978 > --config merge-patterns.b=:merge-other \
1943 > --config merge-patterns.re:[a-z]=:other
1979 > --config merge-patterns.re:[a-z]=:other
1944 tool :merge-other (for pattern b) can't handle binary
1980 tool :merge-other (for pattern b) can't handle binary
1945 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1981 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1946 (branch merge, don't forget to commit)
1982 (branch merge, don't forget to commit)
1947 $ f --hexdump b
1983 $ f --hexdump b
1948 b:
1984 b:
1949 0000: 00 01 02 03 |....|
1985 0000: 00 01 02 03 |....|
1950 $ hg merge --abort -q
1986 $ hg merge --abort -q
1951
1987
1952 (for ui.merge)
1988 (for ui.merge)
1953
1989
1954 $ hg merge 9 --config merge.strict-capability-check=true \
1990 $ hg merge 9 --config merge.strict-capability-check=true \
1955 > --config ui.merge=:other
1991 > --config ui.merge=:other
1956 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1992 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1957 (branch merge, don't forget to commit)
1993 (branch merge, don't forget to commit)
1958 $ f --hexdump b
1994 $ f --hexdump b
1959 b:
1995 b:
1960 0000: 00 01 02 03 |....|
1996 0000: 00 01 02 03 |....|
1961 $ hg merge --abort -q
1997 $ hg merge --abort -q
1962
1998
1963 Check that the extra information is printed correctly
1999 Check that the extra information is printed correctly
1964
2000
1965 $ hg merge 9 \
2001 $ hg merge 9 \
1966 > --config merge-tools.testecho.executable='echo' \
2002 > --config merge-tools.testecho.executable='echo' \
1967 > --config merge-tools.testecho.args='merge runs here ...' \
2003 > --config merge-tools.testecho.args='merge runs here ...' \
1968 > --config merge-tools.testecho.binary=True \
2004 > --config merge-tools.testecho.binary=True \
1969 > --config ui.merge=testecho \
2005 > --config ui.merge=testecho \
1970 > --config ui.pre-merge-tool-output-template='\n{label("extmerge.running_merge_tool", "Running merge tool for {path} ({toolpath}):")}\n{separate("\n", extmerge_section(local), extmerge_section(base), extmerge_section(other))}\n' \
2006 > --config ui.pre-merge-tool-output-template='\n{label("extmerge.running_merge_tool", "Running merge tool for {path} ({toolpath}):")}\n{separate("\n", extmerge_section(local), extmerge_section(base), extmerge_section(other))}\n' \
1971 > --config 'templatealias.extmerge_section(sect)="- {pad("{sect.name} ({sect.label})", 20, left=True)}: {revset(sect.node)%"{rev}:{shortest(node,8)} {desc|firstline} {separate(" ", tags, bookmarks, branch)}"}"'
2007 > --config 'templatealias.extmerge_section(sect)="- {pad("{sect.name} ({sect.label})", 20, left=True)}: {revset(sect.node)%"{rev}:{shortest(node,8)} {desc|firstline} {separate(" ", tags, bookmarks, branch)}"}"'
1972 merging b
2008 merging b
1973
2009
1974 Running merge tool for b ("*/bin/echo.exe"): (glob) (windows !)
2010 Running merge tool for b ("*/bin/echo.exe"): (glob) (windows !)
1975 Running merge tool for b (*/bin/echo): (glob) (no-windows !)
2011 Running merge tool for b (*/bin/echo): (glob) (no-windows !)
1976 - local (working copy): 10:2d1f533d add binary file (#2) tip default
2012 - local (working copy): 10:2d1f533d add binary file (#2) tip default
1977 - base (common ancestor): -1:00000000 default
2013 - base (common ancestor): -1:00000000 default
1978 - other (merge rev): 9:1e7ad7d7 add binary file (#1) default
2014 - other (merge rev): 9:1e7ad7d7 add binary file (#1) default
1979 merge runs here ...
2015 merge runs here ...
1980 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
2016 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1981 (branch merge, don't forget to commit)
2017 (branch merge, don't forget to commit)
1982
2018
1983 Check that debugpicktool examines which merge tool is chosen for
2019 Check that debugpicktool examines which merge tool is chosen for
1984 specified file as expected
2020 specified file as expected
1985
2021
1986 $ beforemerge
2022 $ beforemerge
1987 [merge-tools]
2023 [merge-tools]
1988 false.whatever=
2024 false.whatever=
1989 true.priority=1
2025 true.priority=1
1990 true.executable=cat
2026 true.executable=cat
1991 missingbinary.executable=doesnotexist
2027 missingbinary.executable=doesnotexist
1992 # hg update -C 1
2028 # hg update -C 1
1993
2029
1994 (default behavior: checking files in the working parent context)
2030 (default behavior: checking files in the working parent context)
1995
2031
1996 $ hg manifest
2032 $ hg manifest
1997 f
2033 f
1998 $ hg debugpickmergetool
2034 $ hg debugpickmergetool
1999 f = true
2035 f = true
2000
2036
2001 (-X/-I and file patterns limmit examination targets)
2037 (-X/-I and file patterns limmit examination targets)
2002
2038
2003 $ hg debugpickmergetool -X f
2039 $ hg debugpickmergetool -X f
2004 $ hg debugpickmergetool unknown
2040 $ hg debugpickmergetool unknown
2005 unknown: no such file in rev ef83787e2614
2041 unknown: no such file in rev ef83787e2614
2006
2042
2007 (--changedelete emulates merging change and delete)
2043 (--changedelete emulates merging change and delete)
2008
2044
2009 $ hg debugpickmergetool --changedelete
2045 $ hg debugpickmergetool --changedelete
2010 f = :prompt
2046 f = :prompt
2011
2047
2012 (-r REV causes checking files in specified revision)
2048 (-r REV causes checking files in specified revision)
2013
2049
2014 $ hg manifest -r 8
2050 $ hg manifest -r 8
2015 f.txt
2051 f.txt
2016 $ hg debugpickmergetool -r 8
2052 $ hg debugpickmergetool -r 8
2017 f.txt = true
2053 f.txt = true
2018
2054
2019 #if symlink
2055 #if symlink
2020
2056
2021 (symlink causes chosing :prompt)
2057 (symlink causes chosing :prompt)
2022
2058
2023 $ hg debugpickmergetool -r 6d00b3726f6e
2059 $ hg debugpickmergetool -r 6d00b3726f6e
2024 f = :prompt
2060 f = :prompt
2025
2061
2026 (by default, it is assumed that no internal merge tools has symlinks
2062 (by default, it is assumed that no internal merge tools has symlinks
2027 capability)
2063 capability)
2028
2064
2029 $ hg debugpickmergetool \
2065 $ hg debugpickmergetool \
2030 > -r 6d00b3726f6e \
2066 > -r 6d00b3726f6e \
2031 > --config merge-tools.:merge-other.symlink=true \
2067 > --config merge-tools.:merge-other.symlink=true \
2032 > --config merge-patterns.f=:merge-other \
2068 > --config merge-patterns.f=:merge-other \
2033 > --config merge-patterns.re:[f]=:merge-local \
2069 > --config merge-patterns.re:[f]=:merge-local \
2034 > --config merge-patterns.re:[a-z]=:other
2070 > --config merge-patterns.re:[a-z]=:other
2035 f = :prompt
2071 f = :prompt
2036
2072
2037 $ hg debugpickmergetool \
2073 $ hg debugpickmergetool \
2038 > -r 6d00b3726f6e \
2074 > -r 6d00b3726f6e \
2039 > --config merge-tools.:other.symlink=true \
2075 > --config merge-tools.:other.symlink=true \
2040 > --config ui.merge=:other
2076 > --config ui.merge=:other
2041 f = :prompt
2077 f = :prompt
2042
2078
2043 (with strict-capability-check=true, actual symlink capabilities are
2079 (with strict-capability-check=true, actual symlink capabilities are
2044 checked striclty)
2080 checked striclty)
2045
2081
2046 $ hg debugpickmergetool --config merge.strict-capability-check=true \
2082 $ hg debugpickmergetool --config merge.strict-capability-check=true \
2047 > -r 6d00b3726f6e \
2083 > -r 6d00b3726f6e \
2048 > --config merge-tools.:merge-other.symlink=true \
2084 > --config merge-tools.:merge-other.symlink=true \
2049 > --config merge-patterns.f=:merge-other \
2085 > --config merge-patterns.f=:merge-other \
2050 > --config merge-patterns.re:[f]=:merge-local \
2086 > --config merge-patterns.re:[f]=:merge-local \
2051 > --config merge-patterns.re:[a-z]=:other
2087 > --config merge-patterns.re:[a-z]=:other
2052 f = :other
2088 f = :other
2053
2089
2054 $ hg debugpickmergetool --config merge.strict-capability-check=true \
2090 $ hg debugpickmergetool --config merge.strict-capability-check=true \
2055 > -r 6d00b3726f6e \
2091 > -r 6d00b3726f6e \
2056 > --config ui.merge=:other
2092 > --config ui.merge=:other
2057 f = :other
2093 f = :other
2058
2094
2059 $ hg debugpickmergetool --config merge.strict-capability-check=true \
2095 $ hg debugpickmergetool --config merge.strict-capability-check=true \
2060 > -r 6d00b3726f6e \
2096 > -r 6d00b3726f6e \
2061 > --config merge-tools.:merge-other.symlink=true \
2097 > --config merge-tools.:merge-other.symlink=true \
2062 > --config ui.merge=:merge-other
2098 > --config ui.merge=:merge-other
2063 f = :prompt
2099 f = :prompt
2064
2100
2065 #endif
2101 #endif
2066
2102
2067 (--verbose shows some configurations)
2103 (--verbose shows some configurations)
2068
2104
2069 $ hg debugpickmergetool --tool foobar -v
2105 $ hg debugpickmergetool --tool foobar -v
2070 with --tool 'foobar'
2106 with --tool 'foobar'
2071 f = foobar
2107 f = foobar
2072
2108
2073 $ HGMERGE=false hg debugpickmergetool -v
2109 $ HGMERGE=false hg debugpickmergetool -v
2074 with HGMERGE='false'
2110 with HGMERGE='false'
2075 f = false
2111 f = false
2076
2112
2077 $ hg debugpickmergetool --config ui.merge=false -v
2113 $ hg debugpickmergetool --config ui.merge=false -v
2078 with ui.merge='false'
2114 with ui.merge='false'
2079 f = false
2115 f = false
2080
2116
2081 (--debug shows errors detected intermediately)
2117 (--debug shows errors detected intermediately)
2082
2118
2083 $ hg debugpickmergetool --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool --debug f
2119 $ hg debugpickmergetool --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool --debug f
2084 couldn't find merge tool true (for pattern f)
2120 couldn't find merge tool true (for pattern f)
2085 couldn't find merge tool true
2121 couldn't find merge tool true
2086 f = false
2122 f = false
2087
2123
2088 $ cd ..
2124 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now