comparison mercurial/merge.py @ 23385:91c24457c16a

merge: move calculateupdates() before applyupdated() calculateupdates() happens before applyupdates(), so move it before in the code. That also moves it close to manifestmerge(), which is a good location as calculateupdates() is the only caller of manifestmerge().
author Martin von Zweigbergk <martinvonz@google.com>
date Fri, 21 Nov 2014 13:06:04 -0800
parents 0791a10ad87c
children 8229f32d2b79
comparison
equal deleted inserted replaced
23384:0791a10ad87c 23385:91c24457c16a
520 else: 520 else:
521 _checkcollision(repo, m1, actions) 521 _checkcollision(repo, m1, actions)
522 522
523 return actions 523 return actions
524 524
525 def batchremove(repo, actions):
526 """apply removes to the working directory
527
528 yields tuples for progress updates
529 """
530 verbose = repo.ui.verbose
531 unlink = util.unlinkpath
532 wjoin = repo.wjoin
533 audit = repo.wopener.audit
534 i = 0
535 for f, args, msg in actions:
536 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
537 if verbose:
538 repo.ui.note(_("removing %s\n") % f)
539 audit(f)
540 try:
541 unlink(wjoin(f), ignoremissing=True)
542 except OSError, inst:
543 repo.ui.warn(_("update failed to remove %s: %s!\n") %
544 (f, inst.strerror))
545 if i == 100:
546 yield i, f
547 i = 0
548 i += 1
549 if i > 0:
550 yield i, f
551
552 def batchget(repo, mctx, actions):
553 """apply gets to the working directory
554
555 mctx is the context to get from
556
557 yields tuples for progress updates
558 """
559 verbose = repo.ui.verbose
560 fctx = mctx.filectx
561 wwrite = repo.wwrite
562 i = 0
563 for f, args, msg in actions:
564 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
565 if verbose:
566 repo.ui.note(_("getting %s\n") % f)
567 wwrite(f, fctx(f).data(), args[0])
568 if i == 100:
569 yield i, f
570 i = 0
571 i += 1
572 if i > 0:
573 yield i, f
574
575 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
576 """apply the merge action list to the working directory
577
578 wctx is the working copy context
579 mctx is the context to be merged into the working copy
580
581 Return a tuple of counts (updated, merged, removed, unresolved) that
582 describes how many files were affected by the update.
583 """
584
585 updated, merged, removed, unresolved = 0, 0, 0, 0
586 ms = mergestate(repo)
587 ms.reset(wctx.p1().node(), mctx.node())
588 moves = []
589 for m, l in actions.items():
590 l.sort()
591
592 # prescan for merges
593 for f, args, msg in actions['m']:
594 f1, f2, fa, move, anc = args
595 if f == '.hgsubstate': # merged internally
596 continue
597 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
598 fcl = wctx[f1]
599 fco = mctx[f2]
600 actx = repo[anc]
601 if fa in actx:
602 fca = actx[fa]
603 else:
604 fca = repo.filectx(f1, fileid=nullrev)
605 ms.add(fcl, fco, fca, f)
606 if f1 != f and move:
607 moves.append(f1)
608
609 audit = repo.wopener.audit
610 _updating = _('updating')
611 _files = _('files')
612 progress = repo.ui.progress
613
614 # remove renamed files after safely stored
615 for f in moves:
616 if os.path.lexists(repo.wjoin(f)):
617 repo.ui.debug("removing %s\n" % f)
618 audit(f)
619 util.unlinkpath(repo.wjoin(f))
620
621 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
622
623 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
624 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
625
626 # remove in parallel (must come first)
627 z = 0
628 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
629 for i, item in prog:
630 z += i
631 progress(_updating, z, item=item, total=numupdates, unit=_files)
632 removed = len(actions['r'])
633
634 # get in parallel
635 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
636 for i, item in prog:
637 z += i
638 progress(_updating, z, item=item, total=numupdates, unit=_files)
639 updated = len(actions['g'])
640
641 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
642 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
643
644 # forget (manifest only, just log it) (must come first)
645 for f, args, msg in actions['f']:
646 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
647 z += 1
648 progress(_updating, z, item=f, total=numupdates, unit=_files)
649
650 # re-add (manifest only, just log it)
651 for f, args, msg in actions['a']:
652 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
653 z += 1
654 progress(_updating, z, item=f, total=numupdates, unit=_files)
655
656 # keep (noop, just log it)
657 for f, args, msg in actions['k']:
658 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
659 # no progress
660
661 # merge
662 for f, args, msg in actions['m']:
663 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
664 z += 1
665 progress(_updating, z, item=f, total=numupdates, unit=_files)
666 f1, f2, fa, move, anc = args
667 if f == '.hgsubstate': # subrepo states need updating
668 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
669 overwrite)
670 continue
671 audit(f)
672 r = ms.resolve(f, wctx, labels=labels)
673 if r is not None and r > 0:
674 unresolved += 1
675 else:
676 if r is None:
677 updated += 1
678 else:
679 merged += 1
680
681 # directory rename, move local
682 for f, args, msg in actions['dm']:
683 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
684 z += 1
685 progress(_updating, z, item=f, total=numupdates, unit=_files)
686 f0, flags = args
687 repo.ui.note(_("moving %s to %s\n") % (f0, f))
688 audit(f)
689 repo.wwrite(f, wctx.filectx(f0).data(), flags)
690 util.unlinkpath(repo.wjoin(f0))
691 updated += 1
692
693 # local directory rename, get
694 for f, args, msg in actions['dg']:
695 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
696 z += 1
697 progress(_updating, z, item=f, total=numupdates, unit=_files)
698 f0, flags = args
699 repo.ui.note(_("getting %s to %s\n") % (f0, f))
700 repo.wwrite(f, mctx.filectx(f0).data(), flags)
701 updated += 1
702
703 # divergent renames
704 for f, args, msg in actions['dr']:
705 repo.ui.debug(" %s: %s -> dr\n" % (f, msg))
706 z += 1
707 progress(_updating, z, item=f, total=numupdates, unit=_files)
708 fl, = args
709 repo.ui.warn(_("note: possible conflict - %s was renamed "
710 "multiple times to:\n") % f)
711 for nf in fl:
712 repo.ui.warn(" %s\n" % nf)
713
714 # rename and delete
715 for f, args, msg in actions['rd']:
716 repo.ui.debug(" %s: %s -> rd\n" % (f, msg))
717 z += 1
718 progress(_updating, z, item=f, total=numupdates, unit=_files)
719 fl, = args
720 repo.ui.warn(_("note: possible conflict - %s was deleted "
721 "and renamed to:\n") % f)
722 for nf in fl:
723 repo.ui.warn(" %s\n" % nf)
724
725 # exec
726 for f, args, msg in actions['e']:
727 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
728 z += 1
729 progress(_updating, z, item=f, total=numupdates, unit=_files)
730 flags, = args
731 audit(f)
732 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
733 updated += 1
734
735 ms.commit()
736 progress(_updating, None, total=numupdates, unit=_files)
737
738 return updated, merged, removed, unresolved
739
740 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial, 525 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
741 acceptremote, followcopies): 526 acceptremote, followcopies):
742 "Calculate the actions needed to merge mctx into wctx using ancestors" 527 "Calculate the actions needed to merge mctx into wctx using ancestors"
743 528
744 if len(ancestors) == 1: # default 529 if len(ancestors) == 1: # default
834 actions['r'].extend(ractions) 619 actions['r'].extend(ractions)
835 actions['f'].extend(factions) 620 actions['f'].extend(factions)
836 621
837 return actions 622 return actions
838 623
624 def batchremove(repo, actions):
625 """apply removes to the working directory
626
627 yields tuples for progress updates
628 """
629 verbose = repo.ui.verbose
630 unlink = util.unlinkpath
631 wjoin = repo.wjoin
632 audit = repo.wopener.audit
633 i = 0
634 for f, args, msg in actions:
635 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
636 if verbose:
637 repo.ui.note(_("removing %s\n") % f)
638 audit(f)
639 try:
640 unlink(wjoin(f), ignoremissing=True)
641 except OSError, inst:
642 repo.ui.warn(_("update failed to remove %s: %s!\n") %
643 (f, inst.strerror))
644 if i == 100:
645 yield i, f
646 i = 0
647 i += 1
648 if i > 0:
649 yield i, f
650
651 def batchget(repo, mctx, actions):
652 """apply gets to the working directory
653
654 mctx is the context to get from
655
656 yields tuples for progress updates
657 """
658 verbose = repo.ui.verbose
659 fctx = mctx.filectx
660 wwrite = repo.wwrite
661 i = 0
662 for f, args, msg in actions:
663 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
664 if verbose:
665 repo.ui.note(_("getting %s\n") % f)
666 wwrite(f, fctx(f).data(), args[0])
667 if i == 100:
668 yield i, f
669 i = 0
670 i += 1
671 if i > 0:
672 yield i, f
673
674 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
675 """apply the merge action list to the working directory
676
677 wctx is the working copy context
678 mctx is the context to be merged into the working copy
679
680 Return a tuple of counts (updated, merged, removed, unresolved) that
681 describes how many files were affected by the update.
682 """
683
684 updated, merged, removed, unresolved = 0, 0, 0, 0
685 ms = mergestate(repo)
686 ms.reset(wctx.p1().node(), mctx.node())
687 moves = []
688 for m, l in actions.items():
689 l.sort()
690
691 # prescan for merges
692 for f, args, msg in actions['m']:
693 f1, f2, fa, move, anc = args
694 if f == '.hgsubstate': # merged internally
695 continue
696 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
697 fcl = wctx[f1]
698 fco = mctx[f2]
699 actx = repo[anc]
700 if fa in actx:
701 fca = actx[fa]
702 else:
703 fca = repo.filectx(f1, fileid=nullrev)
704 ms.add(fcl, fco, fca, f)
705 if f1 != f and move:
706 moves.append(f1)
707
708 audit = repo.wopener.audit
709 _updating = _('updating')
710 _files = _('files')
711 progress = repo.ui.progress
712
713 # remove renamed files after safely stored
714 for f in moves:
715 if os.path.lexists(repo.wjoin(f)):
716 repo.ui.debug("removing %s\n" % f)
717 audit(f)
718 util.unlinkpath(repo.wjoin(f))
719
720 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
721
722 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
723 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
724
725 # remove in parallel (must come first)
726 z = 0
727 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
728 for i, item in prog:
729 z += i
730 progress(_updating, z, item=item, total=numupdates, unit=_files)
731 removed = len(actions['r'])
732
733 # get in parallel
734 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
735 for i, item in prog:
736 z += i
737 progress(_updating, z, item=item, total=numupdates, unit=_files)
738 updated = len(actions['g'])
739
740 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
741 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
742
743 # forget (manifest only, just log it) (must come first)
744 for f, args, msg in actions['f']:
745 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
746 z += 1
747 progress(_updating, z, item=f, total=numupdates, unit=_files)
748
749 # re-add (manifest only, just log it)
750 for f, args, msg in actions['a']:
751 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
752 z += 1
753 progress(_updating, z, item=f, total=numupdates, unit=_files)
754
755 # keep (noop, just log it)
756 for f, args, msg in actions['k']:
757 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
758 # no progress
759
760 # merge
761 for f, args, msg in actions['m']:
762 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
763 z += 1
764 progress(_updating, z, item=f, total=numupdates, unit=_files)
765 f1, f2, fa, move, anc = args
766 if f == '.hgsubstate': # subrepo states need updating
767 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
768 overwrite)
769 continue
770 audit(f)
771 r = ms.resolve(f, wctx, labels=labels)
772 if r is not None and r > 0:
773 unresolved += 1
774 else:
775 if r is None:
776 updated += 1
777 else:
778 merged += 1
779
780 # directory rename, move local
781 for f, args, msg in actions['dm']:
782 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
783 z += 1
784 progress(_updating, z, item=f, total=numupdates, unit=_files)
785 f0, flags = args
786 repo.ui.note(_("moving %s to %s\n") % (f0, f))
787 audit(f)
788 repo.wwrite(f, wctx.filectx(f0).data(), flags)
789 util.unlinkpath(repo.wjoin(f0))
790 updated += 1
791
792 # local directory rename, get
793 for f, args, msg in actions['dg']:
794 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
795 z += 1
796 progress(_updating, z, item=f, total=numupdates, unit=_files)
797 f0, flags = args
798 repo.ui.note(_("getting %s to %s\n") % (f0, f))
799 repo.wwrite(f, mctx.filectx(f0).data(), flags)
800 updated += 1
801
802 # divergent renames
803 for f, args, msg in actions['dr']:
804 repo.ui.debug(" %s: %s -> dr\n" % (f, msg))
805 z += 1
806 progress(_updating, z, item=f, total=numupdates, unit=_files)
807 fl, = args
808 repo.ui.warn(_("note: possible conflict - %s was renamed "
809 "multiple times to:\n") % f)
810 for nf in fl:
811 repo.ui.warn(" %s\n" % nf)
812
813 # rename and delete
814 for f, args, msg in actions['rd']:
815 repo.ui.debug(" %s: %s -> rd\n" % (f, msg))
816 z += 1
817 progress(_updating, z, item=f, total=numupdates, unit=_files)
818 fl, = args
819 repo.ui.warn(_("note: possible conflict - %s was deleted "
820 "and renamed to:\n") % f)
821 for nf in fl:
822 repo.ui.warn(" %s\n" % nf)
823
824 # exec
825 for f, args, msg in actions['e']:
826 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
827 z += 1
828 progress(_updating, z, item=f, total=numupdates, unit=_files)
829 flags, = args
830 audit(f)
831 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
832 updated += 1
833
834 ms.commit()
835 progress(_updating, None, total=numupdates, unit=_files)
836
837 return updated, merged, removed, unresolved
838
839 def recordupdates(repo, actions, branchmerge): 839 def recordupdates(repo, actions, branchmerge):
840 "record merge actions to the dirstate" 840 "record merge actions to the dirstate"
841 # remove (must come first) 841 # remove (must come first)
842 for f, args, msg in actions['r']: 842 for f, args, msg in actions['r']:
843 if branchmerge: 843 if branchmerge: