466 elif nol and n2 == a: # remote only changed 'x' |
466 elif nol and n2 == a: # remote only changed 'x' |
467 actions.append((f, "e", (fl2,), "update permissions")) |
467 actions.append((f, "e", (fl2,), "update permissions")) |
468 elif nol and n1 == a: # local only changed 'x' |
468 elif nol and n1 == a: # local only changed 'x' |
469 actions.append((f, "g", (fl1,), "remote is newer")) |
469 actions.append((f, "g", (fl1,), "remote is newer")) |
470 else: # both changed something |
470 else: # both changed something |
471 actions.append((f, "m", (f, fa, f, False), "versions differ")) |
471 actions.append((f, "m", (f, fa, f, False, pa.node()), |
|
472 "versions differ")) |
472 elif f in copied: # files we'll deal with on m2 side |
473 elif f in copied: # files we'll deal with on m2 side |
473 pass |
474 pass |
474 elif n1 and f in movewithdir: # directory rename |
475 elif n1 and f in movewithdir: # directory rename |
475 f2 = movewithdir[f] |
476 f2 = movewithdir[f] |
476 actions.append((f, "d", (None, f2, fl1), |
477 actions.append((f, "d", (None, f2, fl1), |
477 "remote renamed directory to " + f2)) |
478 "remote renamed directory to " + f2)) |
478 elif n1 and f in copy: |
479 elif n1 and f in copy: |
479 f2 = copy[f] |
480 f2 = copy[f] |
480 actions.append((f, "m", (f2, f2, f, False), |
481 actions.append((f, "m", (f2, f2, f, False, pa.node()), |
481 "local copied/moved to " + f2)) |
482 "local copied/moved to " + f2)) |
482 elif n1 and f in ma: # clean, a different, no remote |
483 elif n1 and f in ma: # clean, a different, no remote |
483 if n1 != ma[f]: |
484 if n1 != ma[f]: |
484 if acceptremote: |
485 if acceptremote: |
485 actions.append((f, "r", None, "remote delete")) |
486 actions.append((f, "r", None, "remote delete")) |
494 actions.append((None, "d", (f, f2, fl2), |
495 actions.append((None, "d", (f, f2, fl2), |
495 "local renamed directory to " + f2)) |
496 "local renamed directory to " + f2)) |
496 elif n2 and f in copy: |
497 elif n2 and f in copy: |
497 f2 = copy[f] |
498 f2 = copy[f] |
498 if f2 in m2: |
499 if f2 in m2: |
499 actions.append((f2, "m", (f, f2, f, False), |
500 actions.append((f2, "m", (f, f2, f, False, pa.node()), |
500 "remote copied to " + f)) |
501 "remote copied to " + f)) |
501 else: |
502 else: |
502 actions.append((f2, "m", (f, f2, f, True), |
503 actions.append((f2, "m", (f, f2, f, True, pa.node()), |
503 "remote moved to " + f)) |
504 "remote moved to " + f)) |
504 elif n2 and f not in ma: |
505 elif n2 and f not in ma: |
505 # local unknown, remote created: the logic is described by the |
506 # local unknown, remote created: the logic is described by the |
506 # following table: |
507 # following table: |
507 # |
508 # |
518 actions.append((f, "g", (fl2,), "remote created")) |
519 actions.append((f, "g", (fl2,), "remote created")) |
519 else: |
520 else: |
520 different = _checkunknownfile(repo, wctx, p2, f) |
521 different = _checkunknownfile(repo, wctx, p2, f) |
521 if force and branchmerge and different: |
522 if force and branchmerge and different: |
522 # FIXME: This is wrong - f is not in ma ... |
523 # FIXME: This is wrong - f is not in ma ... |
523 actions.append((f, "m", (f, f, f, False), |
524 actions.append((f, "m", (f, f, f, False, pa.node()), |
524 "remote differs from untracked local")) |
525 "remote differs from untracked local")) |
525 elif not force and different: |
526 elif not force and different: |
526 aborts.append((f, "ud")) |
527 aborts.append((f, "ud")) |
527 else: |
528 else: |
528 actions.append((f, "g", (fl2,), "remote created")) |
529 actions.append((f, "g", (fl2,), "remote created")) |
594 i = 0 |
595 i = 0 |
595 i += 1 |
596 i += 1 |
596 if i > 0: |
597 if i > 0: |
597 yield i, f |
598 yield i, f |
598 |
599 |
599 def applyupdates(repo, actions, wctx, mctx, actx, overwrite): |
600 def applyupdates(repo, actions, wctx, mctx, overwrite): |
600 """apply the merge action list to the working directory |
601 """apply the merge action list to the working directory |
601 |
602 |
602 wctx is the working copy context |
603 wctx is the working copy context |
603 mctx is the context to be merged into the working copy |
604 mctx is the context to be merged into the working copy |
604 actx is the context of the common ancestor |
|
605 |
605 |
606 Return a tuple of counts (updated, merged, removed, unresolved) that |
606 Return a tuple of counts (updated, merged, removed, unresolved) that |
607 describes how many files were affected by the update. |
607 describes how many files were affected by the update. |
608 """ |
608 """ |
609 |
609 |
616 # prescan for merges |
616 # prescan for merges |
617 for a in actions: |
617 for a in actions: |
618 f, m, args, msg = a |
618 f, m, args, msg = a |
619 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) |
619 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) |
620 if m == "m": # merge |
620 if m == "m": # merge |
621 f2, fa, fd, move = args |
621 f2, fa, fd, move, anc = args |
622 if fd == '.hgsubstate': # merged internally |
622 if fd == '.hgsubstate': # merged internally |
623 continue |
623 continue |
624 repo.ui.debug(" preserving %s for resolve of %s\n" % (f, fd)) |
624 repo.ui.debug(" preserving %s for resolve of %s\n" % (f, fd)) |
625 fcl = wctx[f] |
625 fcl = wctx[f] |
626 fco = mctx[f2] |
626 fco = mctx[f2] |
627 if mctx == actx: # backwards, use working dir parent as ancestor |
627 actx = repo[anc] |
628 if fcl.parents(): |
628 if fa in actx: |
629 fca = fcl.p1() |
|
630 else: |
|
631 fca = repo.filectx(f, fileid=nullrev) |
|
632 elif fa in actx: |
|
633 fca = actx[fa] |
629 fca = actx[fa] |
634 else: |
630 else: |
635 fca = repo.filectx(f, fileid=nullrev) |
631 fca = repo.filectx(f, fileid=nullrev) |
636 ms.add(fcl, fco, fca, fd) |
632 ms.add(fcl, fco, fca, fd) |
637 if f != fd and move: |
633 if f != fd and move: |
681 |
677 |
682 for i, a in enumerate(actions): |
678 for i, a in enumerate(actions): |
683 f, m, args, msg = a |
679 f, m, args, msg = a |
684 progress(_updating, z + i + 1, item=f, total=numupdates, unit=_files) |
680 progress(_updating, z + i + 1, item=f, total=numupdates, unit=_files) |
685 if m == "m": # merge |
681 if m == "m": # merge |
686 f2, fa, fd, move = args |
682 f2, fa, fd, move, anc = args |
687 if fd == '.hgsubstate': # subrepo states need updating |
683 if fd == '.hgsubstate': # subrepo states need updating |
688 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), |
684 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), |
689 overwrite) |
685 overwrite) |
690 continue |
686 continue |
691 audit(fd) |
687 audit(fd) |
791 if branchmerge: |
787 if branchmerge: |
792 repo.dirstate.otherparent(f) |
788 repo.dirstate.otherparent(f) |
793 else: |
789 else: |
794 repo.dirstate.normal(f) |
790 repo.dirstate.normal(f) |
795 elif m == "m": # merge |
791 elif m == "m": # merge |
796 f2, fa, fd, move = args |
792 f2, fa, fd, move, anc = args |
797 if branchmerge: |
793 if branchmerge: |
798 # We've done a branch merge, mark this file as merged |
794 # We've done a branch merge, mark this file as merged |
799 # so that we properly record the merger later |
795 # so that we properly record the merger later |
800 repo.dirstate.merge(fd) |
796 repo.dirstate.merge(fd) |
801 if f != f2: # copy/rename |
797 if f != f2: # copy/rename |
997 if not partial: |
993 if not partial: |
998 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2) |
994 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2) |
999 # note that we're in the middle of an update |
995 # note that we're in the middle of an update |
1000 repo.vfs.write('updatestate', p2.hex()) |
996 repo.vfs.write('updatestate', p2.hex()) |
1001 |
997 |
1002 stats = applyupdates(repo, actions, wc, p2, pa, overwrite) |
998 stats = applyupdates(repo, actions, wc, p2, overwrite) |
1003 |
999 |
1004 if not partial: |
1000 if not partial: |
1005 repo.setparents(fp1, fp2) |
1001 repo.setparents(fp1, fp2) |
1006 recordupdates(repo, actions, branchmerge) |
1002 recordupdates(repo, actions, branchmerge) |
1007 # update completed, clear state |
1003 # update completed, clear state |