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: