Mercurial > public > mercurial-scm > hg
comparison mercurial/copies.py @ 30581:43a9e02a7b7f
graft: support grafting changes to new file in renamed directory (issue5436)
author | G?bor Stefanik <gabor.stefanik@nng.com> |
---|---|
date | Mon, 05 Dec 2016 17:40:01 +0100 |
parents | 1070df141718 |
children | 5a909a8098a1 |
comparison
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 |