##// END OF EJS Templates
merge: use separate lists for each action type...
Mads Kiilerich -
r21545:43eecb4e default
parent child Browse files
Show More
@@ -410,14 +410,13 b' def overridecalculateupdates(origfn, rep'
410 if overwrite:
410 if overwrite:
411 return actions
411 return actions
412
412
413 removes = set(a[0] for a in actions if a[1] == 'r')
413 removes = set(a[0] for a in actions['r'])
414 processed = []
415
414
416 for action in actions:
415 newglist = []
417 f, m, args, msg = action
416 for action in actions['g']:
418
417 f, args, msg = action
419 splitstandin = f and lfutil.splitstandin(f)
418 splitstandin = f and lfutil.splitstandin(f)
420 if (m == "g" and splitstandin is not None and
419 if (splitstandin is not None and
421 splitstandin in p1 and splitstandin not in removes):
420 splitstandin in p1 and splitstandin not in removes):
422 # Case 1: normal file in the working copy, largefile in
421 # Case 1: normal file in the working copy, largefile in
423 # the second parent
422 # the second parent
@@ -427,12 +426,11 b' def overridecalculateupdates(origfn, rep'
427 'use (l)argefile or keep (n)ormal file?'
426 'use (l)argefile or keep (n)ormal file?'
428 '$$ &Largefile $$ &Normal file') % lfile
427 '$$ &Largefile $$ &Normal file') % lfile
429 if repo.ui.promptchoice(msg, 0) == 0:
428 if repo.ui.promptchoice(msg, 0) == 0:
430 processed.append((lfile, "r", None, msg))
429 actions['r'].append((lfile, None, msg))
431 processed.append((standin, "g", (p2.flags(standin),), msg))
430 newglist.append((standin, (p2.flags(standin),), msg))
432 else:
431 else:
433 processed.append((standin, "r", None, msg))
432 actions['r'].append((standin, None, msg))
434 elif (m == "g" and
433 elif lfutil.standin(f) in p1 and lfutil.standin(f) not in removes:
435 lfutil.standin(f) in p1 and lfutil.standin(f) not in removes):
436 # Case 2: largefile in the working copy, normal file in
434 # Case 2: largefile in the working copy, normal file in
437 # the second parent
435 # the second parent
438 standin = lfutil.standin(f)
436 standin = lfutil.standin(f)
@@ -441,14 +439,17 b' def overridecalculateupdates(origfn, rep'
441 'keep (l)argefile or use (n)ormal file?'
439 'keep (l)argefile or use (n)ormal file?'
442 '$$ &Largefile $$ &Normal file') % lfile
440 '$$ &Largefile $$ &Normal file') % lfile
443 if repo.ui.promptchoice(msg, 0) == 0:
441 if repo.ui.promptchoice(msg, 0) == 0:
444 processed.append((lfile, "r", None, msg))
442 actions['r'].append((lfile, None, msg))
445 else:
443 else:
446 processed.append((standin, "r", None, msg))
444 actions['r'].append((standin, None, msg))
447 processed.append((lfile, "g", (p2.flags(lfile),), msg))
445 newglist.append((lfile, (p2.flags(lfile),), msg))
448 else:
446 else:
449 processed.append(action)
447 newglist.append(action)
450
448
451 return processed
449 newglist.sort()
450 actions['g'] = newglist
451
452 return actions
452
453
453 # Override filemerge to prompt the user about how they wish to merge
454 # Override filemerge to prompt the user about how they wish to merge
454 # largefiles. This will handle identical edits without prompting the user.
455 # largefiles. This will handle identical edits without prompting the user.
@@ -331,62 +331,44 b' def _forgetremoved(wctx, mctx, branchmer'
331 as removed.
331 as removed.
332 """
332 """
333
333
334 actions = []
334 ractions = []
335 state = branchmerge and 'r' or 'f'
335 factions = xactions = []
336 if branchmerge:
337 xactions = ractions
336 for f in wctx.deleted():
338 for f in wctx.deleted():
337 if f not in mctx:
339 if f not in mctx:
338 actions.append((f, state, None, "forget deleted"))
340 xactions.append((f, None, "forget deleted"))
339
341
340 if not branchmerge:
342 if not branchmerge:
341 for f in wctx.removed():
343 for f in wctx.removed():
342 if f not in mctx:
344 if f not in mctx:
343 actions.append((f, "f", None, "forget removed"))
345 factions.append((f, None, "forget removed"))
344
346
345 return actions
347 return ractions, factions
346
348
347 def _checkcollision(repo, wmf, actions):
349 def _checkcollision(repo, wmf, actions):
348 # build provisional merged manifest up
350 # build provisional merged manifest up
349 pmmf = set(wmf)
351 pmmf = set(wmf)
350
352
351 def addop(f, args):
353 if actions:
352 pmmf.add(f)
354 # k, dr, e and rd are no-op
353 def removeop(f, args):
355 for m in 'a', 'f', 'g', 'cd', 'dc':
354 pmmf.discard(f)
356 for f, args, msg in actions[m]:
355 def nop(f, args):
357 pmmf.add(f)
356 pass
358 for f, args, msg in actions['r']:
357
359 pmmf.discard(f)
358 def renamemoveop(f, args):
360 for f, args, msg in actions['dm']:
359 f2, flags = args
361 f2, flags = args
360 pmmf.discard(f2)
362 pmmf.discard(f2)
361 pmmf.add(f)
363 pmmf.add(f)
362 def renamegetop(f, args):
364 for f, args, msg in actions['dg']:
363 f2, flags = args
365 f2, flags = args
364 pmmf.add(f)
366 pmmf.add(f)
365 def mergeop(f, args):
367 for f, args, msg in actions['m']:
366 f1, f2, fa, move, anc = args
368 f1, f2, fa, move, anc = args
367 if move:
369 if move:
368 pmmf.discard(f1)
370 pmmf.discard(f1)
369 pmmf.add(f)
371 pmmf.add(f)
370
371 opmap = {
372 "a": addop,
373 "dm": renamemoveop,
374 "dg": renamegetop,
375 "dr": nop,
376 "e": nop,
377 "k": nop,
378 "f": addop, # untracked file should be kept in working directory
379 "g": addop,
380 "m": mergeop,
381 "r": removeop,
382 "rd": nop,
383 "cd": addop,
384 "dc": addop,
385 }
386 for f, m, args, msg in actions:
387 op = opmap.get(m)
388 assert op, m
389 op(f, args)
390
372
391 # check case-folding collision in provisional merged manifest
373 # check case-folding collision in provisional merged manifest
392 foldmap = {}
374 foldmap = {}
@@ -407,7 +389,8 b' def manifestmerge(repo, wctx, p2, pa, br'
407 acceptremote = accept the incoming changes without prompting
389 acceptremote = accept the incoming changes without prompting
408 """
390 """
409
391
410 actions, copy, movewithdir = [], {}, {}
392 actions = dict((m, []) for m in 'a f g cd dc r dm dg m dr e rd k'.split())
393 copy, movewithdir = {}, {}
411
394
412 # manifests fetched in order are going to be faster, so prime the caches
395 # manifests fetched in order are going to be faster, so prime the caches
413 [x.manifest() for x in
396 [x.manifest() for x in
@@ -417,9 +400,9 b' def manifestmerge(repo, wctx, p2, pa, br'
417 ret = copies.mergecopies(repo, wctx, p2, pa)
400 ret = copies.mergecopies(repo, wctx, p2, pa)
418 copy, movewithdir, diverge, renamedelete = ret
401 copy, movewithdir, diverge, renamedelete = ret
419 for of, fl in diverge.iteritems():
402 for of, fl in diverge.iteritems():
420 actions.append((of, "dr", (fl,), "divergent renames"))
403 actions['dr'].append((of, (fl,), "divergent renames"))
421 for of, fl in renamedelete.iteritems():
404 for of, fl in renamedelete.iteritems():
422 actions.append((of, "rd", (fl,), "rename and delete"))
405 actions['rd'].append((of, (fl,), "rename and delete"))
423
406
424 repo.ui.note(_("resolving manifests\n"))
407 repo.ui.note(_("resolving manifests\n"))
425 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
408 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
@@ -471,50 +454,50 b' def manifestmerge(repo, wctx, p2, pa, br'
471 fla = ma.flags(fa)
454 fla = ma.flags(fa)
472 nol = 'l' not in fl1 + fl2 + fla
455 nol = 'l' not in fl1 + fl2 + fla
473 if n2 == a and fl2 == fla:
456 if n2 == a and fl2 == fla:
474 actions.append((f, "k", (), "keep")) # remote unchanged
457 actions['k'].append((f, (), "keep")) # remote unchanged
475 elif n1 == a and fl1 == fla: # local unchanged - use remote
458 elif n1 == a and fl1 == fla: # local unchanged - use remote
476 if n1 == n2: # optimization: keep local content
459 if n1 == n2: # optimization: keep local content
477 actions.append((f, "e", (fl2,), "update permissions"))
460 actions['e'].append((f, (fl2,), "update permissions"))
478 else:
461 else:
479 actions.append((f, "g", (fl2,), "remote is newer"))
462 actions['g'].append((f, (fl2,), "remote is newer"))
480 elif nol and n2 == a: # remote only changed 'x'
463 elif nol and n2 == a: # remote only changed 'x'
481 actions.append((f, "e", (fl2,), "update permissions"))
464 actions['e'].append((f, (fl2,), "update permissions"))
482 elif nol and n1 == a: # local only changed 'x'
465 elif nol and n1 == a: # local only changed 'x'
483 actions.append((f, "g", (fl1,), "remote is newer"))
466 actions['g'].append((f, (fl1,), "remote is newer"))
484 else: # both changed something
467 else: # both changed something
485 actions.append((f, "m", (f, f, fa, False, pa.node()),
468 actions['m'].append((f, (f, f, fa, False, pa.node()),
486 "versions differ"))
469 "versions differ"))
487 elif f in copied: # files we'll deal with on m2 side
470 elif f in copied: # files we'll deal with on m2 side
488 pass
471 pass
489 elif n1 and f in movewithdir: # directory rename, move local
472 elif n1 and f in movewithdir: # directory rename, move local
490 f2 = movewithdir[f]
473 f2 = movewithdir[f]
491 actions.append((f2, "dm", (f, fl1),
474 actions['dm'].append((f2, (f, fl1),
492 "remote directory rename - move from " + f))
475 "remote directory rename - move from " + f))
493 elif n1 and f in copy:
476 elif n1 and f in copy:
494 f2 = copy[f]
477 f2 = copy[f]
495 actions.append((f, "m", (f, f2, f2, False, pa.node()),
478 actions['m'].append((f, (f, f2, f2, False, pa.node()),
496 "local copied/moved from " + f2))
479 "local copied/moved from " + f2))
497 elif n1 and f in ma: # clean, a different, no remote
480 elif n1 and f in ma: # clean, a different, no remote
498 if n1 != ma[f]:
481 if n1 != ma[f]:
499 if acceptremote:
482 if acceptremote:
500 actions.append((f, "r", None, "remote delete"))
483 actions['r'].append((f, None, "remote delete"))
501 else:
484 else:
502 actions.append((f, "cd", None, "prompt changed/deleted"))
485 actions['cd'].append((f, None, "prompt changed/deleted"))
503 elif n1[20:] == "a": # added, no remote
486 elif n1[20:] == "a": # added, no remote
504 actions.append((f, "f", None, "remote deleted"))
487 actions['f'].append((f, None, "remote deleted"))
505 else:
488 else:
506 actions.append((f, "r", None, "other deleted"))
489 actions['r'].append((f, None, "other deleted"))
507 elif n2 and f in movewithdir:
490 elif n2 and f in movewithdir:
508 f2 = movewithdir[f]
491 f2 = movewithdir[f]
509 actions.append((f2, "dg", (f, fl2),
492 actions['dg'].append((f2, (f, fl2),
510 "local directory rename - get from " + f))
493 "local directory rename - get from " + f))
511 elif n2 and f in copy:
494 elif n2 and f in copy:
512 f2 = copy[f]
495 f2 = copy[f]
513 if f2 in m2:
496 if f2 in m2:
514 actions.append((f, "m", (f2, f, f2, False, pa.node()),
497 actions['m'].append((f, (f2, f, f2, False, pa.node()),
515 "remote copied from " + f2))
498 "remote copied from " + f2))
516 else:
499 else:
517 actions.append((f, "m", (f2, f, f2, True, pa.node()),
500 actions['m'].append((f, (f2, f, f2, True, pa.node()),
518 "remote moved from " + f2))
501 "remote moved from " + f2))
519 elif n2 and f not in ma:
502 elif n2 and f not in ma:
520 # local unknown, remote created: the logic is described by the
503 # local unknown, remote created: the logic is described by the
@@ -530,17 +513,17 b' def manifestmerge(repo, wctx, p2, pa, br'
530 # Checking whether the files are different is expensive, so we
513 # Checking whether the files are different is expensive, so we
531 # don't do that when we can avoid it.
514 # don't do that when we can avoid it.
532 if force and not branchmerge:
515 if force and not branchmerge:
533 actions.append((f, "g", (fl2,), "remote created"))
516 actions['g'].append((f, (fl2,), "remote created"))
534 else:
517 else:
535 different = _checkunknownfile(repo, wctx, p2, f)
518 different = _checkunknownfile(repo, wctx, p2, f)
536 if force and branchmerge and different:
519 if force and branchmerge and different:
537 # FIXME: This is wrong - f is not in ma ...
520 # FIXME: This is wrong - f is not in ma ...
538 actions.append((f, "m", (f, f, f, False, pa.node()),
521 actions['m'].append((f, (f, f, f, False, pa.node()),
539 "remote differs from untracked local"))
522 "remote differs from untracked local"))
540 elif not force and different:
523 elif not force and different:
541 aborts.append((f, "ud"))
524 aborts.append((f, "ud"))
542 else:
525 else:
543 actions.append((f, "g", (fl2,), "remote created"))
526 actions['g'].append((f, (fl2,), "remote created"))
544 elif n2 and n2 != ma[f]:
527 elif n2 and n2 != ma[f]:
545 different = _checkunknownfile(repo, wctx, p2, f)
528 different = _checkunknownfile(repo, wctx, p2, f)
546 if not force and different:
529 if not force and different:
@@ -548,10 +531,10 b' def manifestmerge(repo, wctx, p2, pa, br'
548 else:
531 else:
549 # if different: old untracked f may be overwritten and lost
532 # if different: old untracked f may be overwritten and lost
550 if acceptremote:
533 if acceptremote:
551 actions.append((f, "g", (m2.flags(f),),
534 actions['g'].append((f, (m2.flags(f),),
552 "remote recreating"))
535 "remote recreating"))
553 else:
536 else:
554 actions.append((f, "dc", (m2.flags(f),),
537 actions['dc'].append((f, (m2.flags(f),),
555 "prompt deleted/changed"))
538 "prompt deleted/changed"))
556
539
557 for f, m in sorted(aborts):
540 for f, m in sorted(aborts):
@@ -566,18 +549,12 b' def manifestmerge(repo, wctx, p2, pa, br'
566 # check collision between files only in p2 for clean update
549 # check collision between files only in p2 for clean update
567 if (not branchmerge and
550 if (not branchmerge and
568 (force or not wctx.dirty(missing=True, branch=False))):
551 (force or not wctx.dirty(missing=True, branch=False))):
569 _checkcollision(repo, m2, [])
552 _checkcollision(repo, m2, None)
570 else:
553 else:
571 _checkcollision(repo, m1, actions)
554 _checkcollision(repo, m1, actions)
572
555
573 return actions
556 return actions
574
557
575 actionpriority = dict((m, p) for p, m in enumerate(
576 ['r', 'f', 'g', 'a', 'k', 'm', 'dm', 'dg', 'dr', 'cd', 'dc', 'rd', 'e']))
577
578 def actionkey(a):
579 return actionpriority[a[1]], a
580
581 def batchremove(repo, actions):
558 def batchremove(repo, actions):
582 """apply removes to the working directory
559 """apply removes to the working directory
583
560
@@ -588,7 +565,7 b' def batchremove(repo, actions):'
588 wjoin = repo.wjoin
565 wjoin = repo.wjoin
589 audit = repo.wopener.audit
566 audit = repo.wopener.audit
590 i = 0
567 i = 0
591 for f, m, args, msg in actions:
568 for f, args, msg in actions:
592 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
569 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
593 if True:
570 if True:
594 if verbose:
571 if verbose:
@@ -617,7 +594,7 b' def batchget(repo, mctx, actions):'
617 fctx = mctx.filectx
594 fctx = mctx.filectx
618 wwrite = repo.wwrite
595 wwrite = repo.wwrite
619 i = 0
596 i = 0
620 for f, m, args, msg in actions:
597 for f, args, msg in actions:
621 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
598 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
622 if True:
599 if True:
623 if verbose:
600 if verbose:
@@ -644,12 +621,12 b' def applyupdates(repo, actions, wctx, mc'
644 ms = mergestate(repo)
621 ms = mergestate(repo)
645 ms.reset(wctx.p1().node(), mctx.node())
622 ms.reset(wctx.p1().node(), mctx.node())
646 moves = []
623 moves = []
647 actions.sort(key=actionkey)
624 for m, l in actions.items():
625 l.sort()
648
626
649 # prescan for merges
627 # prescan for merges
650 for a in actions:
628 for f, args, msg in actions['m']:
651 f, m, args, msg = a
629 if True:
652 if m == "m": # merge
653 f1, f2, fa, move, anc = args
630 f1, f2, fa, move, anc = args
654 if f == '.hgsubstate': # merged internally
631 if f == '.hgsubstate': # merged internally
655 continue
632 continue
@@ -677,55 +654,50 b' def applyupdates(repo, actions, wctx, mc'
677 audit(f)
654 audit(f)
678 util.unlinkpath(repo.wjoin(f))
655 util.unlinkpath(repo.wjoin(f))
679
656
680 numupdates = len([a for a in actions if a[1] != 'k'])
657 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
681 workeractions = [a for a in actions if a[1] in 'gr']
682 updateactions = [a for a in workeractions if a[1] == 'g']
683 updated = len(updateactions)
684 removeactions = [a for a in workeractions if a[1] == 'r']
685 removed = len(removeactions)
686 actions = [a for a in actions if a[1] not in 'gr']
687
658
688 hgsub = [a[1] for a in workeractions if a[0] == '.hgsubstate']
659 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
689 if hgsub and hgsub[0] == 'r':
690 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
660 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
691
661
692 # remove in parallel (must come first)
662 # remove in parallel (must come first)
693 z = 0
663 z = 0
694 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), removeactions)
664 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
695 for i, item in prog:
665 for i, item in prog:
696 z += i
666 z += i
697 progress(_updating, z, item=item, total=numupdates, unit=_files)
667 progress(_updating, z, item=item, total=numupdates, unit=_files)
668 removed = len(actions['r'])
698
669
699 # get in parallel
670 # get in parallel
700 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), updateactions)
671 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
701 for i, item in prog:
672 for i, item in prog:
702 z += i
673 z += i
703 progress(_updating, z, item=item, total=numupdates, unit=_files)
674 progress(_updating, z, item=item, total=numupdates, unit=_files)
675 updated = len(actions['g'])
704
676
705 if hgsub and hgsub[0] == 'g':
677 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
706 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
678 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
707
679
708 for f, m, args, msg in actions:
680 if True:
709
681
710 # forget (manifest only, just log it) (must come first)
682 # forget (manifest only, just log it) (must come first)
711 if m == "f":
683 for f, args, msg in actions['f']:
712 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
684 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
713 z += 1
685 z += 1
714 progress(_updating, z, item=f, total=numupdates, unit=_files)
686 progress(_updating, z, item=f, total=numupdates, unit=_files)
715
687
716 # re-add (manifest only, just log it)
688 # re-add (manifest only, just log it)
717 elif m == "a":
689 for f, args, msg in actions['a']:
718 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
690 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
719 z += 1
691 z += 1
720 progress(_updating, z, item=f, total=numupdates, unit=_files)
692 progress(_updating, z, item=f, total=numupdates, unit=_files)
721
693
722 # keep (noop, just log it)
694 # keep (noop, just log it)
723 elif m == "k":
695 for f, args, msg in actions['k']:
724 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
696 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
725 # no progress
697 # no progress
726
698
727 # merge
699 # merge
728 elif m == "m":
700 for f, args, msg in actions['m']:
729 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
701 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
730 z += 1
702 z += 1
731 progress(_updating, z, item=f, total=numupdates, unit=_files)
703 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -745,7 +717,7 b' def applyupdates(repo, actions, wctx, mc'
745 merged += 1
717 merged += 1
746
718
747 # directory rename, move local
719 # directory rename, move local
748 elif m == "dm":
720 for f, args, msg in actions['dm']:
749 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
721 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
750 z += 1
722 z += 1
751 progress(_updating, z, item=f, total=numupdates, unit=_files)
723 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -757,7 +729,7 b' def applyupdates(repo, actions, wctx, mc'
757 updated += 1
729 updated += 1
758
730
759 # local directory rename, get
731 # local directory rename, get
760 elif m == "dg":
732 for f, args, msg in actions['dg']:
761 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
733 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
762 z += 1
734 z += 1
763 progress(_updating, z, item=f, total=numupdates, unit=_files)
735 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -767,7 +739,7 b' def applyupdates(repo, actions, wctx, mc'
767 updated += 1
739 updated += 1
768
740
769 # divergent renames
741 # divergent renames
770 elif m == "dr":
742 for f, args, msg in actions['dr']:
771 repo.ui.debug(" %s: %s -> dr\n" % (f, msg))
743 repo.ui.debug(" %s: %s -> dr\n" % (f, msg))
772 z += 1
744 z += 1
773 progress(_updating, z, item=f, total=numupdates, unit=_files)
745 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -778,7 +750,7 b' def applyupdates(repo, actions, wctx, mc'
778 repo.ui.warn(" %s\n" % nf)
750 repo.ui.warn(" %s\n" % nf)
779
751
780 # rename and delete
752 # rename and delete
781 elif m == "rd":
753 for f, args, msg in actions['rd']:
782 repo.ui.debug(" %s: %s -> rd\n" % (f, msg))
754 repo.ui.debug(" %s: %s -> rd\n" % (f, msg))
783 z += 1
755 z += 1
784 progress(_updating, z, item=f, total=numupdates, unit=_files)
756 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -789,7 +761,7 b' def applyupdates(repo, actions, wctx, mc'
789 repo.ui.warn(" %s\n" % nf)
761 repo.ui.warn(" %s\n" % nf)
790
762
791 # exec
763 # exec
792 elif m == "e":
764 for f, args, msg in actions['e']:
793 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
765 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
794 z += 1
766 z += 1
795 progress(_updating, z, item=f, total=numupdates, unit=_files)
767 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -818,132 +790,127 b' def calculateupdates(repo, wctx, mctx, a'
818 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
790 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
819
791
820 # Call for bids
792 # Call for bids
821 fbids = {} # mapping filename to list af action bids
793 fbids = {} # mapping filename to bids (action method to list af actions)
822 for ancestor in ancestors:
794 for ancestor in ancestors:
823 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
795 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
824 actions = manifestmerge(repo, wctx, mctx, ancestor,
796 actions = manifestmerge(repo, wctx, mctx, ancestor,
825 branchmerge, force,
797 branchmerge, force,
826 partial, acceptremote, followcopies)
798 partial, acceptremote, followcopies)
827 for a in sorted(actions, key=lambda a: (a[1], a)):
799 for m, l in sorted(actions.items()):
828 f, m, args, msg = a
800 for a in l:
829 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
801 f, args, msg = a
830 if f in fbids:
802 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
831 fbids[f].append(a)
803 if f in fbids:
832 else:
804 d = fbids[f]
833 fbids[f] = [a]
805 if m in d:
806 d[m].append(a)
807 else:
808 d[m] = [a]
809 else:
810 fbids[f] = {m: [a]}
834
811
835 # Pick the best bid for each file
812 # Pick the best bid for each file
836 repo.ui.note(_('\nauction for merging merge bids\n'))
813 repo.ui.note(_('\nauction for merging merge bids\n'))
837 actions = []
814 actions = dict((m, []) for m in actions.keys())
838 for f, bidsl in sorted(fbids.items()):
815 for f, bids in sorted(fbids.items()):
816 # bids is a mapping from action method to list af actions
839 # Consensus?
817 # Consensus?
840 a0 = bidsl[0]
818 if len(bids) == 1: # all bids are the same kind of method
841 if util.all(a == a0 for a in bidsl[1:]): # len(bidsl) is > 1
819 m, l = bids.items()[0]
842 repo.ui.note(" %s: consensus for %s\n" % (f, a0[1]))
820 if util.all(a == l[0] for a in l[1:]): # len(bids) is > 1
843 actions.append(a0)
821 repo.ui.note(" %s: consensus for %s\n" % (f, m))
844 continue
822 actions[m].append(l[0])
845 # Group bids by kind of action
823 continue
846 bids = {}
847 for a in bidsl:
848 m = a[1]
849 if m in bids:
850 bids[m].append(a)
851 else:
852 bids[m] = [a]
853 # If keep is an option, just do it.
824 # If keep is an option, just do it.
854 if "k" in bids:
825 if "k" in bids:
855 repo.ui.note(" %s: picking 'keep' action\n" % f)
826 repo.ui.note(" %s: picking 'keep' action\n" % f)
856 actions.append(bids["k"][0])
827 actions['k'].append(bids["k"][0])
857 continue
828 continue
858 # If all gets agree [how could they not?], just do it.
829 # If there are gets and they all agree [how could they not?], do it.
859 if "g" in bids:
830 if "g" in bids:
860 ga0 = bids["g"][0]
831 ga0 = bids["g"][0]
861 if util.all(a == ga0 for a in bids["g"][1:]):
832 if util.all(a == ga0 for a in bids["g"][1:]):
862 repo.ui.note(" %s: picking 'get' action\n" % f)
833 repo.ui.note(" %s: picking 'get' action\n" % f)
863 actions.append(ga0)
834 actions['g'].append(ga0)
864 continue
835 continue
865 # TODO: Consider other simple actions such as mode changes
836 # TODO: Consider other simple actions such as mode changes
866 # Handle inefficient democrazy.
837 # Handle inefficient democrazy.
867 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
838 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
868 for _f, m, args, msg in bidsl:
839 for m, l in sorted(bids.items()):
869 repo.ui.note(' %s -> %s\n' % (msg, m))
840 for _f, args, msg in l:
841 repo.ui.note(' %s -> %s\n' % (msg, m))
870 # Pick random action. TODO: Instead, prompt user when resolving
842 # Pick random action. TODO: Instead, prompt user when resolving
871 a0 = bidsl[0]
843 m, l = bids.items()[0]
872 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
844 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
873 (f, a0[1]))
845 (f, m))
874 actions.append(a0)
846 actions[m].append(l[0])
875 continue
847 continue
876 repo.ui.note(_('end of auction\n\n'))
848 repo.ui.note(_('end of auction\n\n'))
877
849
878 # Filter out prompts.
879 newactions, prompts = [], []
880 for a in actions:
881 if a[1] in ("cd", "dc"):
882 prompts.append(a)
883 else:
884 newactions.append(a)
885 # Prompt and create actions. TODO: Move this towards resolve phase.
850 # Prompt and create actions. TODO: Move this towards resolve phase.
886 for f, m, args, msg in sorted(prompts):
851 if True:
887 if m == "cd":
852 for f, args, msg in actions['cd']:
888 if repo.ui.promptchoice(
853 if repo.ui.promptchoice(
889 _("local changed %s which remote deleted\n"
854 _("local changed %s which remote deleted\n"
890 "use (c)hanged version or (d)elete?"
855 "use (c)hanged version or (d)elete?"
891 "$$ &Changed $$ &Delete") % f, 0):
856 "$$ &Changed $$ &Delete") % f, 0):
892 newactions.append((f, "r", None, "prompt delete"))
857 actions['r'].append((f, None, "prompt delete"))
893 else:
858 else:
894 newactions.append((f, "a", None, "prompt keep"))
859 actions['a'].append((f, None, "prompt keep"))
895 elif m == "dc":
860 del actions['cd'][:]
861
862 for f, args, msg in actions['dc']:
896 flags, = args
863 flags, = args
897 if repo.ui.promptchoice(
864 if repo.ui.promptchoice(
898 _("remote changed %s which local deleted\n"
865 _("remote changed %s which local deleted\n"
899 "use (c)hanged version or leave (d)eleted?"
866 "use (c)hanged version or leave (d)eleted?"
900 "$$ &Changed $$ &Deleted") % f, 0) == 0:
867 "$$ &Changed $$ &Deleted") % f, 0) == 0:
901 newactions.append((f, "g", (flags,), "prompt recreating"))
868 actions['g'].append((f, (flags,), "prompt recreating"))
902 else: assert False, m
869 del actions['dc'][:]
903
870
904 if wctx.rev() is None:
871 if wctx.rev() is None:
905 newactions += _forgetremoved(wctx, mctx, branchmerge)
872 ractions, factions = _forgetremoved(wctx, mctx, branchmerge)
873 actions['r'].extend(ractions)
874 actions['f'].extend(factions)
906
875
907 return newactions
876 return actions
908
877
909 def recordupdates(repo, actions, branchmerge):
878 def recordupdates(repo, actions, branchmerge):
910 "record merge actions to the dirstate"
879 "record merge actions to the dirstate"
911
880 if True:
912 for f, m, args, msg in actions:
913
914 # remove (must come first)
881 # remove (must come first)
915 if m == "r": # remove
882 for f, args, msg in actions['r']:
916 if branchmerge:
883 if branchmerge:
917 repo.dirstate.remove(f)
884 repo.dirstate.remove(f)
918 else:
885 else:
919 repo.dirstate.drop(f)
886 repo.dirstate.drop(f)
920
887
921 # forget (must come first)
888 # forget (must come first)
922 elif m == "f":
889 for f, args, msg in actions['f']:
923 repo.dirstate.drop(f)
890 repo.dirstate.drop(f)
924
891
925 # re-add
892 # re-add
926 elif m == "a":
893 for f, args, msg in actions['a']:
927 if not branchmerge:
894 if not branchmerge:
928 repo.dirstate.add(f)
895 repo.dirstate.add(f)
929
896
930 # exec change
897 # exec change
931 elif m == "e":
898 for f, args, msg in actions['e']:
932 repo.dirstate.normallookup(f)
899 repo.dirstate.normallookup(f)
933
900
934 # keep
901 # keep
935 elif m == "k":
902 for f, args, msg in actions['k']:
936 pass
903 pass
937
904
938 # get
905 # get
939 elif m == "g":
906 for f, args, msg in actions['g']:
940 if branchmerge:
907 if branchmerge:
941 repo.dirstate.otherparent(f)
908 repo.dirstate.otherparent(f)
942 else:
909 else:
943 repo.dirstate.normal(f)
910 repo.dirstate.normal(f)
944
911
945 # merge
912 # merge
946 elif m == "m":
913 for f, args, msg in actions['m']:
947 f1, f2, fa, move, anc = args
914 f1, f2, fa, move, anc = args
948 if branchmerge:
915 if branchmerge:
949 # We've done a branch merge, mark this file as merged
916 # We've done a branch merge, mark this file as merged
@@ -968,7 +935,7 b' def recordupdates(repo, actions, branchm'
968 repo.dirstate.drop(f1)
935 repo.dirstate.drop(f1)
969
936
970 # directory rename, move local
937 # directory rename, move local
971 elif m == "dm":
938 for f, args, msg in actions['dm']:
972 f0, flag = args
939 f0, flag = args
973 if f0 not in repo.dirstate:
940 if f0 not in repo.dirstate:
974 # untracked file moved
941 # untracked file moved
@@ -982,7 +949,7 b' def recordupdates(repo, actions, branchm'
982 repo.dirstate.drop(f0)
949 repo.dirstate.drop(f0)
983
950
984 # directory rename, get
951 # directory rename, get
985 elif m == "dg":
952 for f, args, msg in actions['dg']:
986 f0, flag = args
953 f0, flag = args
987 if branchmerge:
954 if branchmerge:
988 repo.dirstate.add(f)
955 repo.dirstate.add(f)
General Comments 0
You need to be logged in to leave comments. Login now