mercurial/copies.py
changeset 45640 2693659c2b34
parent 45639 7a757e893532
child 45670 a8fb29b05f92
equal deleted inserted replaced
45639:7a757e893532 45640:2693659c2b34
   169             )
   169             )
   170     return cm
   170     return cm
   171 
   171 
   172 
   172 
   173 def _revinfo_getter(repo):
   173 def _revinfo_getter(repo):
   174     """return a function that return multiple data given a <rev>"i
   174     """returns a function that returns the following data given a <rev>"
   175 
   175 
   176     * p1: revision number of first parent
   176     * p1: revision number of first parent
   177     * p2: revision number of first parent
   177     * p2: revision number of first parent
   178     * p1copies: mapping of copies from p1
   178     * changes: a ChangingFiles object
   179     * p2copies: mapping of copies from p2
       
   180     * removed: a list of removed files
       
   181     * ismerged: a callback to know if file was merged in that revision
       
   182     """
   179     """
   183     cl = repo.changelog
   180     cl = repo.changelog
   184     parents = cl.parentrevs
   181     parents = cl.parentrevs
   185 
       
   186     def get_ismerged(rev):
       
   187         ctx = repo[rev]
       
   188 
       
   189         def ismerged(path):
       
   190             if path not in ctx.files():
       
   191                 return False
       
   192             fctx = ctx[path]
       
   193             parents = fctx._filelog.parents(fctx._filenode)
       
   194             nb_parents = 0
       
   195             for n in parents:
       
   196                 if n != node.nullid:
       
   197                     nb_parents += 1
       
   198             return nb_parents >= 2
       
   199 
       
   200         return ismerged
       
   201 
   182 
   202     changelogrevision = cl.changelogrevision
   183     changelogrevision = cl.changelogrevision
   203 
   184 
   204     # A small cache to avoid doing the work twice for merges
   185     # A small cache to avoid doing the work twice for merges
   205     #
   186     #
   230         p1, p2 = parents(rev)
   211         p1, p2 = parents(rev)
   231         value = None
   212         value = None
   232         e = merge_caches.pop(rev, None)
   213         e = merge_caches.pop(rev, None)
   233         if e is not None:
   214         if e is not None:
   234             return e
   215             return e
   235         c = changelogrevision(rev)
   216         value = (p1, p2, changelogrevision(rev).changes)
   236         p1copies = c.p1copies
       
   237         p2copies = c.p2copies
       
   238         removed = c.filesremoved
       
   239         if p1 != node.nullrev and p2 != node.nullrev:
   217         if p1 != node.nullrev and p2 != node.nullrev:
   240             # XXX some case we over cache, IGNORE
   218             # XXX some case we over cache, IGNORE
   241             value = merge_caches[rev] = (
   219             merge_caches[rev] = value
   242                 p1,
       
   243                 p2,
       
   244                 p1copies,
       
   245                 p2copies,
       
   246                 removed,
       
   247                 get_ismerged(rev),
       
   248             )
       
   249 
       
   250         if value is None:
       
   251             value = (p1, p2, p1copies, p2copies, removed, get_ismerged(rev))
       
   252         return value
   220         return value
   253 
   221 
   254     return revinfo
   222     return revinfo
   255 
   223 
   256 
   224 
   322         copies = all_copies.pop(r, None)
   290         copies = all_copies.pop(r, None)
   323         if copies is None:
   291         if copies is None:
   324             # this is a root
   292             # this is a root
   325             copies = {}
   293             copies = {}
   326         for i, c in enumerate(children[r]):
   294         for i, c in enumerate(children[r]):
   327             p1, p2, p1copies, p2copies, removed, ismerged = revinfo(c)
   295             p1, p2, changes = revinfo(c)
   328             if r == p1:
   296             if r == p1:
   329                 parent = 1
   297                 parent = 1
   330                 childcopies = p1copies
   298                 childcopies = changes.copied_from_p1
   331             else:
   299             else:
   332                 assert r == p2
   300                 assert r == p2
   333                 parent = 2
   301                 parent = 2
   334                 childcopies = p2copies
   302                 childcopies = changes.copied_from_p2
   335             if not alwaysmatch:
   303             if not alwaysmatch:
   336                 childcopies = {
   304                 childcopies = {
   337                     dst: src for dst, src in childcopies.items() if match(dst)
   305                     dst: src for dst, src in childcopies.items() if match(dst)
   338                 }
   306                 }
   339             newcopies = copies
   307             newcopies = copies
   343                     prev = copies.get(source)
   311                     prev = copies.get(source)
   344                     if prev is not None and prev[1] is not None:
   312                     if prev is not None and prev[1] is not None:
   345                         source = prev[1]
   313                         source = prev[1]
   346                     newcopies[dest] = (c, source)
   314                     newcopies[dest] = (c, source)
   347                 assert newcopies is not copies
   315                 assert newcopies is not copies
   348             for f in removed:
   316             for f in changes.removed:
   349                 if f in newcopies:
   317                 if f in newcopies:
   350                     if newcopies is copies:
   318                     if newcopies is copies:
   351                         # copy on write to avoid affecting potential other
   319                         # copy on write to avoid affecting potential other
   352                         # branches.  when there are no other branches, this
   320                         # branches.  when there are no other branches, this
   353                         # could be avoided.
   321                         # could be avoided.
   364                 # This is an arbitrary choice made anew when implementing
   332                 # This is an arbitrary choice made anew when implementing
   365                 # changeset based copies. It was made without regards with
   333                 # changeset based copies. It was made without regards with
   366                 # potential filelog related behavior.
   334                 # potential filelog related behavior.
   367                 if parent == 1:
   335                 if parent == 1:
   368                     _merge_copies_dict(
   336                     _merge_copies_dict(
   369                         othercopies, newcopies, isancestor, ismerged
   337                         othercopies, newcopies, isancestor, changes
   370                     )
   338                     )
   371                 else:
   339                 else:
   372                     _merge_copies_dict(
   340                     _merge_copies_dict(
   373                         newcopies, othercopies, isancestor, ismerged
   341                         newcopies, othercopies, isancestor, changes
   374                     )
   342                     )
   375                     all_copies[c] = newcopies
   343                     all_copies[c] = newcopies
   376 
   344 
   377     final_copies = {}
   345     final_copies = {}
   378     for dest, (tt, source) in all_copies[targetrev].items():
   346     for dest, (tt, source) in all_copies[targetrev].items():
   379         if source is not None:
   347         if source is not None:
   380             final_copies[dest] = source
   348             final_copies[dest] = source
   381     return final_copies
   349     return final_copies
   382 
   350 
   383 
   351 
   384 def _merge_copies_dict(minor, major, isancestor, ismerged):
   352 def _merge_copies_dict(minor, major, isancestor, changes):
   385     """merge two copies-mapping together, minor and major
   353     """merge two copies-mapping together, minor and major
   386 
   354 
   387     In case of conflict, value from "major" will be picked.
   355     In case of conflict, value from "major" will be picked.
   388 
   356 
   389     - `isancestors(low_rev, high_rev)`: callable return True if `low_rev` is an
   357     - `isancestors(low_rev, high_rev)`: callable return True if `low_rev` is an
   404             # content from "major" wins, unless it is older
   372             # content from "major" wins, unless it is older
   405             # than the branch point or there is a merge
   373             # than the branch point or there is a merge
   406             if (
   374             if (
   407                 new_tt == other_tt
   375                 new_tt == other_tt
   408                 or not isancestor(new_tt, other_tt)
   376                 or not isancestor(new_tt, other_tt)
   409                 or ismerged(dest)
   377                 or dest in changes.merged
   410             ):
   378             ):
   411                 minor[dest] = value
   379                 minor[dest] = value
   412 
   380 
   413 
   381 
   414 def _revinfo_getter_extra(repo):
   382 def _revinfo_getter_extra(repo):