mercurial/merge.py
changeset 3309 488d3062d225
parent 3305 e7abcf3a7c5f
child 3312 5c9806554d65
equal deleted inserted replaced
3308:192085505f6f 3309:488d3062d225
    14     """perform a 3-way merge in the working directory
    14     """perform a 3-way merge in the working directory
    15 
    15 
    16     fw = filename in the working directory and first parent
    16     fw = filename in the working directory and first parent
    17     fo = filename in other parent
    17     fo = filename in other parent
    18     fd = destination filename
    18     fd = destination filename
    19     my = fileid in first parent
       
    20     other = fileid in second parent
       
    21     wctx, mctx = working and merge changecontexts
    19     wctx, mctx = working and merge changecontexts
    22     move = whether to move or copy the file to the destination
    20     move = whether to move or copy the file to the destination
    23 
    21 
    24     TODO:
    22     TODO:
    25       if fw is copied in the working directory, we get confused
    23       if fw is copied in the working directory, we get confused
   210             # are files different?
   208             # are files different?
   211             if n != m2[f]:
   209             if n != m2[f]:
   212                 a = ma.get(f, nullid)
   210                 a = ma.get(f, nullid)
   213                 # are both different from the ancestor?
   211                 # are both different from the ancestor?
   214                 if not overwrite and n != a and m2[f] != a:
   212                 if not overwrite and n != a and m2[f] != a:
   215                     act("versions differ", f, "m", fmerge(f), n[:20], m2[f])
   213                     act("versions differ", f, "m", fmerge(f))
   216                 # are we clobbering?
   214                 # are we clobbering?
   217                 # is remote's version newer?
   215                 # is remote's version newer?
   218                 # or are we going back in time and clean?
   216                 # or are we going back in time and clean?
   219                 elif overwrite or m2[f] != a or (backwards and not n[20:]):
   217                 elif overwrite or m2[f] != a or (backwards and not n[20:]):
   220                     act("remote is newer", f, "g", m2.execf(f), m2[f])
   218                     act("remote is newer", f, "g", m2.execf(f), m2[f])
   227                     act("update permissions", f, "e", m2.execf(f))
   225                     act("update permissions", f, "e", m2.execf(f))
   228         elif f in copy:
   226         elif f in copy:
   229             f2 = copy[f]
   227             f2 = copy[f]
   230             if f in ma: # case 3,20 A/B/A
   228             if f in ma: # case 3,20 A/B/A
   231                 act("remote moved",
   229                 act("remote moved",
   232                     f, "c", f2, f2, m1[f], m2[f2], fmerge(f, f2, f), True)
   230                     f, "c", f2, f2, fmerge(f, f2, f), True)
   233             else:
   231             else:
   234                 if f2 in m1: # case 2 A,B/B/B
   232                 if f2 in m1: # case 2 A,B/B/B
   235                     act("local copied",
   233                     act("local copied",
   236                         f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False)
   234                         f, "c", f2, f, fmerge(f, f2, f2), False)
   237                 else: # case 4,21 A/B/B
   235                 else: # case 4,21 A/B/B
   238                     act("local moved",
   236                     act("local moved",
   239                         f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False)
   237                         f, "c", f2, f, fmerge(f, f2, f2), False)
   240         elif f in ma:
   238         elif f in ma:
   241             if n != ma[f] and not overwrite:
   239             if n != ma[f] and not overwrite:
   242                 if repo.ui.prompt(
   240                 if repo.ui.prompt(
   243                     (_(" local changed %s which remote deleted\n") % f) +
   241                     (_(" local changed %s which remote deleted\n") % f) +
   244                     _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"):
   242                     _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"):
   258         if f in copy:
   256         if f in copy:
   259             f2 = copy[f]
   257             f2 = copy[f]
   260             if f2 not in m2: # already seen
   258             if f2 not in m2: # already seen
   261                 continue
   259                 continue
   262             # rename case 1, A/A,B/A
   260             # rename case 1, A/A,B/A
   263             act("remote copied",
   261             act("remote copied", f2, "c", f, f, fmerge(f2, f, f2), False)
   264                 f2, "c", f, f, m1[f2], m2[f], fmerge(f2, f, f2), False)
       
   265         elif f in ma:
   262         elif f in ma:
   266             if overwrite or backwards:
   263             if overwrite or backwards:
   267                 act("recreating", f, "g", m2.execf(f), n)
   264                 act("recreating", f, "g", m2.execf(f), n)
   268             elif n != ma[f]:
   265             elif n != ma[f]:
   269                 if repo.ui.prompt(
   266                 if repo.ui.prompt(
   291                 if inst.errno != errno.ENOENT:
   288                 if inst.errno != errno.ENOENT:
   292                     repo.ui.warn(_("update failed to remove %s: %s!\n") %
   289                     repo.ui.warn(_("update failed to remove %s: %s!\n") %
   293                                  (f, inst.strerror))
   290                                  (f, inst.strerror))
   294             removed +=1
   291             removed +=1
   295         elif m == "c": # copy
   292         elif m == "c": # copy
   296             f2, fd, my, other, flag, move = a[2:]
   293             f2, fd, flag, move = a[2:]
   297             repo.ui.status(_("merging %s and %s to %s\n") % (f, f2, fd))
   294             repo.ui.status(_("merging %s and %s to %s\n") % (f, f2, fd))
   298             if filemerge(repo, f, f2, fd, wctx, mctx, move):
   295             if filemerge(repo, f, f2, fd, wctx, mctx, move):
   299                 unresolved += 1
   296                 unresolved += 1
   300             util.set_exec(repo.wjoin(fd), flag)
   297             util.set_exec(repo.wjoin(fd), flag)
   301             merged += 1
   298             merged += 1
   302         elif m == "m": # merge
   299         elif m == "m": # merge
   303             flag, my, other = a[2:]
   300             flag = a[2]
   304             repo.ui.status(_("merging %s\n") % f)
   301             repo.ui.status(_("merging %s\n") % f)
   305             if filemerge(repo, f, f, f, wctx, mctx, False):
   302             if filemerge(repo, f, f, f, wctx, mctx, False):
   306                 unresolved += 1
   303                 unresolved += 1
   307             util.set_exec(repo.wjoin(f), flag)
   304             util.set_exec(repo.wjoin(f), flag)
   308             merged += 1
   305             merged += 1
   309         elif m == "g": # get
   306         elif m == "g": # get
   310             flag, node = a[2:]
   307             flag, node = a[2:]
   311             repo.ui.note(_("getting %s\n") % f)
   308             repo.ui.note(_("getting %s\n") % f)
   312             t = repo.file(f).read(node)
   309             t = mctx.filectx(f).data()
   313             repo.wwrite(f, t)
   310             repo.wwrite(f, t)
   314             util.set_exec(repo.wjoin(f), flag)
   311             util.set_exec(repo.wjoin(f), flag)
   315             updated += 1
   312             updated += 1
   316         elif m == "e": # exec
   313         elif m == "e": # exec
   317             flag = a[2:]
   314             flag = a[2]
   318             util.set_exec(repo.wjoin(f), flag)
   315             util.set_exec(repo.wjoin(f), flag)
   319 
   316 
   320     return updated, merged, removed, unresolved
   317     return updated, merged, removed, unresolved
   321 
   318 
   322 def recordupdates(repo, action, branchmerge):
   319 def recordupdates(repo, action, branchmerge, mctx):
   323     for a in action:
   320     for a in action:
   324         f, m = a[:2]
   321         f, m = a[:2]
   325         if m == "r": # remove
   322         if m == "r": # remove
   326             if branchmerge:
   323             if branchmerge:
   327                 repo.dirstate.update([f], 'r')
   324                 repo.dirstate.update([f], 'r')
   333             if branchmerge:
   330             if branchmerge:
   334                 repo.dirstate.update([f], 'n', st_mtime=-1)
   331                 repo.dirstate.update([f], 'n', st_mtime=-1)
   335             else:
   332             else:
   336                 repo.dirstate.update([f], 'n')
   333                 repo.dirstate.update([f], 'n')
   337         elif m == "m": # merge
   334         elif m == "m": # merge
   338             flag, my, other = a[2:]
   335             flag = a[2]
   339             if branchmerge:
   336             if branchmerge:
   340                 # We've done a branch merge, mark this file as merged
   337                 # We've done a branch merge, mark this file as merged
   341                 # so that we properly record the merger later
   338                 # so that we properly record the merger later
   342                 repo.dirstate.update([f], 'm')
   339                 repo.dirstate.update([f], 'm')
   343             else:
   340             else:
   345                 # we set the dirstate to emulate a normal checkout
   342                 # we set the dirstate to emulate a normal checkout
   346                 # of that file some time in the past. Thus our
   343                 # of that file some time in the past. Thus our
   347                 # merge will appear as a normal local file
   344                 # merge will appear as a normal local file
   348                 # modification.
   345                 # modification.
   349                 fl = repo.file(f)
   346                 fl = repo.file(f)
   350                 f_len = fl.size(fl.rev(other))
   347                 f_len = mctx.filectx(f).size()
   351                 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1)
   348                 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1)
   352         elif m == "c": # copy
   349         elif m == "c": # copy
   353             f2, fd, my, other, flag, move = a[2:]
   350             f2, fd, flag, move = a[2:]
   354             if branchmerge:
   351             if branchmerge:
   355                 # We've done a branch merge, mark this file as merged
   352                 # We've done a branch merge, mark this file as merged
   356                 # so that we properly record the merger later
   353                 # so that we properly record the merger later
   357                 repo.dirstate.update([fd], 'm')
   354                 repo.dirstate.update([fd], 'm')
   358             else:
   355             else:
   360                 # we set the dirstate to emulate a normal checkout
   357                 # we set the dirstate to emulate a normal checkout
   361                 # of that file some time in the past. Thus our
   358                 # of that file some time in the past. Thus our
   362                 # merge will appear as a normal local file
   359                 # merge will appear as a normal local file
   363                 # modification.
   360                 # modification.
   364                 fl = repo.file(f)
   361                 fl = repo.file(f)
   365                 f_len = fl.size(fl.rev(other))
   362                 f_len = mctx.filectx(f).size()
   366                 repo.dirstate.update([fd], 'n', st_size=f_len, st_mtime=-1)
   363                 repo.dirstate.update([fd], 'n', st_size=f_len, st_mtime=-1)
   367             if move:
   364             if move:
   368                 repo.dirstate.update([f], 'r')
   365                 repo.dirstate.update([f], 'r')
   369             if f != fd:
   366             if f != fd:
   370                 repo.dirstate.copy(f, fd)
   367                 repo.dirstate.copy(f, fd)
   435 
   432 
   436     updated, merged, removed, unresolved = applyupdates(repo, action, wc, p2)
   433     updated, merged, removed, unresolved = applyupdates(repo, action, wc, p2)
   437 
   434 
   438     # update dirstate
   435     # update dirstate
   439     if not partial:
   436     if not partial:
   440         recordupdates(repo, action, branchmerge)
   437         recordupdates(repo, action, branchmerge, p2)
   441         repo.dirstate.setparents(fp1, fp2)
   438         repo.dirstate.setparents(fp1, fp2)
   442         repo.hook('update', parent1=xp1, parent2=xp2, error=unresolved)
   439         repo.hook('update', parent1=xp1, parent2=xp2, error=unresolved)
   443 
   440 
   444     if show_stats:
   441     if show_stats:
   445         stats = ((updated, _("updated")),
   442         stats = ((updated, _("updated")),