mercurial/merge.py
changeset 3315 38be819a1225
parent 3314 b16456909a0a
child 3316 39fd6e82ea38
equal deleted inserted replaced
3314:b16456909a0a 3315:38be819a1225
    11 demandload(globals(), "errno util os tempfile")
    11 demandload(globals(), "errno util os tempfile")
    12 
    12 
    13 def filemerge(repo, fw, fo, wctx, mctx):
    13 def filemerge(repo, fw, fo, wctx, mctx):
    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
    17     fo = filename in other parent
    17     fo = filename in other parent
    18     wctx, mctx = working and merge changecontexts
    18     wctx, mctx = working and merge changecontexts
    19 
       
    20     TODO:
       
    21       if fw is copied in the working directory, we get confused
       
    22       implement move and fd
       
    23     """
    19     """
    24 
    20 
    25     def temp(prefix, ctx):
    21     def temp(prefix, ctx):
    26         pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
    22         pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
    27         (fd, name) = tempfile.mkstemp(prefix=pre)
    23         (fd, name) = tempfile.mkstemp(prefix=pre)
    62     os.unlink(b)
    58     os.unlink(b)
    63     os.unlink(c)
    59     os.unlink(c)
    64     return r
    60     return r
    65 
    61 
    66 def checkunknown(wctx, mctx):
    62 def checkunknown(wctx, mctx):
    67     """
    63     "check for collisions between unknown files and files in mctx"
    68     check for collisions between unknown files and files in m2
       
    69     """
       
    70     man = mctx.manifest()
    64     man = mctx.manifest()
    71     for f in wctx.unknown():
    65     for f in wctx.unknown():
    72         if f in man:
    66         if f in man:
    73             if mctx.filectx(f).cmp(wctx.filectx(f).data()):
    67             if mctx.filectx(f).cmp(wctx.filectx(f).data()):
    74                 raise util.Abort(_("'%s' already exists in the working"
    68                 raise util.Abort(_("'%s' already exists in the working"
    92             action.append((f, "f"))
    86             action.append((f, "f"))
    93 
    87 
    94     return action
    88     return action
    95 
    89 
    96 def nonoverlap(d1, d2):
    90 def nonoverlap(d1, d2):
    97     """
    91     "Return list of elements in d1 not in d2"
    98     Return list of elements in d1 not in d2
       
    99     """
       
   100 
    92 
   101     l = []
    93     l = []
   102     for d in d1:
    94     for d in d1:
   103         if d not in d2:
    95         if d not in d2:
   104             l.append(d)
    96             l.append(d)
   105 
    97 
   106     l.sort()
    98     l.sort()
   107     return l
    99     return l
   108 
   100 
   109 def findold(fctx, limit):
   101 def findold(fctx, limit):
   110     """
   102     "find files that path was copied from, back to linkrev limit"
   111     find files that path was copied from, back to linkrev limit
       
   112     """
       
   113 
   103 
   114     old = {}
   104     old = {}
   115     orig = fctx.path()
   105     orig = fctx.path()
   116     visit = [fctx]
   106     visit = [fctx]
   117     while visit:
   107     while visit:
   172 
   162 
   173     return copy
   163     return copy
   174 
   164 
   175 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
   165 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
   176     """
   166     """
   177     Merge manifest m1 with m2 using ancestor ma and generate merge action list
   167     Merge p1 and p2 with ancestor ma and generate merge action list
       
   168 
       
   169     overwrite = whether we clobber working files
       
   170     partial = function to filter file lists
   178     """
   171     """
   179 
   172 
   180     repo.ui.note(_("resolving manifests\n"))
   173     repo.ui.note(_("resolving manifests\n"))
   181     repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
   174     repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
   182     repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
   175     repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
   273             act("remote created", "g", f, m2.execf(f))
   266             act("remote created", "g", f, m2.execf(f))
   274 
   267 
   275     return action
   268     return action
   276 
   269 
   277 def applyupdates(repo, action, wctx, mctx):
   270 def applyupdates(repo, action, wctx, mctx):
       
   271     "apply the merge action list to the working directory"
       
   272 
   278     updated, merged, removed, unresolved = 0, 0, 0, 0
   273     updated, merged, removed, unresolved = 0, 0, 0, 0
   279     action.sort()
   274     action.sort()
   280     for a in action:
   275     for a in action:
   281         f, m = a[:2]
   276         f, m = a[:2]
   282         if f[0] == "/":
   277         if f[0] == "/":
   317             util.set_exec(repo.wjoin(f), flag)
   312             util.set_exec(repo.wjoin(f), flag)
   318 
   313 
   319     return updated, merged, removed, unresolved
   314     return updated, merged, removed, unresolved
   320 
   315 
   321 def recordupdates(repo, action, branchmerge, mctx):
   316 def recordupdates(repo, action, branchmerge, mctx):
       
   317     "record merge actions to the dirstate"
       
   318 
   322     for a in action:
   319     for a in action:
   323         f, m = a[:2]
   320         f, m = a[:2]
   324         if m == "r": # remove
   321         if m == "r": # remove
   325             if branchmerge:
   322             if branchmerge:
   326                 repo.dirstate.update([f], 'r')
   323                 repo.dirstate.update([f], 'r')
   355                 else:
   352                 else:
   356                     repo.dirstate.copy(f2, fd)
   353                     repo.dirstate.copy(f2, fd)
   357 
   354 
   358 def update(repo, node, branchmerge=False, force=False, partial=None,
   355 def update(repo, node, branchmerge=False, force=False, partial=None,
   359            wlock=None, show_stats=True, remind=True):
   356            wlock=None, show_stats=True, remind=True):
       
   357     """
       
   358     Perform a merge between the working directory and the given node
       
   359 
       
   360     branchmerge = whether to merge between branches
       
   361     force = whether to force branch merging or file overwriting
       
   362     partial = a function to filter file lists (dirstate not updated)
       
   363     wlock = working dir lock, if already held
       
   364     show_stats = whether to report merge statistics
       
   365     remind = whether to remind about merge
       
   366     """
   360 
   367 
   361     if not wlock:
   368     if not wlock:
   362         wlock = repo.wlock()
   369         wlock = repo.wlock()
   363 
   370 
   364     overwrite = force and not branchmerge
   371     overwrite = force and not branchmerge