mercurial/merge.py
changeset 5124 06154aff2b1a
parent 5060 2ef14e29e538
child 5141 d316124ebbea
equal deleted inserted replaced
5123:f94dbc6c7eaf 5124:06154aff2b1a
   453 
   453 
   454     for a in action:
   454     for a in action:
   455         f, m = a[:2]
   455         f, m = a[:2]
   456         if m == "r": # remove
   456         if m == "r": # remove
   457             if branchmerge:
   457             if branchmerge:
   458                 repo.dirstate.update([f], 'r')
   458                 repo.dirstate.remove(f)
   459             else:
   459             else:
   460                 repo.dirstate.forget([f])
   460                 repo.dirstate.forget(f)
   461         elif m == "f": # forget
   461         elif m == "f": # forget
   462             repo.dirstate.forget([f])
   462             repo.dirstate.forget(f)
   463         elif m in "ge": # get or exec change
   463         elif m in "ge": # get or exec change
   464             if branchmerge:
   464             if branchmerge:
   465                 repo.dirstate.update([f], 'n', st_mtime=-1)
   465                 repo.dirstate.normaldirty(f)
   466             else:
   466             else:
   467                 repo.dirstate.update([f], 'n')
   467                 repo.dirstate.normal(f)
   468         elif m == "m": # merge
   468         elif m == "m": # merge
   469             f2, fd, flag, move = a[2:]
   469             f2, fd, flag, move = a[2:]
   470             if branchmerge:
   470             if branchmerge:
   471                 # We've done a branch merge, mark this file as merged
   471                 # We've done a branch merge, mark this file as merged
   472                 # so that we properly record the merger later
   472                 # so that we properly record the merger later
   473                 repo.dirstate.update([fd], 'm')
   473                 repo.dirstate.merge(fd)
   474                 if f != f2: # copy/rename
   474                 if f != f2: # copy/rename
   475                     if move:
   475                     if move:
   476                         repo.dirstate.update([f], 'r')
   476                         repo.dirstate.remove(f)
   477                     if f != fd:
   477                     if f != fd:
   478                         repo.dirstate.copy(f, fd)
   478                         repo.dirstate.copy(f, fd)
   479                     else:
   479                     else:
   480                         repo.dirstate.copy(f2, fd)
   480                         repo.dirstate.copy(f2, fd)
   481             else:
   481             else:
   482                 # We've update-merged a locally modified file, so
   482                 # We've update-merged a locally modified file, so
   483                 # we set the dirstate to emulate a normal checkout
   483                 # we set the dirstate to emulate a normal checkout
   484                 # of that file some time in the past. Thus our
   484                 # of that file some time in the past. Thus our
   485                 # merge will appear as a normal local file
   485                 # merge will appear as a normal local file
   486                 # modification.
   486                 # modification.
   487                 repo.dirstate.update([fd], 'n', st_size=-1, st_mtime=-1)
   487                 repo.dirstate.normaldirty(fd)
   488                 if move:
   488                 if move:
   489                     repo.dirstate.forget([f])
   489                     repo.dirstate.forget(f)
   490         elif m == "d": # directory rename
   490         elif m == "d": # directory rename
   491             f2, fd, flag = a[2:]
   491             f2, fd, flag = a[2:]
   492             if not f2 and f not in repo.dirstate:
   492             if not f2 and f not in repo.dirstate:
   493                 # untracked file moved
   493                 # untracked file moved
   494                 continue
   494                 continue
   495             if branchmerge:
   495             if branchmerge:
   496                 repo.dirstate.update([fd], 'a')
   496                 repo.dirstate.add(fd)
   497                 if f:
   497                 if f:
   498                     repo.dirstate.update([f], 'r')
   498                     repo.dirstate.remove(f)
   499                     repo.dirstate.copy(f, fd)
   499                     repo.dirstate.copy(f, fd)
   500                 if f2:
   500                 if f2:
   501                     repo.dirstate.copy(f2, fd)
   501                     repo.dirstate.copy(f2, fd)
   502             else:
   502             else:
   503                 repo.dirstate.update([fd], 'n')
   503                 repo.dirstate.normal(fd)
   504                 if f:
   504                 if f:
   505                     repo.dirstate.forget([f])
   505                     repo.dirstate.forget(f)
   506 
   506 
   507 def update(repo, node, branchmerge, force, partial, wlock):
   507 def update(repo, node, branchmerge, force, partial):
   508     """
   508     """
   509     Perform a merge between the working directory and the given node
   509     Perform a merge between the working directory and the given node
   510 
   510 
   511     branchmerge = whether to merge between branches
   511     branchmerge = whether to merge between branches
   512     force = whether to force branch merging or file overwriting
   512     force = whether to force branch merging or file overwriting
   513     partial = a function to filter file lists (dirstate not updated)
   513     partial = a function to filter file lists (dirstate not updated)
   514     wlock = working dir lock, if already held
   514     """
   515     """
   515 
   516 
   516     wlock = repo.wlock()
   517     if not wlock:
   517     try:
   518         wlock = repo.wlock()
   518         wc = repo.workingctx()
   519 
   519         if node is None:
   520     wc = repo.workingctx()
   520             # tip of current branch
   521     if node is None:
   521             try:
   522         # tip of current branch
   522                 node = repo.branchtags()[wc.branch()]
   523         try:
   523             except KeyError:
   524             node = repo.branchtags()[wc.branch()]
   524                 raise util.Abort(_("branch %s not found") % wc.branch())
   525         except KeyError:
   525         overwrite = force and not branchmerge
   526             raise util.Abort(_("branch %s not found") % wc.branch())
   526         forcemerge = force and branchmerge
   527     overwrite = force and not branchmerge
   527         pl = wc.parents()
   528     forcemerge = force and branchmerge
   528         p1, p2 = pl[0], repo.changectx(node)
   529     pl = wc.parents()
   529         pa = p1.ancestor(p2)
   530     p1, p2 = pl[0], repo.changectx(node)
   530         fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
   531     pa = p1.ancestor(p2)
   531         fastforward = False
   532     fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
   532 
   533     fastforward = False
   533         ### check phase
   534 
   534         if not overwrite and len(pl) > 1:
   535     ### check phase
   535             raise util.Abort(_("outstanding uncommitted merges"))
   536     if not overwrite and len(pl) > 1:
   536         if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
   537         raise util.Abort(_("outstanding uncommitted merges"))
   537             if branchmerge:
   538     if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
   538                 if p1.branch() != p2.branch() and pa != p2:
   539         if branchmerge:
   539                     fastforward = True
   540             if p1.branch() != p2.branch() and pa != p2:
   540                 else:
   541                 fastforward = True
   541                     raise util.Abort(_("there is nothing to merge, just use "
   542             else:
   542                                        "'hg update' or look at 'hg heads'"))
   543                 raise util.Abort(_("there is nothing to merge, just use "
   543         elif not (overwrite or branchmerge):
   544                                    "'hg update' or look at 'hg heads'"))
   544             raise util.Abort(_("update spans branches, use 'hg merge' "
   545     elif not (overwrite or branchmerge):
   545                                "or 'hg update -C' to lose changes"))
   546         raise util.Abort(_("update spans branches, use 'hg merge' "
   546         if branchmerge and not forcemerge:
   547                            "or 'hg update -C' to lose changes"))
   547             if wc.files():
   548     if branchmerge and not forcemerge:
   548                 raise util.Abort(_("outstanding uncommitted changes"))
   549         if wc.files():
   549 
   550             raise util.Abort(_("outstanding uncommitted changes"))
   550         ### calculate phase
   551 
   551         action = []
   552     ### calculate phase
   552         if not force:
   553     action = []
   553             checkunknown(wc, p2)
   554     if not force:
   554         if not util.checkfolding(repo.path):
   555         checkunknown(wc, p2)
   555             checkcollision(p2)
   556     if not util.checkfolding(repo.path):
   556         if not branchmerge:
   557         checkcollision(p2)
   557             action += forgetremoved(wc, p2)
   558     if not branchmerge:
   558         action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
   559         action += forgetremoved(wc, p2)
   559 
   560     action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
   560         ### apply phase
   561 
   561         if not branchmerge: # just jump to the new rev
   562     ### apply phase
   562             fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
   563     if not branchmerge: # just jump to the new rev
   563         if not partial:
   564         fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
   564             repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
   565     if not partial:
   565 
   566         repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
   566         stats = applyupdates(repo, action, wc, p2)
   567 
   567 
   568     stats = applyupdates(repo, action, wc, p2)
   568         if not partial:
   569 
   569             recordupdates(repo, action, branchmerge)
   570     if not partial:
   570             repo.dirstate.setparents(fp1, fp2)
   571         recordupdates(repo, action, branchmerge)
   571             if not branchmerge and not fastforward:
   572         repo.dirstate.setparents(fp1, fp2)
   572                 repo.dirstate.setbranch(p2.branch())
   573         if not branchmerge and not fastforward:
   573             repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
   574             repo.dirstate.setbranch(p2.branch())
   574 
   575         repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
   575         return stats
   576 
   576     finally:
   577     return stats
   577         del wlock
   578