equal
deleted
inserted
replaced
|
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 |