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