Mercurial > hg
comparison mercurial/copies.py @ 46148:70a9eb899637
copies: document the current algorithm step
We are about to reorganise everything and we document the "old" way to clarify
the change that leads to the "new way".
Differential Revision: https://phab.mercurial-scm.org/D9581
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 14 Dec 2020 11:32:20 +0100 |
parents | 59fa3890d40a |
children | 294d5aca4ff5 |
comparison
equal
deleted
inserted
replaced
46146:d109dda4a3e7 | 46148:70a9eb899637 |
---|---|
1 # coding: utf8 | |
1 # copies.py - copy detection for Mercurial | 2 # copies.py - copy detection for Mercurial |
2 # | 3 # |
3 # Copyright 2008 Matt Mackall <mpm@selenic.com> | 4 # Copyright 2008 Matt Mackall <mpm@selenic.com> |
4 # | 5 # |
5 # This software may be used and distributed according to the terms of the | 6 # This software may be used and distributed according to the terms of the |
349 ) | 350 ) |
350 | 351 |
351 isancestor = cached_is_ancestor(isancestor) | 352 isancestor = cached_is_ancestor(isancestor) |
352 | 353 |
353 all_copies = {} | 354 all_copies = {} |
355 # iterate over all the "parent" side of copy tracing "edge" | |
354 for r in revs: | 356 for r in revs: |
357 # fetch potential previously computed data for that parent | |
355 copies = all_copies.pop(r, None) | 358 copies = all_copies.pop(r, None) |
356 if copies is None: | 359 if copies is None: |
357 # this is a root | 360 # this is a root |
358 copies = {} | 361 copies = {} |
362 | |
363 # iterate over all known children to chain the existing data with the | |
364 # data from the parent → child edge. | |
359 for i, c in enumerate(children[r]): | 365 for i, c in enumerate(children[r]): |
360 p1, p2, changes = revinfo(c) | 366 p1, p2, changes = revinfo(c) |
361 childcopies = {} | 367 childcopies = {} |
368 | |
369 # select the right parent → child edge | |
362 if r == p1: | 370 if r == p1: |
363 parent = 1 | 371 parent = 1 |
364 if changes is not None: | 372 if changes is not None: |
365 childcopies = changes.copied_from_p1 | 373 childcopies = changes.copied_from_p1 |
366 else: | 374 else: |
370 childcopies = changes.copied_from_p2 | 378 childcopies = changes.copied_from_p2 |
371 if not alwaysmatch: | 379 if not alwaysmatch: |
372 childcopies = { | 380 childcopies = { |
373 dst: src for dst, src in childcopies.items() if match(dst) | 381 dst: src for dst, src in childcopies.items() if match(dst) |
374 } | 382 } |
383 | |
384 # chain the data in the edge with the existing data | |
375 newcopies = copies | 385 newcopies = copies |
376 if childcopies: | 386 if childcopies: |
377 newcopies = copies.copy() | 387 newcopies = copies.copy() |
378 for dest, source in pycompat.iteritems(childcopies): | 388 for dest, source in pycompat.iteritems(childcopies): |
379 prev = copies.get(source) | 389 prev = copies.get(source) |
390 # copy on write to avoid affecting potential other | 400 # copy on write to avoid affecting potential other |
391 # branches. when there are no other branches, this | 401 # branches. when there are no other branches, this |
392 # could be avoided. | 402 # could be avoided. |
393 newcopies = copies.copy() | 403 newcopies = copies.copy() |
394 newcopies[f] = (c, None) | 404 newcopies[f] = (c, None) |
405 | |
406 # check potential need to combine the data from another parent (for | |
407 # that child). See comment below for details. | |
395 othercopies = all_copies.get(c) | 408 othercopies = all_copies.get(c) |
396 if othercopies is None: | 409 if othercopies is None: |
397 all_copies[c] = newcopies | 410 all_copies[c] = newcopies |
398 elif newcopies is othercopies: | 411 elif newcopies is othercopies: |
399 # nothing to merge: | 412 # nothing to merge: |
416 # unnecessary. | 429 # unnecessary. |
417 minor, major = newcopies, othercopies.copy() | 430 minor, major = newcopies, othercopies.copy() |
418 copies = _merge_copies_dict(minor, major, isancestor, changes) | 431 copies = _merge_copies_dict(minor, major, isancestor, changes) |
419 all_copies[c] = copies | 432 all_copies[c] = copies |
420 | 433 |
434 # filter out internal details and return a {dest: source mapping} | |
421 final_copies = {} | 435 final_copies = {} |
422 for dest, (tt, source) in all_copies[targetrev].items(): | 436 for dest, (tt, source) in all_copies[targetrev].items(): |
423 if source is not None: | 437 if source is not None: |
424 final_copies[dest] = source | 438 final_copies[dest] = source |
425 return final_copies | 439 return final_copies |