Mercurial > public > mercurial-scm > hg
comparison mercurial/merge.py @ 20640:52929dcdd512
merge: handle create+delete prompts in calculateupdates
I would like to move it all the way to the interactive resolve state like
merges are ... but this is a first intermediate step.
author | Mads Kiilerich <madski@unity3d.com> |
---|---|
date | Sun, 02 Mar 2014 18:36:02 +0100 |
parents | 1df033640a8e |
children | 0dc7a50345c2 |
comparison
equal
deleted
inserted
replaced
20639:1df033640a8e | 20640:52929dcdd512 |
---|---|
261 if f not in mctx: | 261 if f not in mctx: |
262 actions.append((f, "f", None, "forget removed")) | 262 actions.append((f, "f", None, "forget removed")) |
263 | 263 |
264 return actions | 264 return actions |
265 | 265 |
266 def _checkcollision(repo, wmf, actions, prompts): | 266 def _checkcollision(repo, wmf, actions): |
267 # build provisional merged manifest up | 267 # build provisional merged manifest up |
268 pmmf = set(wmf) | 268 pmmf = set(wmf) |
269 | 269 |
270 def addop(f, args): | 270 def addop(f, args): |
271 pmmf.add(f) | 271 pmmf.add(f) |
293 "f": addop, # untracked file should be kept in working directory | 293 "f": addop, # untracked file should be kept in working directory |
294 "g": addop, | 294 "g": addop, |
295 "m": mergeop, | 295 "m": mergeop, |
296 "r": removeop, | 296 "r": removeop, |
297 "rd": nop, | 297 "rd": nop, |
298 "cd": addop, | |
299 "dc": addop, | |
298 } | 300 } |
299 for f, m, args, msg in actions: | 301 for f, m, args, msg in actions: |
300 op = opmap.get(m) | 302 op = opmap.get(m) |
301 assert op, m | 303 assert op, m |
302 op(f, args) | 304 op(f, args) |
303 | |
304 opmap = { | |
305 "cd": addop, | |
306 "dc": addop, | |
307 } | |
308 for f, m in prompts: | |
309 op = opmap.get(m) | |
310 assert op, m | |
311 op(f, None) | |
312 | 305 |
313 # check case-folding collision in provisional merged manifest | 306 # check case-folding collision in provisional merged manifest |
314 foldmap = {} | 307 foldmap = {} |
315 for f in sorted(pmmf): | 308 for f in sorted(pmmf): |
316 fold = util.normcase(f) | 309 fold = util.normcase(f) |
368 for s in sorted(wctx.substate): | 361 for s in sorted(wctx.substate): |
369 if wctx.sub(s).dirty(): | 362 if wctx.sub(s).dirty(): |
370 m1['.hgsubstate'] += "+" | 363 m1['.hgsubstate'] += "+" |
371 break | 364 break |
372 | 365 |
373 aborts, prompts = [], [] | 366 aborts = [] |
374 # Compare manifests | 367 # Compare manifests |
375 fdiff = dicthelpers.diff(m1, m2) | 368 fdiff = dicthelpers.diff(m1, m2) |
376 flagsdiff = m1.flagsdiff(m2) | 369 flagsdiff = m1.flagsdiff(m2) |
377 diff12 = dicthelpers.join(fdiff, flagsdiff) | 370 diff12 = dicthelpers.join(fdiff, flagsdiff) |
378 | 371 |
424 elif n1 and f in ma: # clean, a different, no remote | 417 elif n1 and f in ma: # clean, a different, no remote |
425 if n1 != ma[f]: | 418 if n1 != ma[f]: |
426 if acceptremote: | 419 if acceptremote: |
427 actions.append((f, "r", None, "remote delete")) | 420 actions.append((f, "r", None, "remote delete")) |
428 else: | 421 else: |
429 prompts.append((f, "cd")) # prompt changed/deleted | 422 actions.append((f, "cd", None, "prompt changed/deleted")) |
430 elif n1[20:] == "a": # added, no remote | 423 elif n1[20:] == "a": # added, no remote |
431 actions.append((f, "f", None, "remote deleted")) | 424 actions.append((f, "f", None, "remote deleted")) |
432 else: | 425 else: |
433 actions.append((f, "r", None, "other deleted")) | 426 actions.append((f, "r", None, "other deleted")) |
434 elif n2 and f in movewithdir: | 427 elif n2 and f in movewithdir: |
475 # if different: old untracked f may be overwritten and lost | 468 # if different: old untracked f may be overwritten and lost |
476 if acceptremote: | 469 if acceptremote: |
477 actions.append((f, "g", (m2.flags(f),), | 470 actions.append((f, "g", (m2.flags(f),), |
478 "remote recreating")) | 471 "remote recreating")) |
479 else: | 472 else: |
480 prompts.append((f, "dc")) # prompt deleted/changed | 473 actions.append((f, "dc", (m2.flags(f),), |
474 "prompt deleted/changed")) | |
481 | 475 |
482 for f, m in sorted(aborts): | 476 for f, m in sorted(aborts): |
483 if m == "ud": | 477 if m == "ud": |
484 repo.ui.warn(_("%s: untracked file differs\n") % f) | 478 repo.ui.warn(_("%s: untracked file differs\n") % f) |
485 else: assert False, m | 479 else: assert False, m |
489 | 483 |
490 if not util.checkcase(repo.path): | 484 if not util.checkcase(repo.path): |
491 # check collision between files only in p2 for clean update | 485 # check collision between files only in p2 for clean update |
492 if (not branchmerge and | 486 if (not branchmerge and |
493 (force or not wctx.dirty(missing=True, branch=False))): | 487 (force or not wctx.dirty(missing=True, branch=False))): |
494 _checkcollision(repo, m2, [], []) | 488 _checkcollision(repo, m2, []) |
495 else: | 489 else: |
496 _checkcollision(repo, m1, actions, prompts) | 490 _checkcollision(repo, m1, actions) |
497 | 491 |
498 for f, m in sorted(prompts): | |
499 if m == "cd": | |
500 if repo.ui.promptchoice( | |
501 _("local changed %s which remote deleted\n" | |
502 "use (c)hanged version or (d)elete?" | |
503 "$$ &Changed $$ &Delete") % f, 0): | |
504 actions.append((f, "r", None, "prompt delete")) | |
505 else: | |
506 actions.append((f, "a", None, "prompt keep")) | |
507 elif m == "dc": | |
508 if repo.ui.promptchoice( | |
509 _("remote changed %s which local deleted\n" | |
510 "use (c)hanged version or leave (d)eleted?" | |
511 "$$ &Changed $$ &Deleted") % f, 0) == 0: | |
512 actions.append((f, "g", (m2.flags(f),), "prompt recreating")) | |
513 else: assert False, m | |
514 return actions | 492 return actions |
515 | 493 |
516 def actionkey(a): | 494 def actionkey(a): |
517 return a[1] in "rf" and -1 or 0, a | 495 return a[1] in "rf" and -1 or 0, a |
518 | 496 |
692 actions = [] | 670 actions = [] |
693 actions += manifestmerge(repo, tctx, mctx, | 671 actions += manifestmerge(repo, tctx, mctx, |
694 ancestor, | 672 ancestor, |
695 branchmerge, force, | 673 branchmerge, force, |
696 partial, acceptremote) | 674 partial, acceptremote) |
675 | |
676 # Filter out prompts. | |
677 newactions, prompts = [], [] | |
678 for a in actions: | |
679 if a[1] in ("cd", "dc"): | |
680 prompts.append(a) | |
681 else: | |
682 newactions.append(a) | |
683 # Prompt and create actions. TODO: Move this towards resolve phase. | |
684 for f, m, args, msg in sorted(prompts): | |
685 if m == "cd": | |
686 if repo.ui.promptchoice( | |
687 _("local changed %s which remote deleted\n" | |
688 "use (c)hanged version or (d)elete?" | |
689 "$$ &Changed $$ &Delete") % f, 0): | |
690 newactions.append((f, "r", None, "prompt delete")) | |
691 else: | |
692 newactions.append((f, "a", None, "prompt keep")) | |
693 elif m == "dc": | |
694 flags, = args | |
695 if repo.ui.promptchoice( | |
696 _("remote changed %s which local deleted\n" | |
697 "use (c)hanged version or leave (d)eleted?" | |
698 "$$ &Changed $$ &Deleted") % f, 0) == 0: | |
699 newactions.append((f, "g", (flags,), "prompt recreating")) | |
700 else: assert False, m | |
701 | |
697 if tctx.rev() is None: | 702 if tctx.rev() is None: |
698 actions += _forgetremoved(tctx, mctx, branchmerge) | 703 newactions += _forgetremoved(tctx, mctx, branchmerge) |
699 return actions | 704 |
705 return newactions | |
700 | 706 |
701 def recordupdates(repo, actions, branchmerge): | 707 def recordupdates(repo, actions, branchmerge): |
702 "record merge actions to the dirstate" | 708 "record merge actions to the dirstate" |
703 | 709 |
704 for a in actions: | 710 for a in actions: |