##// END OF EJS Templates
merge: better debug messages before/after invoking external merge tool
Mads Kiilerich -
r24727:5668202c default
parent child Browse files
Show More
@@ -1,476 +1,479
1 1 # filemerge.py - file-level merge handling for Mercurial
2 2 #
3 3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import short
9 9 from i18n import _
10 10 import util, simplemerge, match, error, templater, templatekw
11 11 import os, tempfile, re, filecmp
12 12 import tagmerge
13 13
14 14 def _toolstr(ui, tool, part, default=""):
15 15 return ui.config("merge-tools", tool + "." + part, default)
16 16
17 17 def _toolbool(ui, tool, part, default=False):
18 18 return ui.configbool("merge-tools", tool + "." + part, default)
19 19
20 20 def _toollist(ui, tool, part, default=[]):
21 21 return ui.configlist("merge-tools", tool + "." + part, default)
22 22
23 23 internals = {}
24 24 # Merge tools to document.
25 25 internalsdoc = {}
26 26
27 27 def internaltool(name, trymerge, onfailure=None):
28 28 '''return a decorator for populating internal merge tool table'''
29 29 def decorator(func):
30 30 fullname = ':' + name
31 31 func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
32 32 internals[fullname] = func
33 33 internals['internal:' + name] = func
34 34 internalsdoc[fullname] = func
35 35 func.trymerge = trymerge
36 36 func.onfailure = onfailure
37 37 return func
38 38 return decorator
39 39
40 40 def _findtool(ui, tool):
41 41 if tool in internals:
42 42 return tool
43 43 return findexternaltool(ui, tool)
44 44
45 45 def findexternaltool(ui, tool):
46 46 for kn in ("regkey", "regkeyalt"):
47 47 k = _toolstr(ui, tool, kn)
48 48 if not k:
49 49 continue
50 50 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
51 51 if p:
52 52 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
53 53 if p:
54 54 return p
55 55 exe = _toolstr(ui, tool, "executable", tool)
56 56 return util.findexe(util.expandpath(exe))
57 57
58 58 def _picktool(repo, ui, path, binary, symlink):
59 59 def check(tool, pat, symlink, binary):
60 60 tmsg = tool
61 61 if pat:
62 62 tmsg += " specified for " + pat
63 63 if not _findtool(ui, tool):
64 64 if pat: # explicitly requested tool deserves a warning
65 65 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
66 66 else: # configured but non-existing tools are more silent
67 67 ui.note(_("couldn't find merge tool %s\n") % tmsg)
68 68 elif symlink and not _toolbool(ui, tool, "symlink"):
69 69 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
70 70 elif binary and not _toolbool(ui, tool, "binary"):
71 71 ui.warn(_("tool %s can't handle binary\n") % tmsg)
72 72 elif not util.gui() and _toolbool(ui, tool, "gui"):
73 73 ui.warn(_("tool %s requires a GUI\n") % tmsg)
74 74 else:
75 75 return True
76 76 return False
77 77
78 78 # forcemerge comes from command line arguments, highest priority
79 79 force = ui.config('ui', 'forcemerge')
80 80 if force:
81 81 toolpath = _findtool(ui, force)
82 82 if toolpath:
83 83 return (force, util.shellquote(toolpath))
84 84 else:
85 85 # mimic HGMERGE if given tool not found
86 86 return (force, force)
87 87
88 88 # HGMERGE takes next precedence
89 89 hgmerge = os.environ.get("HGMERGE")
90 90 if hgmerge:
91 91 return (hgmerge, hgmerge)
92 92
93 93 # then patterns
94 94 for pat, tool in ui.configitems("merge-patterns"):
95 95 mf = match.match(repo.root, '', [pat])
96 96 if mf(path) and check(tool, pat, symlink, False):
97 97 toolpath = _findtool(ui, tool)
98 98 return (tool, util.shellquote(toolpath))
99 99
100 100 # then merge tools
101 101 tools = {}
102 102 for k, v in ui.configitems("merge-tools"):
103 103 t = k.split('.')[0]
104 104 if t not in tools:
105 105 tools[t] = int(_toolstr(ui, t, "priority", "0"))
106 106 names = tools.keys()
107 107 tools = sorted([(-p, t) for t, p in tools.items()])
108 108 uimerge = ui.config("ui", "merge")
109 109 if uimerge:
110 110 if uimerge not in names:
111 111 return (uimerge, uimerge)
112 112 tools.insert(0, (None, uimerge)) # highest priority
113 113 tools.append((None, "hgmerge")) # the old default, if found
114 114 for p, t in tools:
115 115 if check(t, None, symlink, binary):
116 116 toolpath = _findtool(ui, t)
117 117 return (t, util.shellquote(toolpath))
118 118
119 119 # internal merge or prompt as last resort
120 120 if symlink or binary:
121 121 return ":prompt", None
122 122 return ":merge", None
123 123
124 124 def _eoltype(data):
125 125 "Guess the EOL type of a file"
126 126 if '\0' in data: # binary
127 127 return None
128 128 if '\r\n' in data: # Windows
129 129 return '\r\n'
130 130 if '\r' in data: # Old Mac
131 131 return '\r'
132 132 if '\n' in data: # UNIX
133 133 return '\n'
134 134 return None # unknown
135 135
136 136 def _matcheol(file, origfile):
137 137 "Convert EOL markers in a file to match origfile"
138 138 tostyle = _eoltype(util.readfile(origfile))
139 139 if tostyle:
140 140 data = util.readfile(file)
141 141 style = _eoltype(data)
142 142 if style:
143 143 newdata = data.replace(style, tostyle)
144 144 if newdata != data:
145 145 util.writefile(file, newdata)
146 146
147 147 @internaltool('prompt', False)
148 148 def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
149 149 """Asks the user which of the local or the other version to keep as
150 150 the merged version."""
151 151 ui = repo.ui
152 152 fd = fcd.path()
153 153
154 154 if ui.promptchoice(_(" no tool found to merge %s\n"
155 155 "keep (l)ocal or take (o)ther?"
156 156 "$$ &Local $$ &Other") % fd, 0):
157 157 return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
158 158 else:
159 159 return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
160 160
161 161 @internaltool('local', False)
162 162 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
163 163 """Uses the local version of files as the merged version."""
164 164 return 0
165 165
166 166 @internaltool('other', False)
167 167 def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
168 168 """Uses the other version of files as the merged version."""
169 169 repo.wwrite(fcd.path(), fco.data(), fco.flags())
170 170 return 0
171 171
172 172 @internaltool('fail', False)
173 173 def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
174 174 """
175 175 Rather than attempting to merge files that were modified on both
176 176 branches, it marks them as unresolved. The resolve command must be
177 177 used to resolve these conflicts."""
178 178 return 1
179 179
180 180 def _premerge(repo, toolconf, files, labels=None):
181 181 tool, toolpath, binary, symlink = toolconf
182 182 if symlink:
183 183 return 1
184 184 a, b, c, back = files
185 185
186 186 ui = repo.ui
187 187
188 188 validkeep = ['keep', 'keep-merge3']
189 189
190 190 # do we attempt to simplemerge first?
191 191 try:
192 192 premerge = _toolbool(ui, tool, "premerge", not binary)
193 193 except error.ConfigError:
194 194 premerge = _toolstr(ui, tool, "premerge").lower()
195 195 if premerge not in validkeep:
196 196 _valid = ', '.join(["'" + v + "'" for v in validkeep])
197 197 raise error.ConfigError(_("%s.premerge not valid "
198 198 "('%s' is neither boolean nor %s)") %
199 199 (tool, premerge, _valid))
200 200
201 201 if premerge:
202 202 if premerge == 'keep-merge3':
203 203 if not labels:
204 204 labels = _defaultconflictlabels
205 205 if len(labels) < 3:
206 206 labels.append('base')
207 207 r = simplemerge.simplemerge(ui, a, b, c, quiet=True, label=labels)
208 208 if not r:
209 209 ui.debug(" premerge successful\n")
210 210 return 0
211 211 if premerge not in validkeep:
212 212 util.copyfile(back, a) # restore from backup and try again
213 213 return 1 # continue merging
214 214
215 215 @internaltool('merge', True,
216 216 _("merging %s incomplete! "
217 217 "(edit conflicts, then use 'hg resolve --mark')\n"))
218 218 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
219 219 """
220 220 Uses the internal non-interactive simple merge algorithm for merging
221 221 files. It will fail if there are any conflicts and leave markers in
222 222 the partially merged file. Markers will have two sections, one for each side
223 223 of merge."""
224 224 tool, toolpath, binary, symlink = toolconf
225 225 if symlink:
226 226 repo.ui.warn(_('warning: internal :merge cannot merge symlinks '
227 227 'for %s\n') % fcd.path())
228 228 return False, 1
229 229 r = _premerge(repo, toolconf, files, labels=labels)
230 230 if r:
231 231 a, b, c, back = files
232 232
233 233 ui = repo.ui
234 234
235 235 r = simplemerge.simplemerge(ui, a, b, c, label=labels)
236 236 return True, r
237 237 return False, 0
238 238
239 239 @internaltool('merge3', True,
240 240 _("merging %s incomplete! "
241 241 "(edit conflicts, then use 'hg resolve --mark')\n"))
242 242 def _imerge3(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
243 243 """
244 244 Uses the internal non-interactive simple merge algorithm for merging
245 245 files. It will fail if there are any conflicts and leave markers in
246 246 the partially merged file. Marker will have three sections, one from each
247 247 side of the merge and one for the base content."""
248 248 if not labels:
249 249 labels = _defaultconflictlabels
250 250 if len(labels) < 3:
251 251 labels.append('base')
252 252 return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels)
253 253
254 254 @internaltool('tagmerge', True,
255 255 _("automatic tag merging of %s failed! "
256 256 "(use 'hg resolve --tool :merge' or another merge "
257 257 "tool of your choice)\n"))
258 258 def _itagmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
259 259 """
260 260 Uses the internal tag merge algorithm (experimental).
261 261 """
262 262 return tagmerge.merge(repo, fcd, fco, fca)
263 263
264 264 @internaltool('dump', True)
265 265 def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
266 266 """
267 267 Creates three versions of the files to merge, containing the
268 268 contents of local, other and base. These files can then be used to
269 269 perform a merge manually. If the file to be merged is named
270 270 ``a.txt``, these files will accordingly be named ``a.txt.local``,
271 271 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
272 272 same directory as ``a.txt``."""
273 273 r = _premerge(repo, toolconf, files, labels=labels)
274 274 if r:
275 275 a, b, c, back = files
276 276
277 277 fd = fcd.path()
278 278
279 279 util.copyfile(a, a + ".local")
280 280 repo.wwrite(fd + ".other", fco.data(), fco.flags())
281 281 repo.wwrite(fd + ".base", fca.data(), fca.flags())
282 282 return False, r
283 283
284 284 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
285 285 r = _premerge(repo, toolconf, files, labels=labels)
286 286 if r:
287 287 tool, toolpath, binary, symlink = toolconf
288 288 a, b, c, back = files
289 289 out = ""
290 290 env = {'HG_FILE': fcd.path(),
291 291 'HG_MY_NODE': short(mynode),
292 292 'HG_OTHER_NODE': str(fco.changectx()),
293 293 'HG_BASE_NODE': str(fca.changectx()),
294 294 'HG_MY_ISLINK': 'l' in fcd.flags(),
295 295 'HG_OTHER_ISLINK': 'l' in fco.flags(),
296 296 'HG_BASE_ISLINK': 'l' in fca.flags(),
297 297 }
298 298
299 299 ui = repo.ui
300 300
301 301 args = _toolstr(ui, tool, "args", '$local $base $other')
302 302 if "$output" in args:
303 303 out, a = a, back # read input from backup, write to original
304 304 replace = {'local': a, 'base': b, 'other': c, 'output': out}
305 305 args = util.interpolate(r'\$', replace, args,
306 306 lambda s: util.shellquote(util.localpath(s)))
307 r = ui.system(toolpath + ' ' + args, cwd=repo.root, environ=env)
307 cmd = toolpath + ' ' + args
308 repo.ui.debug('launching merge tool: %s\n' % cmd)
309 r = ui.system(cmd, cwd=repo.root, environ=env)
310 repo.ui.debug('merge tool returned: %s\n' % r)
308 311 return True, r
309 312 return False, 0
310 313
311 314 def _formatconflictmarker(repo, ctx, template, label, pad):
312 315 """Applies the given template to the ctx, prefixed by the label.
313 316
314 317 Pad is the minimum width of the label prefix, so that multiple markers
315 318 can have aligned templated parts.
316 319 """
317 320 if ctx.node() is None:
318 321 ctx = ctx.p1()
319 322
320 323 props = templatekw.keywords.copy()
321 324 props['templ'] = template
322 325 props['ctx'] = ctx
323 326 props['repo'] = repo
324 327 templateresult = template('conflictmarker', **props)
325 328
326 329 label = ('%s:' % label).ljust(pad + 1)
327 330 mark = '%s %s' % (label, templater.stringify(templateresult))
328 331
329 332 if mark:
330 333 mark = mark.splitlines()[0] # split for safety
331 334
332 335 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ')
333 336 return util.ellipsis(mark, 80 - 8)
334 337
335 338 _defaultconflictmarker = ('{node|short} ' +
336 339 '{ifeq(tags, "tip", "", "{tags} ")}' +
337 340 '{if(bookmarks, "{bookmarks} ")}' +
338 341 '{ifeq(branch, "default", "", "{branch} ")}' +
339 342 '- {author|user}: {desc|firstline}')
340 343
341 344 _defaultconflictlabels = ['local', 'other']
342 345
343 346 def _formatlabels(repo, fcd, fco, fca, labels):
344 347 """Formats the given labels using the conflict marker template.
345 348
346 349 Returns a list of formatted labels.
347 350 """
348 351 cd = fcd.changectx()
349 352 co = fco.changectx()
350 353 ca = fca.changectx()
351 354
352 355 ui = repo.ui
353 356 template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker)
354 357 template = templater.parsestring(template, quoted=False)
355 358 tmpl = templater.templater(None, cache={'conflictmarker': template})
356 359
357 360 pad = max(len(l) for l in labels)
358 361
359 362 newlabels = [_formatconflictmarker(repo, cd, tmpl, labels[0], pad),
360 363 _formatconflictmarker(repo, co, tmpl, labels[1], pad)]
361 364 if len(labels) > 2:
362 365 newlabels.append(_formatconflictmarker(repo, ca, tmpl, labels[2], pad))
363 366 return newlabels
364 367
365 368 def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
366 369 """perform a 3-way merge in the working directory
367 370
368 371 mynode = parent node before merge
369 372 orig = original local filename before merge
370 373 fco = other file context
371 374 fca = ancestor file context
372 375 fcd = local file context for current/destination file
373 376 """
374 377
375 378 def temp(prefix, ctx):
376 379 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
377 380 (fd, name) = tempfile.mkstemp(prefix=pre)
378 381 data = repo.wwritedata(ctx.path(), ctx.data())
379 382 f = os.fdopen(fd, "wb")
380 383 f.write(data)
381 384 f.close()
382 385 return name
383 386
384 387 if not fco.cmp(fcd): # files identical?
385 388 return None
386 389
387 390 ui = repo.ui
388 391 fd = fcd.path()
389 392 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
390 393 symlink = 'l' in fcd.flags() + fco.flags()
391 394 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
392 395 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
393 396 (tool, fd, binary, symlink))
394 397
395 398 if tool in internals:
396 399 func = internals[tool]
397 400 trymerge = func.trymerge
398 401 onfailure = func.onfailure
399 402 else:
400 403 func = _xmerge
401 404 trymerge = True
402 405 onfailure = _("merging %s failed!\n")
403 406
404 407 toolconf = tool, toolpath, binary, symlink
405 408
406 409 if not trymerge:
407 410 return func(repo, mynode, orig, fcd, fco, fca, toolconf)
408 411
409 412 a = repo.wjoin(fd)
410 413 b = temp("base", fca)
411 414 c = temp("other", fco)
412 415 back = a + ".orig"
413 416 util.copyfile(a, back)
414 417
415 418 if orig != fco.path():
416 419 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
417 420 else:
418 421 ui.status(_("merging %s\n") % fd)
419 422
420 423 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
421 424
422 425 markerstyle = ui.config('ui', 'mergemarkers', 'basic')
423 426 if not labels:
424 427 labels = _defaultconflictlabels
425 428 if markerstyle != 'basic':
426 429 labels = _formatlabels(repo, fcd, fco, fca, labels)
427 430
428 431 needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
429 432 (a, b, c, back), labels=labels)
430 433 if not needcheck:
431 434 if r:
432 435 if onfailure:
433 436 ui.warn(onfailure % fd)
434 437 else:
435 438 util.unlink(back)
436 439
437 440 util.unlink(b)
438 441 util.unlink(c)
439 442 return r
440 443
441 444 if not r and (_toolbool(ui, tool, "checkconflicts") or
442 445 'conflicts' in _toollist(ui, tool, "check")):
443 446 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
444 447 re.MULTILINE):
445 448 r = 1
446 449
447 450 checked = False
448 451 if 'prompt' in _toollist(ui, tool, "check"):
449 452 checked = True
450 453 if ui.promptchoice(_("was merge of '%s' successful (yn)?"
451 454 "$$ &Yes $$ &No") % fd, 1):
452 455 r = 1
453 456
454 457 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
455 458 'changed' in _toollist(ui, tool, "check")):
456 459 if filecmp.cmp(a, back):
457 460 if ui.promptchoice(_(" output file %s appears unchanged\n"
458 461 "was merge successful (yn)?"
459 462 "$$ &Yes $$ &No") % fd, 1):
460 463 r = 1
461 464
462 465 if _toolbool(ui, tool, "fixeol"):
463 466 _matcheol(a, back)
464 467
465 468 if r:
466 469 if onfailure:
467 470 ui.warn(onfailure % fd)
468 471 else:
469 472 util.unlink(back)
470 473
471 474 util.unlink(b)
472 475 util.unlink(c)
473 476 return r
474 477
475 478 # tell hggettext to extract docstrings from these functions:
476 479 i18nfunctions = internals.values()
@@ -1,960 +1,1024
1 1
2 2 $ mkdir -p t
3 3 $ cd t
4 4 $ cat <<EOF > merge
5 5 > import sys, os
6 6 > f = open(sys.argv[1], "wb")
7 7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
8 8 > f.close()
9 9 > EOF
10 10
11 11 perform a test merge with possible renaming
12 12 args:
13 13 $1 = action in local branch
14 14 $2 = action in remote branch
15 15 $3 = action in working dir
16 16 $4 = expected result
17 17
18 18 $ tm()
19 19 > {
20 20 > hg init t
21 21 > cd t
22 22 > echo "[merge]" >> .hg/hgrc
23 23 > echo "followcopies = 1" >> .hg/hgrc
24 24 >
25 25 > # base
26 26 > echo base > a
27 27 > echo base > rev # used to force commits
28 28 > hg add a rev
29 29 > hg ci -m "base"
30 30 >
31 31 > # remote
32 32 > echo remote > rev
33 33 > if [ "$2" != "" ] ; then $2 ; fi
34 34 > hg ci -m "remote"
35 35 >
36 36 > # local
37 37 > hg co -q 0
38 38 > echo local > rev
39 39 > if [ "$1" != "" ] ; then $1 ; fi
40 40 > hg ci -m "local"
41 41 >
42 42 > # working dir
43 43 > echo local > rev
44 44 > if [ "$3" != "" ] ; then $3 ; fi
45 45 >
46 46 > # merge
47 47 > echo "--------------"
48 48 > echo "test L:$1 R:$2 W:$3 - $4"
49 49 > echo "--------------"
50 50 > hg merge -y --debug --traceback --tool="python ../merge"
51 51 >
52 52 > echo "--------------"
53 53 > hg status -camC -X rev
54 54 >
55 55 > hg ci -m "merge"
56 56 >
57 57 > echo "--------------"
58 58 > echo
59 59 >
60 60 > cd ..
61 61 > rm -r t
62 62 > }
63 63 $ up() {
64 64 > cp rev $1
65 65 > hg add $1 2> /dev/null
66 66 > if [ "$2" != "" ] ; then
67 67 > cp rev $2
68 68 > hg add $2 2> /dev/null
69 69 > fi
70 70 > }
71 71 $ uc() { up $1; hg cp $1 $2; } # update + copy
72 72 $ um() { up $1; hg mv $1 $2; }
73 73 $ nc() { hg cp $1 $2; } # just copy
74 74 $ nm() { hg mv $1 $2; } # just move
75 75 $ tm "up a " "nc a b" " " "1 get local a to b"
76 76 created new head
77 77 --------------
78 78 test L:up a R:nc a b W: - 1 get local a to b
79 79 --------------
80 80 searching for copies back to rev 1
81 81 unmatched files in other:
82 82 b
83 83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
84 84 src: 'a' -> dst: 'b' *
85 85 checking for directory renames
86 86 resolving manifests
87 87 branchmerge: True, force: False, partial: False
88 88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
89 89 preserving a for resolve of b
90 90 preserving rev for resolve of rev
91 91 a: remote unchanged -> k
92 92 b: remote copied from a -> m
93 93 updating: b 1/2 files (50.00%)
94 94 picked tool 'python ../merge' for b (binary False symlink False)
95 95 merging a and b to b
96 96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
97 97 premerge successful
98 98 rev: versions differ -> m
99 99 updating: rev 2/2 files (100.00%)
100 100 picked tool 'python ../merge' for rev (binary False symlink False)
101 101 merging rev
102 102 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
103 launching merge tool: python ../merge $TESTTMP/t/t/rev '*' '*' (glob)
104 merge tool returned: 0
103 105 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
104 106 (branch merge, don't forget to commit)
105 107 --------------
106 108 M b
107 109 a
108 110 C a
109 111 --------------
110 112
111 113 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
112 114 created new head
113 115 --------------
114 116 test L:nc a b R:up a W: - 2 get rem change to a and b
115 117 --------------
116 118 searching for copies back to rev 1
117 119 unmatched files in local:
118 120 b
119 121 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
120 122 src: 'a' -> dst: 'b' *
121 123 checking for directory renames
122 124 resolving manifests
123 125 branchmerge: True, force: False, partial: False
124 126 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
125 127 preserving b for resolve of b
126 128 preserving rev for resolve of rev
127 129 a: remote is newer -> g
128 130 getting a
129 131 updating: a 1/3 files (33.33%)
130 132 b: local copied/moved from a -> m
131 133 updating: b 2/3 files (66.67%)
132 134 picked tool 'python ../merge' for b (binary False symlink False)
133 135 merging b and a to b
134 136 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
135 137 premerge successful
136 138 rev: versions differ -> m
137 139 updating: rev 3/3 files (100.00%)
138 140 picked tool 'python ../merge' for rev (binary False symlink False)
139 141 merging rev
140 142 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
143 launching merge tool: python ../merge $TESTTMP/t/t/rev * (glob)
144 merge tool returned: 0
141 145 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
142 146 (branch merge, don't forget to commit)
143 147 --------------
144 148 M a
145 149 M b
146 150 a
147 151 --------------
148 152
149 153 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
150 154 created new head
151 155 --------------
152 156 test L:up a R:nm a b W: - 3 get local a change to b, remove a
153 157 --------------
154 158 searching for copies back to rev 1
155 159 unmatched files in other:
156 160 b
157 161 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
158 162 src: 'a' -> dst: 'b' *
159 163 checking for directory renames
160 164 resolving manifests
161 165 branchmerge: True, force: False, partial: False
162 166 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
163 167 preserving a for resolve of b
164 168 preserving rev for resolve of rev
165 169 removing a
166 170 b: remote moved from a -> m
167 171 updating: b 1/2 files (50.00%)
168 172 picked tool 'python ../merge' for b (binary False symlink False)
169 173 merging a and b to b
170 174 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
171 175 premerge successful
172 176 rev: versions differ -> m
173 177 updating: rev 2/2 files (100.00%)
174 178 picked tool 'python ../merge' for rev (binary False symlink False)
175 179 merging rev
176 180 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
181 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
182 merge tool returned: 0
177 183 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
178 184 (branch merge, don't forget to commit)
179 185 --------------
180 186 M b
181 187 a
182 188 --------------
183 189
184 190 $ tm "nm a b" "up a " " " "4 get remote change to b"
185 191 created new head
186 192 --------------
187 193 test L:nm a b R:up a W: - 4 get remote change to b
188 194 --------------
189 195 searching for copies back to rev 1
190 196 unmatched files in local:
191 197 b
192 198 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
193 199 src: 'a' -> dst: 'b' *
194 200 checking for directory renames
195 201 resolving manifests
196 202 branchmerge: True, force: False, partial: False
197 203 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
198 204 preserving b for resolve of b
199 205 preserving rev for resolve of rev
200 206 b: local copied/moved from a -> m
201 207 updating: b 1/2 files (50.00%)
202 208 picked tool 'python ../merge' for b (binary False symlink False)
203 209 merging b and a to b
204 210 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
205 211 premerge successful
206 212 rev: versions differ -> m
207 213 updating: rev 2/2 files (100.00%)
208 214 picked tool 'python ../merge' for rev (binary False symlink False)
209 215 merging rev
210 216 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
217 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
218 merge tool returned: 0
211 219 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
212 220 (branch merge, don't forget to commit)
213 221 --------------
214 222 M b
215 223 a
216 224 --------------
217 225
218 226 $ tm " " "nc a b" " " "5 get b"
219 227 created new head
220 228 --------------
221 229 test L: R:nc a b W: - 5 get b
222 230 --------------
223 231 searching for copies back to rev 1
224 232 unmatched files in other:
225 233 b
226 234 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
227 235 src: 'a' -> dst: 'b'
228 236 checking for directory renames
229 237 resolving manifests
230 238 branchmerge: True, force: False, partial: False
231 239 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
232 240 preserving rev for resolve of rev
233 241 b: remote created -> g
234 242 getting b
235 243 updating: b 1/2 files (50.00%)
236 244 rev: versions differ -> m
237 245 updating: rev 2/2 files (100.00%)
238 246 picked tool 'python ../merge' for rev (binary False symlink False)
239 247 merging rev
240 248 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
249 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
250 merge tool returned: 0
241 251 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
242 252 (branch merge, don't forget to commit)
243 253 --------------
244 254 M b
245 255 C a
246 256 --------------
247 257
248 258 $ tm "nc a b" " " " " "6 nothing"
249 259 created new head
250 260 --------------
251 261 test L:nc a b R: W: - 6 nothing
252 262 --------------
253 263 searching for copies back to rev 1
254 264 unmatched files in local:
255 265 b
256 266 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
257 267 src: 'a' -> dst: 'b'
258 268 checking for directory renames
259 269 resolving manifests
260 270 branchmerge: True, force: False, partial: False
261 271 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
262 272 preserving rev for resolve of rev
263 273 rev: versions differ -> m
264 274 updating: rev 1/1 files (100.00%)
265 275 picked tool 'python ../merge' for rev (binary False symlink False)
266 276 merging rev
267 277 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
278 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
279 merge tool returned: 0
268 280 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
269 281 (branch merge, don't forget to commit)
270 282 --------------
271 283 C a
272 284 C b
273 285 --------------
274 286
275 287 $ tm " " "nm a b" " " "7 get b"
276 288 created new head
277 289 --------------
278 290 test L: R:nm a b W: - 7 get b
279 291 --------------
280 292 searching for copies back to rev 1
281 293 unmatched files in other:
282 294 b
283 295 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
284 296 src: 'a' -> dst: 'b'
285 297 checking for directory renames
286 298 resolving manifests
287 299 branchmerge: True, force: False, partial: False
288 300 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
289 301 preserving rev for resolve of rev
290 302 a: other deleted -> r
291 303 removing a
292 304 updating: a 1/3 files (33.33%)
293 305 b: remote created -> g
294 306 getting b
295 307 updating: b 2/3 files (66.67%)
296 308 rev: versions differ -> m
297 309 updating: rev 3/3 files (100.00%)
298 310 picked tool 'python ../merge' for rev (binary False symlink False)
299 311 merging rev
300 312 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
313 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
314 merge tool returned: 0
301 315 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
302 316 (branch merge, don't forget to commit)
303 317 --------------
304 318 M b
305 319 --------------
306 320
307 321 $ tm "nm a b" " " " " "8 nothing"
308 322 created new head
309 323 --------------
310 324 test L:nm a b R: W: - 8 nothing
311 325 --------------
312 326 searching for copies back to rev 1
313 327 unmatched files in local:
314 328 b
315 329 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
316 330 src: 'a' -> dst: 'b'
317 331 checking for directory renames
318 332 resolving manifests
319 333 branchmerge: True, force: False, partial: False
320 334 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
321 335 preserving rev for resolve of rev
322 336 rev: versions differ -> m
323 337 updating: rev 1/1 files (100.00%)
324 338 picked tool 'python ../merge' for rev (binary False symlink False)
325 339 merging rev
326 340 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
341 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
342 merge tool returned: 0
327 343 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
328 344 (branch merge, don't forget to commit)
329 345 --------------
330 346 C b
331 347 --------------
332 348
333 349 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
334 350 created new head
335 351 --------------
336 352 test L:um a b R:um a b W: - 9 do merge with ancestor in a
337 353 --------------
338 354 searching for copies back to rev 1
339 355 unmatched files new in both:
340 356 b
341 357 resolving manifests
342 358 branchmerge: True, force: False, partial: False
343 359 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
344 360 preserving b for resolve of b
345 361 preserving rev for resolve of rev
346 362 b: both renamed from a -> m
347 363 updating: b 1/2 files (50.00%)
348 364 picked tool 'python ../merge' for b (binary False symlink False)
349 365 merging b
350 366 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
367 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
368 merge tool returned: 0
351 369 rev: versions differ -> m
352 370 updating: rev 2/2 files (100.00%)
353 371 picked tool 'python ../merge' for rev (binary False symlink False)
354 372 merging rev
355 373 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
374 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
375 merge tool returned: 0
356 376 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
357 377 (branch merge, don't forget to commit)
358 378 --------------
359 379 M b
360 380 --------------
361 381
362 382
363 383 m "um a c" "um x c" " " "10 do merge with no ancestor"
364 384
365 385 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
366 386 created new head
367 387 --------------
368 388 test L:nm a b R:nm a c W: - 11 get c, keep b
369 389 --------------
370 390 searching for copies back to rev 1
371 391 unmatched files in local:
372 392 b
373 393 unmatched files in other:
374 394 c
375 395 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
376 396 src: 'a' -> dst: 'b' !
377 397 src: 'a' -> dst: 'c' !
378 398 checking for directory renames
379 399 resolving manifests
380 400 branchmerge: True, force: False, partial: False
381 401 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
382 402 preserving rev for resolve of rev
383 403 c: remote created -> g
384 404 getting c
385 405 updating: c 1/2 files (50.00%)
386 406 rev: versions differ -> m
387 407 updating: rev 2/2 files (100.00%)
388 408 picked tool 'python ../merge' for rev (binary False symlink False)
389 409 merging rev
390 410 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
411 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
412 merge tool returned: 0
391 413 note: possible conflict - a was renamed multiple times to:
392 414 b
393 415 c
394 416 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
395 417 (branch merge, don't forget to commit)
396 418 --------------
397 419 M c
398 420 C b
399 421 --------------
400 422
401 423 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
402 424 created new head
403 425 --------------
404 426 test L:nc a b R:up b W: - 12 merge b no ancestor
405 427 --------------
406 428 searching for copies back to rev 1
407 429 unmatched files new in both:
408 430 b
409 431 resolving manifests
410 432 branchmerge: True, force: False, partial: False
411 433 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
412 434 preserving b for resolve of b
413 435 preserving rev for resolve of rev
414 436 b: both created -> m
415 437 updating: b 1/2 files (50.00%)
416 438 picked tool 'python ../merge' for b (binary False symlink False)
417 439 merging b
418 440 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
441 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
442 merge tool returned: 0
419 443 rev: versions differ -> m
420 444 updating: rev 2/2 files (100.00%)
421 445 picked tool 'python ../merge' for rev (binary False symlink False)
422 446 merging rev
423 447 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
448 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
449 merge tool returned: 0
424 450 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
425 451 (branch merge, don't forget to commit)
426 452 --------------
427 453 M b
428 454 C a
429 455 --------------
430 456
431 457 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
432 458 created new head
433 459 --------------
434 460 test L:up b R:nm a b W: - 13 merge b no ancestor
435 461 --------------
436 462 searching for copies back to rev 1
437 463 unmatched files new in both:
438 464 b
439 465 resolving manifests
440 466 branchmerge: True, force: False, partial: False
441 467 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
442 468 preserving b for resolve of b
443 469 preserving rev for resolve of rev
444 470 a: other deleted -> r
445 471 removing a
446 472 updating: a 1/3 files (33.33%)
447 473 b: both created -> m
448 474 updating: b 2/3 files (66.67%)
449 475 picked tool 'python ../merge' for b (binary False symlink False)
450 476 merging b
451 477 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
478 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
479 merge tool returned: 0
452 480 rev: versions differ -> m
453 481 updating: rev 3/3 files (100.00%)
454 482 picked tool 'python ../merge' for rev (binary False symlink False)
455 483 merging rev
456 484 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
485 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
486 merge tool returned: 0
457 487 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
458 488 (branch merge, don't forget to commit)
459 489 --------------
460 490 M b
461 491 --------------
462 492
463 493 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
464 494 created new head
465 495 --------------
466 496 test L:nc a b R:up a b W: - 14 merge b no ancestor
467 497 --------------
468 498 searching for copies back to rev 1
469 499 unmatched files new in both:
470 500 b
471 501 resolving manifests
472 502 branchmerge: True, force: False, partial: False
473 503 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
474 504 preserving b for resolve of b
475 505 preserving rev for resolve of rev
476 506 a: remote is newer -> g
477 507 getting a
478 508 updating: a 1/3 files (33.33%)
479 509 b: both created -> m
480 510 updating: b 2/3 files (66.67%)
481 511 picked tool 'python ../merge' for b (binary False symlink False)
482 512 merging b
483 513 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
514 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
515 merge tool returned: 0
484 516 rev: versions differ -> m
485 517 updating: rev 3/3 files (100.00%)
486 518 picked tool 'python ../merge' for rev (binary False symlink False)
487 519 merging rev
488 520 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
521 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
522 merge tool returned: 0
489 523 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
490 524 (branch merge, don't forget to commit)
491 525 --------------
492 526 M a
493 527 M b
494 528 --------------
495 529
496 530 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
497 531 created new head
498 532 --------------
499 533 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
500 534 --------------
501 535 searching for copies back to rev 1
502 536 unmatched files new in both:
503 537 b
504 538 resolving manifests
505 539 branchmerge: True, force: False, partial: False
506 540 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
507 541 preserving b for resolve of b
508 542 preserving rev for resolve of rev
509 543 a: other deleted -> r
510 544 removing a
511 545 updating: a 1/3 files (33.33%)
512 546 b: both created -> m
513 547 updating: b 2/3 files (66.67%)
514 548 picked tool 'python ../merge' for b (binary False symlink False)
515 549 merging b
516 550 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
551 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
552 merge tool returned: 0
517 553 rev: versions differ -> m
518 554 updating: rev 3/3 files (100.00%)
519 555 picked tool 'python ../merge' for rev (binary False symlink False)
520 556 merging rev
521 557 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
558 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
559 merge tool returned: 0
522 560 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
523 561 (branch merge, don't forget to commit)
524 562 --------------
525 563 M b
526 564 --------------
527 565
528 566 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
529 567 created new head
530 568 --------------
531 569 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
532 570 --------------
533 571 searching for copies back to rev 1
534 572 unmatched files new in both:
535 573 b
536 574 resolving manifests
537 575 branchmerge: True, force: False, partial: False
538 576 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
539 577 preserving b for resolve of b
540 578 preserving rev for resolve of rev
541 579 a: remote is newer -> g
542 580 getting a
543 581 updating: a 1/3 files (33.33%)
544 582 b: both created -> m
545 583 updating: b 2/3 files (66.67%)
546 584 picked tool 'python ../merge' for b (binary False symlink False)
547 585 merging b
548 586 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
587 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
588 merge tool returned: 0
549 589 rev: versions differ -> m
550 590 updating: rev 3/3 files (100.00%)
551 591 picked tool 'python ../merge' for rev (binary False symlink False)
552 592 merging rev
553 593 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
594 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
595 merge tool returned: 0
554 596 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
555 597 (branch merge, don't forget to commit)
556 598 --------------
557 599 M a
558 600 M b
559 601 --------------
560 602
561 603 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
562 604 created new head
563 605 --------------
564 606 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
565 607 --------------
566 608 searching for copies back to rev 1
567 609 unmatched files new in both:
568 610 b
569 611 resolving manifests
570 612 branchmerge: True, force: False, partial: False
571 613 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
572 614 preserving b for resolve of b
573 615 preserving rev for resolve of rev
574 616 a: remote unchanged -> k
575 617 b: both created -> m
576 618 updating: b 1/2 files (50.00%)
577 619 picked tool 'python ../merge' for b (binary False symlink False)
578 620 merging b
579 621 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
622 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
623 merge tool returned: 0
580 624 rev: versions differ -> m
581 625 updating: rev 2/2 files (100.00%)
582 626 picked tool 'python ../merge' for rev (binary False symlink False)
583 627 merging rev
584 628 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
629 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
630 merge tool returned: 0
585 631 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
586 632 (branch merge, don't forget to commit)
587 633 --------------
588 634 M b
589 635 C a
590 636 --------------
591 637
592 638 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
593 639 created new head
594 640 --------------
595 641 test L:nm a b R:up a b W: - 18 merge b no ancestor
596 642 --------------
597 643 searching for copies back to rev 1
598 644 unmatched files new in both:
599 645 b
600 646 resolving manifests
601 647 branchmerge: True, force: False, partial: False
602 648 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
603 649 remote changed a which local deleted
604 650 use (c)hanged version or leave (d)eleted? c
605 651 preserving b for resolve of b
606 652 preserving rev for resolve of rev
607 653 a: prompt recreating -> g
608 654 getting a
609 655 updating: a 1/3 files (33.33%)
610 656 b: both created -> m
611 657 updating: b 2/3 files (66.67%)
612 658 picked tool 'python ../merge' for b (binary False symlink False)
613 659 merging b
614 660 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
661 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
662 merge tool returned: 0
615 663 rev: versions differ -> m
616 664 updating: rev 3/3 files (100.00%)
617 665 picked tool 'python ../merge' for rev (binary False symlink False)
618 666 merging rev
619 667 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
668 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
669 merge tool returned: 0
620 670 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
621 671 (branch merge, don't forget to commit)
622 672 --------------
623 673 M a
624 674 M b
625 675 --------------
626 676
627 677 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
628 678 created new head
629 679 --------------
630 680 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
631 681 --------------
632 682 searching for copies back to rev 1
633 683 unmatched files new in both:
634 684 b
635 685 resolving manifests
636 686 branchmerge: True, force: False, partial: False
637 687 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
638 688 local changed a which remote deleted
639 689 use (c)hanged version or (d)elete? c
640 690 preserving b for resolve of b
641 691 preserving rev for resolve of rev
642 692 a: prompt keep -> a
643 693 updating: a 1/3 files (33.33%)
644 694 b: both created -> m
645 695 updating: b 2/3 files (66.67%)
646 696 picked tool 'python ../merge' for b (binary False symlink False)
647 697 merging b
648 698 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
699 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
700 merge tool returned: 0
649 701 rev: versions differ -> m
650 702 updating: rev 3/3 files (100.00%)
651 703 picked tool 'python ../merge' for rev (binary False symlink False)
652 704 merging rev
653 705 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
706 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
707 merge tool returned: 0
654 708 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
655 709 (branch merge, don't forget to commit)
656 710 --------------
657 711 M b
658 712 C a
659 713 --------------
660 714
661 715 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
662 716 created new head
663 717 --------------
664 718 test L:up a R:um a b W: - 20 merge a and b to b, remove a
665 719 --------------
666 720 searching for copies back to rev 1
667 721 unmatched files in other:
668 722 b
669 723 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
670 724 src: 'a' -> dst: 'b' *
671 725 checking for directory renames
672 726 resolving manifests
673 727 branchmerge: True, force: False, partial: False
674 728 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
675 729 preserving a for resolve of b
676 730 preserving rev for resolve of rev
677 731 removing a
678 732 b: remote moved from a -> m
679 733 updating: b 1/2 files (50.00%)
680 734 picked tool 'python ../merge' for b (binary False symlink False)
681 735 merging a and b to b
682 736 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
737 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
738 merge tool returned: 0
683 739 rev: versions differ -> m
684 740 updating: rev 2/2 files (100.00%)
685 741 picked tool 'python ../merge' for rev (binary False symlink False)
686 742 merging rev
687 743 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
744 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
745 merge tool returned: 0
688 746 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
689 747 (branch merge, don't forget to commit)
690 748 --------------
691 749 M b
692 750 a
693 751 --------------
694 752
695 753 $ tm "um a b" "up a " " " "21 merge a and b to b"
696 754 created new head
697 755 --------------
698 756 test L:um a b R:up a W: - 21 merge a and b to b
699 757 --------------
700 758 searching for copies back to rev 1
701 759 unmatched files in local:
702 760 b
703 761 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
704 762 src: 'a' -> dst: 'b' *
705 763 checking for directory renames
706 764 resolving manifests
707 765 branchmerge: True, force: False, partial: False
708 766 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
709 767 preserving b for resolve of b
710 768 preserving rev for resolve of rev
711 769 b: local copied/moved from a -> m
712 770 updating: b 1/2 files (50.00%)
713 771 picked tool 'python ../merge' for b (binary False symlink False)
714 772 merging b and a to b
715 773 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
774 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
775 merge tool returned: 0
716 776 rev: versions differ -> m
717 777 updating: rev 2/2 files (100.00%)
718 778 picked tool 'python ../merge' for rev (binary False symlink False)
719 779 merging rev
720 780 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
781 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
782 merge tool returned: 0
721 783 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
722 784 (branch merge, don't forget to commit)
723 785 --------------
724 786 M b
725 787 a
726 788 --------------
727 789
728 790
729 791 m "nm a b" "um x a" " " "22 get a, keep b"
730 792
731 793 $ tm "nm a b" "up a c" " " "23 get c, keep b"
732 794 created new head
733 795 --------------
734 796 test L:nm a b R:up a c W: - 23 get c, keep b
735 797 --------------
736 798 searching for copies back to rev 1
737 799 unmatched files in local:
738 800 b
739 801 unmatched files in other:
740 802 c
741 803 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
742 804 src: 'a' -> dst: 'b' *
743 805 checking for directory renames
744 806 resolving manifests
745 807 branchmerge: True, force: False, partial: False
746 808 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
747 809 preserving b for resolve of b
748 810 preserving rev for resolve of rev
749 811 c: remote created -> g
750 812 getting c
751 813 updating: c 1/3 files (33.33%)
752 814 b: local copied/moved from a -> m
753 815 updating: b 2/3 files (66.67%)
754 816 picked tool 'python ../merge' for b (binary False symlink False)
755 817 merging b and a to b
756 818 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
757 819 premerge successful
758 820 rev: versions differ -> m
759 821 updating: rev 3/3 files (100.00%)
760 822 picked tool 'python ../merge' for rev (binary False symlink False)
761 823 merging rev
762 824 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
825 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
826 merge tool returned: 0
763 827 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
764 828 (branch merge, don't forget to commit)
765 829 --------------
766 830 M b
767 831 a
768 832 M c
769 833 --------------
770 834
771 835
772 836 $ cd ..
773 837
774 838
775 839 Systematic and terse testing of merge merges and ancestor calculation:
776 840
777 841 Expected result:
778 842
779 843 \ a m1 m2 dst
780 844 0 - f f f "versions differ"
781 845 1 f g g g "versions differ"
782 846 2 f f f f "versions differ"
783 847 3 f f g f+g "remote copied to " + f
784 848 4 f f g g "remote moved to " + f
785 849 5 f g f f+g "local copied to " + f2
786 850 6 f g f g "local moved to " + f2
787 851 7 - (f) f f "remote differs from untracked local"
788 852 8 f (f) f f "remote differs from untracked local"
789 853
790 854 $ hg init ancestortest
791 855 $ cd ancestortest
792 856 $ for x in 1 2 3 4 5 6 8; do mkdir $x; echo a > $x/f; done
793 857 $ hg ci -Aqm "a"
794 858 $ mkdir 0
795 859 $ touch 0/f
796 860 $ hg mv 1/f 1/g
797 861 $ hg cp 5/f 5/g
798 862 $ hg mv 6/f 6/g
799 863 $ hg rm 8/f
800 864 $ for x in */*; do echo m1 > $x; done
801 865 $ hg ci -Aqm "m1"
802 866 $ hg up -qr0
803 867 $ mkdir 0 7
804 868 $ touch 0/f 7/f
805 869 $ hg mv 1/f 1/g
806 870 $ hg cp 3/f 3/g
807 871 $ hg mv 4/f 4/g
808 872 $ for x in */*; do echo m2 > $x; done
809 873 $ hg ci -Aqm "m2"
810 874 $ hg up -qr1
811 875 $ mkdir 7 8
812 876 $ echo m > 7/f
813 877 $ echo m > 8/f
814 878 $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^updating:/,$d' 2> /dev/null
815 879 searching for copies back to rev 1
816 880 unmatched files in local:
817 881 5/g
818 882 6/g
819 883 unmatched files in other:
820 884 3/g
821 885 4/g
822 886 7/f
823 887 unmatched files new in both:
824 888 0/f
825 889 1/g
826 890 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
827 891 src: '3/f' -> dst: '3/g' *
828 892 src: '4/f' -> dst: '4/g' *
829 893 src: '5/f' -> dst: '5/g' *
830 894 src: '6/f' -> dst: '6/g' *
831 895 checking for directory renames
832 896 resolving manifests
833 897 branchmerge: True, force: True, partial: False
834 898 ancestor: e6cb3cf11019, local: ec44bf929ab5+, remote: c62e34d0b898
835 899 remote changed 8/f which local deleted
836 900 use (c)hanged version or leave (d)eleted? c
837 901 preserving 0/f for resolve of 0/f
838 902 preserving 1/g for resolve of 1/g
839 903 preserving 2/f for resolve of 2/f
840 904 preserving 3/f for resolve of 3/f
841 905 preserving 3/f for resolve of 3/g
842 906 preserving 4/f for resolve of 4/g
843 907 preserving 5/f for resolve of 5/f
844 908 preserving 5/g for resolve of 5/g
845 909 preserving 6/g for resolve of 6/g
846 910 preserving 7/f for resolve of 7/f
847 911 removing 4/f
848 912 8/f: prompt recreating -> g
849 913 getting 8/f
850 914 $ hg mani
851 915 0/f
852 916 1/g
853 917 2/f
854 918 3/f
855 919 4/f
856 920 5/f
857 921 5/g
858 922 6/g
859 923 $ for f in */*; do echo $f:; cat $f; done
860 924 0/f:
861 925 m1
862 926 0/f.base:
863 927 0/f.local:
864 928 m1
865 929 0/f.orig:
866 930 m1
867 931 0/f.other:
868 932 m2
869 933 1/g:
870 934 m1
871 935 1/g.base:
872 936 a
873 937 1/g.local:
874 938 m1
875 939 1/g.orig:
876 940 m1
877 941 1/g.other:
878 942 m2
879 943 2/f:
880 944 m1
881 945 2/f.base:
882 946 a
883 947 2/f.local:
884 948 m1
885 949 2/f.orig:
886 950 m1
887 951 2/f.other:
888 952 m2
889 953 3/f:
890 954 m1
891 955 3/f.base:
892 956 a
893 957 3/f.local:
894 958 m1
895 959 3/f.orig:
896 960 m1
897 961 3/f.other:
898 962 m2
899 963 3/g:
900 964 m1
901 965 3/g.base:
902 966 a
903 967 3/g.local:
904 968 m1
905 969 3/g.orig:
906 970 m1
907 971 3/g.other:
908 972 m2
909 973 4/g:
910 974 m1
911 975 4/g.base:
912 976 a
913 977 4/g.local:
914 978 m1
915 979 4/g.orig:
916 980 m1
917 981 4/g.other:
918 982 m2
919 983 5/f:
920 984 m1
921 985 5/f.base:
922 986 a
923 987 5/f.local:
924 988 m1
925 989 5/f.orig:
926 990 m1
927 991 5/f.other:
928 992 m2
929 993 5/g:
930 994 m1
931 995 5/g.base:
932 996 a
933 997 5/g.local:
934 998 m1
935 999 5/g.orig:
936 1000 m1
937 1001 5/g.other:
938 1002 m2
939 1003 6/g:
940 1004 m1
941 1005 6/g.base:
942 1006 a
943 1007 6/g.local:
944 1008 m1
945 1009 6/g.orig:
946 1010 m1
947 1011 6/g.other:
948 1012 m2
949 1013 7/f:
950 1014 m
951 1015 7/f.base:
952 1016 7/f.local:
953 1017 m
954 1018 7/f.orig:
955 1019 m
956 1020 7/f.other:
957 1021 m2
958 1022 8/f:
959 1023 m2
960 1024 $ cd ..
@@ -1,222 +1,228
1 1 $ HGMERGE=true; export HGMERGE
2 2
3 3 $ hg init r1
4 4 $ cd r1
5 5 $ echo a > a
6 6 $ hg addremove
7 7 adding a
8 8 $ hg commit -m "1"
9 9
10 10 $ hg clone . ../r2
11 11 updating to branch default
12 12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 13 $ cd ../r2
14 14 $ hg up
15 15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 16 $ echo abc > a
17 17 $ hg diff --nodates
18 18 diff -r c19d34741b0a a
19 19 --- a/a
20 20 +++ b/a
21 21 @@ -1,1 +1,1 @@
22 22 -a
23 23 +abc
24 24
25 25 $ cd ../r1
26 26 $ echo b > b
27 27 $ echo a2 > a
28 28 $ hg addremove
29 29 adding b
30 30 $ hg commit -m "2"
31 31
32 32 $ cd ../r2
33 33 $ hg -q pull ../r1
34 34 $ hg status
35 35 M a
36 36 $ hg parents
37 37 changeset: 0:c19d34741b0a
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: 1
41 41
42 42 $ hg --debug up
43 43 searching for copies back to rev 1
44 44 unmatched files in other:
45 45 b
46 46 resolving manifests
47 47 branchmerge: False, force: False, partial: False
48 48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
49 49 preserving a for resolve of a
50 50 b: remote created -> g
51 51 getting b
52 52 updating: b 1/2 files (50.00%)
53 53 a: versions differ -> m
54 54 updating: a 2/2 files (100.00%)
55 55 picked tool 'true' for a (binary False symlink False)
56 56 merging a
57 57 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
58 launching merge tool: true $TESTTMP/r2/a * (glob)
59 merge tool returned: 0
58 60 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
59 61 $ hg parents
60 62 changeset: 1:1e71731e6fbb
61 63 tag: tip
62 64 user: test
63 65 date: Thu Jan 01 00:00:00 1970 +0000
64 66 summary: 2
65 67
66 68 $ hg --debug up 0
67 69 resolving manifests
68 70 branchmerge: False, force: False, partial: False
69 71 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
70 72 preserving a for resolve of a
71 73 b: other deleted -> r
72 74 removing b
73 75 updating: b 1/2 files (50.00%)
74 76 a: versions differ -> m
75 77 updating: a 2/2 files (100.00%)
76 78 picked tool 'true' for a (binary False symlink False)
77 79 merging a
78 80 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
81 launching merge tool: true $TESTTMP/r2/a * (glob)
82 merge tool returned: 0
79 83 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
80 84 $ hg parents
81 85 changeset: 0:c19d34741b0a
82 86 user: test
83 87 date: Thu Jan 01 00:00:00 1970 +0000
84 88 summary: 1
85 89
86 90 $ hg parents
87 91 changeset: 0:c19d34741b0a
88 92 user: test
89 93 date: Thu Jan 01 00:00:00 1970 +0000
90 94 summary: 1
91 95
92 96 $ hg --debug up
93 97 searching for copies back to rev 1
94 98 unmatched files in other:
95 99 b
96 100 resolving manifests
97 101 branchmerge: False, force: False, partial: False
98 102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
99 103 preserving a for resolve of a
100 104 b: remote created -> g
101 105 getting b
102 106 updating: b 1/2 files (50.00%)
103 107 a: versions differ -> m
104 108 updating: a 2/2 files (100.00%)
105 109 picked tool 'true' for a (binary False symlink False)
106 110 merging a
107 111 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
112 launching merge tool: true $TESTTMP/r2/a * (glob)
113 merge tool returned: 0
108 114 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
109 115 $ hg parents
110 116 changeset: 1:1e71731e6fbb
111 117 tag: tip
112 118 user: test
113 119 date: Thu Jan 01 00:00:00 1970 +0000
114 120 summary: 2
115 121
116 122 $ hg -v history
117 123 changeset: 1:1e71731e6fbb
118 124 tag: tip
119 125 user: test
120 126 date: Thu Jan 01 00:00:00 1970 +0000
121 127 files: a b
122 128 description:
123 129 2
124 130
125 131
126 132 changeset: 0:c19d34741b0a
127 133 user: test
128 134 date: Thu Jan 01 00:00:00 1970 +0000
129 135 files: a
130 136 description:
131 137 1
132 138
133 139
134 140 $ hg diff --nodates
135 141 diff -r 1e71731e6fbb a
136 142 --- a/a
137 143 +++ b/a
138 144 @@ -1,1 +1,1 @@
139 145 -a2
140 146 +abc
141 147
142 148
143 149 create a second head
144 150
145 151 $ cd ../r1
146 152 $ hg up 0
147 153 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
148 154 $ echo b2 > b
149 155 $ echo a3 > a
150 156 $ hg addremove
151 157 adding b
152 158 $ hg commit -m "3"
153 159 created new head
154 160
155 161 $ cd ../r2
156 162 $ hg -q pull ../r1
157 163 $ hg status
158 164 M a
159 165 $ hg parents
160 166 changeset: 1:1e71731e6fbb
161 167 user: test
162 168 date: Thu Jan 01 00:00:00 1970 +0000
163 169 summary: 2
164 170
165 171 $ hg --debug up
166 172 abort: uncommitted changes
167 173 (commit and merge, or update --clean to discard changes)
168 174 [255]
169 175
170 176 test conflicting untracked files
171 177
172 178 $ hg up -qC 0
173 179 $ echo untracked > b
174 180 $ hg st
175 181 ? b
176 182 $ hg up 1
177 183 b: untracked file differs
178 184 abort: untracked files in working directory differ from files in requested revision
179 185 [255]
180 186 $ rm b
181 187
182 188 test conflicting untracked ignored file
183 189
184 190 $ hg up -qC 0
185 191 $ echo ignored > .hgignore
186 192 $ hg add .hgignore
187 193 $ hg ci -m 'add .hgignore'
188 194 created new head
189 195 $ echo ignored > ignored
190 196 $ hg add ignored
191 197 $ hg ci -m 'add ignored file'
192 198
193 199 $ hg up -q 'desc("add .hgignore")'
194 200 $ echo untracked > ignored
195 201 $ hg st
196 202 $ hg up 'desc("add ignored file")'
197 203 ignored: untracked file differs
198 204 abort: untracked files in working directory differ from files in requested revision
199 205 [255]
200 206
201 207 test a local add
202 208
203 209 $ cd ..
204 210 $ hg init a
205 211 $ hg init b
206 212 $ echo a > a/a
207 213 $ echo a > b/a
208 214 $ hg --cwd a commit -A -m a
209 215 adding a
210 216 $ cd b
211 217 $ hg add a
212 218 $ hg pull -u ../a
213 219 pulling from ../a
214 220 requesting all changes
215 221 adding changesets
216 222 adding manifests
217 223 adding file changes
218 224 added 1 changesets with 1 changes to 1 files
219 225 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 226 $ hg st
221 227
222 228 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now