mercurial/copies.py
changeset 30581 43a9e02a7b7f
parent 30361 1070df141718
child 31256 5a909a8098a1
equal deleted inserted replaced
30580:51e7c83e05ee 30581:43a9e02a7b7f
   308 def mergecopies(repo, c1, c2, base):
   308 def mergecopies(repo, c1, c2, base):
   309     """
   309     """
   310     Find moves and copies between context c1 and c2 that are relevant
   310     Find moves and copies between context c1 and c2 that are relevant
   311     for merging. 'base' will be used as the merge base.
   311     for merging. 'base' will be used as the merge base.
   312 
   312 
   313     Returns four dicts: "copy", "movewithdir", "diverge", and
   313     Returns five dicts: "copy", "movewithdir", "diverge", "renamedelete" and
   314     "renamedelete".
   314     "dirmove".
   315 
   315 
   316     "copy" is a mapping from destination name -> source name,
   316     "copy" is a mapping from destination name -> source name,
   317     where source is in c1 and destination is in c2 or vice-versa.
   317     where source is in c1 and destination is in c2 or vice-versa.
   318 
   318 
   319     "movewithdir" is a mapping from source name -> destination name,
   319     "movewithdir" is a mapping from source name -> destination name,
   324     "diverge" is a mapping of source name -> list of destination names
   324     "diverge" is a mapping of source name -> list of destination names
   325     for divergent renames.
   325     for divergent renames.
   326 
   326 
   327     "renamedelete" is a mapping of source name -> list of destination
   327     "renamedelete" is a mapping of source name -> list of destination
   328     names for files deleted in c1 that were renamed in c2 or vice-versa.
   328     names for files deleted in c1 that were renamed in c2 or vice-versa.
       
   329 
       
   330     "dirmove" is a mapping of detected source dir -> destination dir renames.
       
   331     This is needed for handling changes to new files previously grafted into
       
   332     renamed directories.
   329     """
   333     """
   330     # avoid silly behavior for update from empty dir
   334     # avoid silly behavior for update from empty dir
   331     if not c1 or not c2 or c1 == c2:
   335     if not c1 or not c2 or c1 == c2:
   332         return {}, {}, {}, {}
   336         return {}, {}, {}, {}, {}
   333 
   337 
   334     # avoid silly behavior for parent -> working dir
   338     # avoid silly behavior for parent -> working dir
   335     if c2.node() is None and c1.node() == repo.dirstate.p1():
   339     if c2.node() is None and c1.node() == repo.dirstate.p1():
   336         return repo.dirstate.copies(), {}, {}, {}
   340         return repo.dirstate.copies(), {}, {}, {}, {}
   337 
   341 
   338     # Copy trace disabling is explicitly below the node == p1 logic above
   342     # Copy trace disabling is explicitly below the node == p1 logic above
   339     # because the logic above is required for a simple copy to be kept across a
   343     # because the logic above is required for a simple copy to be kept across a
   340     # rebase.
   344     # rebase.
   341     if repo.ui.configbool('experimental', 'disablecopytrace'):
   345     if repo.ui.configbool('experimental', 'disablecopytrace'):
   342         return {}, {}, {}, {}
   346         return {}, {}, {}, {}, {}
   343 
   347 
   344     # In certain scenarios (e.g. graft, update or rebase), base can be
   348     # In certain scenarios (e.g. graft, update or rebase), base can be
   345     # overridden We still need to know a real common ancestor in this case We
   349     # overridden We still need to know a real common ancestor in this case We
   346     # can't just compute _c1.ancestor(_c2) and compare it to ca, because there
   350     # can't just compute _c1.ancestor(_c2) and compare it to ca, because there
   347     # can be multiple common ancestors, e.g. in case of bidmerge.  Because our
   351     # can be multiple common ancestors, e.g. in case of bidmerge.  Because our
   363         tca = _c1.ancestor(_c2)
   367         tca = _c1.ancestor(_c2)
   364 
   368 
   365     limit = _findlimit(repo, c1.rev(), c2.rev())
   369     limit = _findlimit(repo, c1.rev(), c2.rev())
   366     if limit is None:
   370     if limit is None:
   367         # no common ancestor, no copies
   371         # no common ancestor, no copies
   368         return {}, {}, {}, {}
   372         return {}, {}, {}, {}, {}
   369     repo.ui.debug("  searching for copies back to rev %d\n" % limit)
   373     repo.ui.debug("  searching for copies back to rev %d\n" % limit)
   370 
   374 
   371     m1 = c1.manifest()
   375     m1 = c1.manifest()
   372     m2 = c2.manifest()
   376     m2 = c2.manifest()
   373     mb = base.manifest()
   377     mb = base.manifest()
   501             repo.ui.debug("   src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f,
   505             repo.ui.debug("   src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f,
   502                                                               note))
   506                                                               note))
   503     del divergeset
   507     del divergeset
   504 
   508 
   505     if not fullcopy:
   509     if not fullcopy:
   506         return copy, {}, diverge, renamedelete
   510         return copy, {}, diverge, renamedelete, {}
   507 
   511 
   508     repo.ui.debug("  checking for directory renames\n")
   512     repo.ui.debug("  checking for directory renames\n")
   509 
   513 
   510     # generate a directory move map
   514     # generate a directory move map
   511     d1, d2 = c1.dirs(), c2.dirs()
   515     d1, d2 = c1.dirs(), c2.dirs()
   539         if i in dirmove:
   543         if i in dirmove:
   540             del dirmove[i]
   544             del dirmove[i]
   541     del d1, d2, invalid
   545     del d1, d2, invalid
   542 
   546 
   543     if not dirmove:
   547     if not dirmove:
   544         return copy, {}, diverge, renamedelete
   548         return copy, {}, diverge, renamedelete, {}
   545 
   549 
   546     for d in dirmove:
   550     for d in dirmove:
   547         repo.ui.debug("   discovered dir src: '%s' -> dst: '%s'\n" %
   551         repo.ui.debug("   discovered dir src: '%s' -> dst: '%s'\n" %
   548                       (d, dirmove[d]))
   552                       (d, dirmove[d]))
   549 
   553 
   559                         movewithdir[f] = df
   563                         movewithdir[f] = df
   560                         repo.ui.debug(("   pending file src: '%s' -> "
   564                         repo.ui.debug(("   pending file src: '%s' -> "
   561                                        "dst: '%s'\n") % (f, df))
   565                                        "dst: '%s'\n") % (f, df))
   562                     break
   566                     break
   563 
   567 
   564     return copy, movewithdir, diverge, renamedelete
   568     return copy, movewithdir, diverge, renamedelete, dirmove
   565 
   569 
   566 def _related(f1, f2, limit):
   570 def _related(f1, f2, limit):
   567     """return True if f1 and f2 filectx have a common ancestor
   571     """return True if f1 and f2 filectx have a common ancestor
   568 
   572 
   569     Walk back to common ancestor to see if the two files originate
   573     Walk back to common ancestor to see if the two files originate