mercurial/merge.py
changeset 23385 91c24457c16a
parent 23384 0791a10ad87c
child 23386 8229f32d2b79
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: