mercurial/copies.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Thu, 16 Feb 2023 04:04:40 +0100
changeset 50137 a66926099c0f
parent 49037 642e31cb55f0
child 51749 493034cc3265
permissions -rw-r--r--
localrepo: enforce a clean dirstate when the transaction open This is important to simplify the backup process. This also seems like a quite reasonable expectation. See inline documentation for details.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
46148
70a9eb899637 copies: document the current algorithm step
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46114
diff changeset
     1
# coding: utf8
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
# copies.py - copy detection for Mercurial
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
#
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46689
diff changeset
     4
# Copyright 2008 Olivia Mackall <olivia@selenic.com>
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
     6
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10262
diff changeset
     7
# GNU General Public License version 2 or any later version.
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
     9
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
    10
import collections
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
    11
import os
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
34846
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
    13
from .i18n import _
47055
d55b71393907 node: replace nullid and friends with nodeconstants class
Joerg Sonnenberger <joerg@bec.de>
parents: 46843
diff changeset
    14
from .node import nullrev
43148
843da18386d5 sidedatacopies: deal with upgrading and downgrading to that format
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43147
diff changeset
    15
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    16
from . import (
33886
252fb66ee5bb copies: use intersectmatchers() in non-merge p1 optimization
Yuya Nishihara <yuya@tcha.org>
parents: 33843
diff changeset
    17
    match as matchmod,
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    18
    pathutil,
45977
a66568f20ddc copies: use the rust code for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45957
diff changeset
    19
    policy,
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    20
    util,
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    21
)
43148
843da18386d5 sidedatacopies: deal with upgrading and downgrading to that format
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43147
diff changeset
    22
843da18386d5 sidedatacopies: deal with upgrading and downgrading to that format
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43147
diff changeset
    23
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
    24
from .utils import stringutil
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
    25
46061
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
    26
from .revlogutils import (
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
    27
    flagutil,
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
    28
    sidedata as sidedatamod,
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
    29
)
45672
f877b3628015 copies: return None instead of ChangingFiles when relevant
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45670
diff changeset
    30
45977
a66568f20ddc copies: use the rust code for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45957
diff changeset
    31
rustmod = policy.importrust("copy_tracing")
a66568f20ddc copies: use the rust code for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45957
diff changeset
    32
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    33
42593
11ceb1b8fd74 copies: inline _chainandfilter() to prepare for next patch
Martin von Zweigbergk <martinvonz@google.com>
parents: 42592
diff changeset
    34
def _filter(src, dst, t):
11ceb1b8fd74 copies: inline _chainandfilter() to prepare for next patch
Martin von Zweigbergk <martinvonz@google.com>
parents: 42592
diff changeset
    35
    """filters out invalid copies after chaining"""
42257
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    36
42593
11ceb1b8fd74 copies: inline _chainandfilter() to prepare for next patch
Martin von Zweigbergk <martinvonz@google.com>
parents: 42592
diff changeset
    37
    # When _chain()'ing copies in 'a' (from 'src' via some other commit 'mid')
11ceb1b8fd74 copies: inline _chainandfilter() to prepare for next patch
Martin von Zweigbergk <martinvonz@google.com>
parents: 42592
diff changeset
    38
    # with copies in 'b' (from 'mid' to 'dst'), we can get the different cases
46302
599d247af600 copies: fix some comment in _filter
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46184
diff changeset
    39
    # in the following table (not including trivial cases). For example, case 6
42593
11ceb1b8fd74 copies: inline _chainandfilter() to prepare for next patch
Martin von Zweigbergk <martinvonz@google.com>
parents: 42592
diff changeset
    40
    # is where a file existed in 'src' and remained under that name in 'mid' and
42257
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    41
    # then was renamed between 'mid' and 'dst'.
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    42
    #
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    43
    # case src mid dst result
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    44
    #   1   x   y   -    -
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    45
    #   2   x   y   y   x->y
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    46
    #   3   x   y   x    -
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    47
    #   4   x   y   z   x->z
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    48
    #   5   -   x   y    -
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    49
    #   6   x   x   y   x->y
42395
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    50
    #
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    51
    # _chain() takes care of chaining the copies in 'a' and 'b', but it
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    52
    # cannot tell the difference between cases 1 and 2, between 3 and 4, or
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    53
    # between 5 and 6, so it includes all cases in its result.
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    54
    # Cases 1, 3, and 5 are then removed by _filter().
42257
d1c2688eda80 copies: document cases in _chain()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42256
diff changeset
    55
42395
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    56
    for k, v in list(t.items()):
46471
1d6d1a15a963 copies: simplify the conditional for _filter's case 3
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46470
diff changeset
    57
        if k == v:  # case 3
42395
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    58
            del t[k]
46471
1d6d1a15a963 copies: simplify the conditional for _filter's case 3
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46470
diff changeset
    59
        elif v not in src:  # case 5
1d6d1a15a963 copies: simplify the conditional for _filter's case 3
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46470
diff changeset
    60
            # remove copies from files that didn't exist
42395
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    61
            del t[k]
46470
154ded9104f1 copies: clarify which case some conditional are handling
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46469
diff changeset
    62
        elif k not in dst:  # case 1
46471
1d6d1a15a963 copies: simplify the conditional for _filter's case 3
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46470
diff changeset
    63
            # remove copies to files that were then removed
42395
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    64
            del t[k]
f3d06d37e194 copies: split up _chain() in naive chaining and filtering steps
Martin von Zweigbergk <martinvonz@google.com>
parents: 42366
diff changeset
    65
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
    66
43804
995066c41bb2 copies: expand `_chain` variable name to make the function easier to read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43803
diff changeset
    67
def _chain(prefix, suffix):
995066c41bb2 copies: expand `_chain` variable name to make the function easier to read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43803
diff changeset
    68
    """chain two sets of copies 'prefix' and 'suffix'"""
995066c41bb2 copies: expand `_chain` variable name to make the function easier to read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43803
diff changeset
    69
    result = prefix.copy()
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
    70
    for key, value in suffix.items():
43804
995066c41bb2 copies: expand `_chain` variable name to make the function easier to read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43803
diff changeset
    71
        result[key] = prefix.get(value, value)
995066c41bb2 copies: expand `_chain` variable name to make the function easier to read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43803
diff changeset
    72
    return result
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    73
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
    74
43199
069cbbb53cdf copies: drop the findlimit logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43198
diff changeset
    75
def _tracefile(fctx, am, basemf):
35428
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35427
diff changeset
    76
    """return file context that is the ancestor of fctx present in ancestor
43198
c16fe77e340a pathcopies: give up any optimization based on `introrev`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43148
diff changeset
    77
    manifest am
c16fe77e340a pathcopies: give up any optimization based on `introrev`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43148
diff changeset
    78
c16fe77e340a pathcopies: give up any optimization based on `introrev`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43148
diff changeset
    79
    Note: we used to try and stop after a given limit, however checking if that
c16fe77e340a pathcopies: give up any optimization based on `introrev`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43148
diff changeset
    80
    limit is reached turned out to be very expensive. we are better off
c16fe77e340a pathcopies: give up any optimization based on `introrev`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43148
diff changeset
    81
    disabling that feature."""
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    82
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    83
    for f in fctx.ancestors():
42554
4ebbd7c4a3c5 copies: return only path from _tracefile() since that's all caller needs
Martin von Zweigbergk <martinvonz@google.com>
parents: 42527
diff changeset
    84
        path = f.path()
4ebbd7c4a3c5 copies: return only path from _tracefile() since that's all caller needs
Martin von Zweigbergk <martinvonz@google.com>
parents: 42527
diff changeset
    85
        if am.get(path, None) == f.filenode():
4ebbd7c4a3c5 copies: return only path from _tracefile() since that's all caller needs
Martin von Zweigbergk <martinvonz@google.com>
parents: 42527
diff changeset
    86
            return path
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
    87
        if basemf and basemf.get(path, None) == f.filenode():
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
    88
            return path
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    89
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
    90
41761
012f695546aa copies: respect narrowmatcher in "parent -> working dir" case
Martin von Zweigbergk <martinvonz@google.com>
parents: 41735
diff changeset
    91
def _dirstatecopies(repo, match=None):
012f695546aa copies: respect narrowmatcher in "parent -> working dir" case
Martin von Zweigbergk <martinvonz@google.com>
parents: 41735
diff changeset
    92
    ds = repo.dirstate
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    93
    c = ds.copies().copy()
34355
1a5abc45e2fa py3: explicitly convert dict.keys() and dict.items() into a list
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34318
diff changeset
    94
    for k in list(c):
48109
d86875b75838 dirstate-item: use `tracked` instead of `state` during copy detection
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47469
diff changeset
    95
        if not ds.get_entry(k).tracked or (match and not match(k)):
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    96
            del c[k]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    97
    return c
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    98
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
    99
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   100
def _computeforwardmissing(a, b, match=None):
24011
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   101
    """Computes which files are in b but not a.
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   102
    This is its own function so extensions can easily wrap this call to see what
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   103
    files _forwardcopies is about to process.
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   104
    """
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   105
    ma = a.manifest()
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   106
    mb = b.manifest()
31266
5a909a8098a1 copies: remove use of manifest.matches
Durham Goode <durham@fb.com>
parents: 30586
diff changeset
   107
    return mb.filesnotin(ma, match=match)
24011
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   108
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   109
42115
27475ae67676 copies: extract function for deciding whether to use changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 41941
diff changeset
   110
def usechangesetcentricalgo(repo):
27475ae67676 copies: extract function for deciding whether to use changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 41941
diff changeset
   111
    """Checks if we should use changeset-centric copy algorithms"""
43146
0171483b082f sidedatacopies: read rename information from sidedata
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43117
diff changeset
   112
    if repo.filecopiesmode == b'changeset-sidedata':
0171483b082f sidedatacopies: read rename information from sidedata
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43117
diff changeset
   113
        return True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   114
    readfrom = repo.ui.config(b'experimental', b'copies.read-from')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   115
    changesetsource = (b'changeset-only', b'compatibility')
43022
f3bcae1e9e23 copies: expand the logic of usechangesetcentricalgo
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 42729
diff changeset
   116
    return readfrom in changesetsource
42115
27475ae67676 copies: extract function for deciding whether to use changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 41941
diff changeset
   117
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   118
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   119
def _committedforwardcopies(a, b, base, match):
35429
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35428
diff changeset
   120
    """Like _forwardcopies(), but b.rev() cannot be None (working copy)"""
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   121
    # files might have to be traced back to the fctx parent of the last
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   122
    # one-side-only changeset, but not further back than that
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   123
    repo = a._repo
41765
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   124
42115
27475ae67676 copies: extract function for deciding whether to use changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 41941
diff changeset
   125
    if usechangesetcentricalgo(repo):
41765
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   126
        return _changesetforwardcopies(a, b, match)
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   127
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   128
    debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies')
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   129
    dbg = repo.ui.debug
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   130
    if debug:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   131
        dbg(b'debug.copies:    looking into rename from %s to %s\n' % (a, b))
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   132
    am = a.manifest()
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   133
    basemf = None if base is None else base.manifest()
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   134
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   135
    # find where new files came from
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   136
    # we currently don't try to find where old files went, too expensive
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   137
    # this means we can miss a case like 'hg rm b; hg cp a b'
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   138
    cm = {}
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   139
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   140
    # Computing the forward missing is quite expensive on large manifests, since
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   141
    # it compares the entire manifests. We can optimize it in the common use
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   142
    # case of computing what copies are in a commit versus its parent (like
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   143
    # during a rebase or histedit). Note, we exclude merge commits from this
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   144
    # optimization, since the ctx.files() for a merge commit is not correct for
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   145
    # this comparison.
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   146
    forwardmissingmatch = match
46843
728d89f6f9b1 refactor: prefer checks against nullrev over nullid
Joerg Sonnenberger <joerg@bec.de>
parents: 46819
diff changeset
   147
    if b.p1() == a and b.p2().rev() == nullrev:
41941
a791623458ef copies: remove dependency on scmutil by directly using match.exact()
Martin von Zweigbergk <martinvonz@google.com>
parents: 41937
diff changeset
   148
        filesmatcher = matchmod.exact(b.files())
33886
252fb66ee5bb copies: use intersectmatchers() in non-merge p1 optimization
Yuya Nishihara <yuya@tcha.org>
parents: 33843
diff changeset
   149
        forwardmissingmatch = matchmod.intersectmatchers(match, filesmatcher)
46480
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   150
    if repo.ui.configbool(b'devel', b'copy-tracing.trace-all-files'):
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   151
        missing = list(b.walk(match))
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   152
        # _computeforwardmissing(a, b, match=forwardmissingmatch)
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   153
        if debug:
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   154
            dbg(b'debug.copies:      searching all files: %d\n' % len(missing))
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   155
    else:
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   156
        missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   157
        if debug:
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   158
            dbg(
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   159
                b'debug.copies:      missing files to search: %d\n'
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   160
                % len(missing)
e948ad0dcbe2 copies: add an devel option to trace all files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46471
diff changeset
   161
            )
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   162
23980
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   163
    ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True)
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   164
42243
390ec72b8ea4 copies: process files in deterministic order for stable tests
Martin von Zweigbergk <martinvonz@google.com>
parents: 42211
diff changeset
   165
    for f in sorted(missing):
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   166
        if debug:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   167
            dbg(b'debug.copies:        tracing file: %s\n' % f)
23980
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   168
        fctx = b[f]
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   169
        fctx._ancestrycontext = ancestrycontext
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   170
40059
cf01616f8d96 copies: add time information to the debug information
Boris Feld <boris.feld@octobus.net>
parents: 40058
diff changeset
   171
        if debug:
cf01616f8d96 copies: add time information to the debug information
Boris Feld <boris.feld@octobus.net>
parents: 40058
diff changeset
   172
            start = util.timer()
43199
069cbbb53cdf copies: drop the findlimit logic
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43198
diff changeset
   173
        opath = _tracefile(fctx, am, basemf)
42554
4ebbd7c4a3c5 copies: return only path from _tracefile() since that's all caller needs
Martin von Zweigbergk <martinvonz@google.com>
parents: 42527
diff changeset
   174
        if opath:
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   175
            if debug:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   176
                dbg(b'debug.copies:          rename of: %s\n' % opath)
42554
4ebbd7c4a3c5 copies: return only path from _tracefile() since that's all caller needs
Martin von Zweigbergk <martinvonz@google.com>
parents: 42527
diff changeset
   177
            cm[f] = opath
40059
cf01616f8d96 copies: add time information to the debug information
Boris Feld <boris.feld@octobus.net>
parents: 40058
diff changeset
   178
        if debug:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   179
            dbg(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   180
                b'debug.copies:          time: %f seconds\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   181
                % (util.timer() - start)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   182
            )
35429
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35428
diff changeset
   183
    return cm
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35428
diff changeset
   184
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   185
46061
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   186
def _revinfo_getter(repo, match):
45642
2693659c2b34 copies: directly pass a changes object to the copy tracing code
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45641
diff changeset
   187
    """returns a function that returns the following data given a <rev>"
43255
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   188
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   189
    * p1: revision number of first parent
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   190
    * p2: revision number of first parent
45642
2693659c2b34 copies: directly pass a changes object to the copy tracing code
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45641
diff changeset
   191
    * changes: a ChangingFiles object
43255
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   192
    """
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   193
    cl = repo.changelog
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   194
    parents = cl.parentrevs
45672
f877b3628015 copies: return None instead of ChangingFiles when relevant
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45670
diff changeset
   195
    flags = cl.flags
f877b3628015 copies: return None instead of ChangingFiles when relevant
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45670
diff changeset
   196
f877b3628015 copies: return None instead of ChangingFiles when relevant
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45670
diff changeset
   197
    HASCOPIESINFO = flagutil.REVIDX_HASCOPIESINFO
43255
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   198
45640
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   199
    changelogrevision = cl.changelogrevision
43257
675c776fbcd1 sidedatacopies: directly fetch copies information from sidedata
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43256
diff changeset
   200
46159
929054848d6c copies: properly match result during changeset centric copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46158
diff changeset
   201
    if rustmod is not None:
46061
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   202
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   203
        def revinfo(rev):
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   204
            p1, p2 = parents(rev)
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   205
            if flags(rev) & HASCOPIESINFO:
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   206
                raw = changelogrevision(rev)._sidedata.get(sidedatamod.SD_FILES)
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   207
            else:
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   208
                raw = None
46150
a132aa5979ec copies: no longer cache the ChangedFiles during copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46149
diff changeset
   209
            return (p1, p2, raw)
46061
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   210
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   211
    else:
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   212
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   213
        def revinfo(rev):
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   214
            p1, p2 = parents(rev)
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   215
            if flags(rev) & HASCOPIESINFO:
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   216
                changes = changelogrevision(rev).changes
46150
a132aa5979ec copies: no longer cache the ChangedFiles during copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46149
diff changeset
   217
            else:
a132aa5979ec copies: no longer cache the ChangedFiles during copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46149
diff changeset
   218
                changes = None
a132aa5979ec copies: no longer cache the ChangedFiles during copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46149
diff changeset
   219
            return (p1, p2, changes)
43255
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   220
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   221
    return revinfo
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   222
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   223
45907
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   224
def cached_is_ancestor(is_ancestor):
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   225
    """return a cached version of is_ancestor"""
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   226
    cache = {}
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   227
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   228
    def _is_ancestor(anc, desc):
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   229
        if anc > desc:
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   230
            return False
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   231
        elif anc == desc:
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   232
            return True
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   233
        key = (anc, desc)
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   234
        ret = cache.get(key)
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   235
        if ret is None:
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   236
            ret = cache[key] = is_ancestor(anc, desc)
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   237
        return ret
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   238
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   239
    return _is_ancestor
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   240
06b64fabf91c copies: cache the ancestor checking call when tracing copy
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45821
diff changeset
   241
41765
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   242
def _changesetforwardcopies(a, b, match):
46114
59fa3890d40a node: import symbols explicitly
Joerg Sonnenberger <joerg@bec.de>
parents: 46110
diff changeset
   243
    if a.rev() in (nullrev, b.rev()):
41765
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   244
        return {}
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   245
43256
00de32aa834e copies: use an unfiltered repository for the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43255
diff changeset
   246
    repo = a.repo().unfiltered()
43255
b8d60845fa5d copies: extract data extraction into a `revinfo` function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43254
diff changeset
   247
41765
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   248
    cl = repo.changelog
45987
8b99c473aae2 copies-rust: move is_ancestor caching within the rust code
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45977
diff changeset
   249
    isancestor = cl.isancestorrev
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   250
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   251
    # To track rename from "A" to B, we need to gather all parent → children
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   252
    # edges that are contains in `::B` but not in `::A`.
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   253
    #
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   254
    #
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   255
    # To do so, we need to gather all revisions exclusive¹ to "B" (ie¹: `::b -
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   256
    # ::a`) and also all the "roots point", ie the parents of the exclusive set
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   257
    # that belong to ::a. These are exactly all the revisions needed to express
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   258
    # the parent → children we need to combine.
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   259
    #
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   260
    # [1] actually, we need to gather all the edges within `(::a)::b`, ie:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   261
    # excluding paths that leads to roots that are not ancestors of `a`. We
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   262
    # keep this out of the explanation because it is hard enough without this special case..
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   263
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   264
    parents = cl._uncheckedparentrevs
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   265
    graph_roots = (nullrev, nullrev)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   266
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   267
    ancestors = cl.ancestors([a.rev()], inclusive=True)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   268
    revs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()])
43299
83bb1e89ab9b copies: compute the exact set of revision to walk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43297
diff changeset
   269
    roots = set()
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   270
    has_graph_roots = False
46627
47557ea79fc7 copies-rust: move CPU-heavy Rust processing into a child thread
Simon Sapin <simon.sapin@octobus.net>
parents: 46613
diff changeset
   271
    multi_thread = repo.ui.configbool(b'devel', b'copy-tracing.multi-thread')
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   272
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   273
    # iterate over `only(B, A)`
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   274
    for r in revs:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   275
        ps = parents(r)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   276
        if ps == graph_roots:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   277
            has_graph_roots = True
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   278
        else:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   279
            p1, p2 = ps
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   280
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   281
            # find all the "root points" (see larger comment above)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   282
            if p1 != nullrev and p1 in ancestors:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   283
                roots.add(p1)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   284
            if p2 != nullrev and p2 in ancestors:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   285
                roots.add(p2)
43299
83bb1e89ab9b copies: compute the exact set of revision to walk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43297
diff changeset
   286
    if not roots:
83bb1e89ab9b copies: compute the exact set of revision to walk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43297
diff changeset
   287
        # no common revision to track copies from
83bb1e89ab9b copies: compute the exact set of revision to walk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43297
diff changeset
   288
        return {}
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   289
    if has_graph_roots:
48515
19e6446cea11 copies: fix some documentation typos
Matt Harbison <matt_harbison@yahoo.com>
parents: 48514
diff changeset
   290
        # this deal with the special case mentioned in the [1] footnotes. We
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   291
        # must filter out revisions that leads to non-common graphroots.
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   292
        roots = list(roots)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   293
        m = min(roots)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   294
        h = [b.rev()]
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   295
        roots_to_head = cl.reachableroots(m, h, roots, includepath=True)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   296
        roots_to_head = set(roots_to_head)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   297
        revs = [r for r in revs if r in roots_to_head]
45639
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   298
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   299
    if repo.filecopiesmode == b'changeset-sidedata':
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   300
        # When using side-data, we will process the edges "from" the children.
48515
19e6446cea11 copies: fix some documentation typos
Matt Harbison <matt_harbison@yahoo.com>
parents: 48514
diff changeset
   301
        # We iterate over the children, gathering previous collected data for
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   302
        # the parents. Do know when the parents data is no longer necessary, we
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   303
        # keep a counter of how many children each revision has.
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   304
        #
48515
19e6446cea11 copies: fix some documentation typos
Matt Harbison <matt_harbison@yahoo.com>
parents: 48514
diff changeset
   305
        # An interesting property of `children_count` is that it only contains
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   306
        # revision that will be relevant for a edge of the graph. So if a
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   307
        # children has parent not in `children_count`, that edges should not be
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   308
        # processed.
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   309
        children_count = dict((r, 0) for r in roots)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   310
        for r in revs:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   311
            for p in cl.parentrevs(r):
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   312
                if p == nullrev:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   313
                    continue
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   314
                children_count[r] = 0
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   315
                if p in children_count:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   316
                    children_count[p] += 1
46061
e0313b0a6f7e copies-rust: parse the changed-file sidedata directly in rust
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46040
diff changeset
   317
        revinfo = _revinfo_getter(repo, match)
47469
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   318
        with repo.changelog.reading():
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   319
            return _combine_changeset_copies(
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   320
                revs,
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   321
                children_count,
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   322
                b.rev(),
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   323
                revinfo,
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   324
                match,
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   325
                isancestor,
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   326
                multi_thread,
5fa083a5ff04 copies: Keep changelog sidedata file open during copy tracing
Simon Sapin <simon.sapin@octobus.net>
parents: 47055
diff changeset
   327
            )
45639
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   328
    else:
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   329
        # When not using side-data, we will process the edges "from" the parent.
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   330
        # so we need a full mapping of the parent -> children relation.
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   331
        children = dict((r, []) for r in roots)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   332
        for r in revs:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   333
            for p in cl.parentrevs(r):
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   334
                if p == nullrev:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   335
                    continue
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   336
                children[r] = []
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   337
                if p in children:
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   338
                    children[p].append(r)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   339
        x = revs.pop()
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   340
        assert x == b.rev()
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   341
        revs.extend(roots)
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   342
        revs.sort()
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   343
45640
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   344
        revinfo = _revinfo_getter_extra(repo)
45639
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   345
        return _combine_changeset_copies_extra(
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   346
            revs, children, b.rev(), revinfo, match, isancestor
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   347
        )
43806
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   348
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   349
45627
fb000408bca5 copies: rename some function to the new naming scheme
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45014
diff changeset
   350
def _combine_changeset_copies(
46627
47557ea79fc7 copies-rust: move CPU-heavy Rust processing into a child thread
Simon Sapin <simon.sapin@octobus.net>
parents: 46613
diff changeset
   351
    revs, children_count, targetrev, revinfo, match, isancestor, multi_thread
44858
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   352
):
43806
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   353
    """combine the copies information for each item of iterrevs
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   354
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   355
    revs: sorted iterable of revision to visit
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   356
    children_count: a {parent: <number-of-relevant-children>} mapping.
43806
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   357
    targetrev: the final copies destination revision (not in iterrevs)
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   358
    revinfo(rev): a function that return (p1, p2, p1copies, p2copies, removed)
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   359
    match: a matcher
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   360
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   361
    It returns the aggregated copies information for `targetrev`.
421ea5772039 copies: split the combination of the copies mapping in its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43805
diff changeset
   362
    """
45977
a66568f20ddc copies: use the rust code for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45957
diff changeset
   363
a66568f20ddc copies: use the rust code for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45957
diff changeset
   364
    alwaysmatch = match.always()
a66568f20ddc copies: use the rust code for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45957
diff changeset
   365
46159
929054848d6c copies: properly match result during changeset centric copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46158
diff changeset
   366
    if rustmod is not None:
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   367
        final_copies = rustmod.combine_changeset_copies(
46627
47557ea79fc7 copies-rust: move CPU-heavy Rust processing into a child thread
Simon Sapin <simon.sapin@octobus.net>
parents: 46613
diff changeset
   368
            list(revs), children_count, targetrev, revinfo, multi_thread
45977
a66568f20ddc copies: use the rust code for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45957
diff changeset
   369
        )
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   370
    else:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   371
        isancestor = cached_is_ancestor(isancestor)
46148
70a9eb899637 copies: document the current algorithm step
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46114
diff changeset
   372
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   373
        all_copies = {}
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   374
        # iterate over all the "children" side of copy tracing "edge"
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   375
        for current_rev in revs:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   376
            p1, p2, changes = revinfo(current_rev)
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   377
            current_copies = None
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   378
            # iterate over all parents to chain the existing data with the
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   379
            # data from the parent → child edge.
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   380
            for parent, parent_rev in ((1, p1), (2, p2)):
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   381
                if parent_rev == nullrev:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   382
                    continue
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   383
                remaining_children = children_count.get(parent_rev)
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   384
                if remaining_children is None:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   385
                    continue
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   386
                remaining_children -= 1
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   387
                children_count[parent_rev] = remaining_children
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   388
                if remaining_children:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   389
                    copies = all_copies.get(parent_rev, None)
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   390
                else:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   391
                    copies = all_copies.pop(parent_rev, None)
46148
70a9eb899637 copies: document the current algorithm step
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46114
diff changeset
   392
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   393
                if copies is None:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   394
                    # this is a root
46184
cb8b2ee89a5d copies: stop attempt to avoid extra dict copies around branching
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46183
diff changeset
   395
                    newcopies = copies = {}
cb8b2ee89a5d copies: stop attempt to avoid extra dict copies around branching
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46183
diff changeset
   396
                elif remaining_children:
cb8b2ee89a5d copies: stop attempt to avoid extra dict copies around branching
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46183
diff changeset
   397
                    newcopies = copies.copy()
cb8b2ee89a5d copies: stop attempt to avoid extra dict copies around branching
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46183
diff changeset
   398
                else:
cb8b2ee89a5d copies: stop attempt to avoid extra dict copies around branching
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46183
diff changeset
   399
                    newcopies = copies
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   400
                # chain the data in the edge with the existing data
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   401
                if changes is not None:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   402
                    childcopies = {}
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   403
                    if parent == 1:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   404
                        childcopies = changes.copied_from_p1
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   405
                    elif parent == 2:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   406
                        childcopies = changes.copied_from_p2
46148
70a9eb899637 copies: document the current algorithm step
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46114
diff changeset
   407
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   408
                    if childcopies:
46149
294d5aca4ff5 copies: iterate over children directly (instead of parents)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46148
diff changeset
   409
                        newcopies = copies.copy()
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
   410
                        for dest, source in childcopies.items():
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   411
                            prev = copies.get(source)
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   412
                            if prev is not None and prev[1] is not None:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   413
                                source = prev[1]
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   414
                            newcopies[dest] = (current_rev, source)
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   415
                        assert newcopies is not copies
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   416
                    if changes.removed:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   417
                        for f in changes.removed:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   418
                            if f in newcopies:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   419
                                if newcopies is copies:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   420
                                    # copy on write to avoid affecting potential other
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   421
                                    # branches.  when there are no other branches, this
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   422
                                    # could be avoided.
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   423
                                    newcopies = copies.copy()
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   424
                                newcopies[f] = (current_rev, None)
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   425
                # check potential need to combine the data from another parent (for
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   426
                # that child). See comment below for details.
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   427
                if current_copies is None:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   428
                    current_copies = newcopies
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   429
                else:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   430
                    # we are the second parent to work on c, we need to merge our
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   431
                    # work with the other.
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   432
                    #
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   433
                    # In case of conflict, parent 1 take precedence over parent 2.
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   434
                    # This is an arbitrary choice made anew when implementing
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   435
                    # changeset based copies. It was made without regards with
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   436
                    # potential filelog related behavior.
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   437
                    assert parent == 2
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   438
                    current_copies = _merge_copies_dict(
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   439
                        newcopies,
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   440
                        current_copies,
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   441
                        isancestor,
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   442
                        changes,
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   443
                        current_rev,
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   444
                    )
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   445
            all_copies[current_rev] = current_copies
46148
70a9eb899637 copies: document the current algorithm step
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46114
diff changeset
   446
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   447
        # filter out internal details and return a {dest: source mapping}
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   448
        final_copies = {}
48516
79b904313357 pytype: stop excluding copies.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 48515
diff changeset
   449
79b904313357 pytype: stop excluding copies.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 48515
diff changeset
   450
        targetrev_items = all_copies[targetrev]
79b904313357 pytype: stop excluding copies.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 48515
diff changeset
   451
        assert targetrev_items is not None  # help pytype
79b904313357 pytype: stop excluding copies.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 48515
diff changeset
   452
79b904313357 pytype: stop excluding copies.py
Matt Harbison <matt_harbison@yahoo.com>
parents: 48515
diff changeset
   453
        for dest, (tt, source) in targetrev_items.items():
46158
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   454
            if source is not None:
1fcfff09cac5 copies: avoid early return in _combine_changeset_copies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46150
diff changeset
   455
                final_copies[dest] = source
46159
929054848d6c copies: properly match result during changeset centric copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46158
diff changeset
   456
    if not alwaysmatch:
929054848d6c copies: properly match result during changeset centric copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46158
diff changeset
   457
        for filename in list(final_copies.keys()):
929054848d6c copies: properly match result during changeset centric copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46158
diff changeset
   458
            if not match(filename):
929054848d6c copies: properly match result during changeset centric copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46158
diff changeset
   459
                del final_copies[filename]
44858
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   460
    return final_copies
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   461
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   462
46161
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   463
# constant to decide which side to pick with _merge_copies_dict
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   464
PICK_MINOR = 0
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   465
PICK_MAJOR = 1
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   466
PICK_EITHER = 2
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   467
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   468
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   469
def _merge_copies_dict(minor, major, isancestor, changes, current_merge):
44858
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   470
    """merge two copies-mapping together, minor and major
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   471
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   472
    In case of conflict, value from "major" will be picked.
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   473
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   474
    - `isancestors(low_rev, high_rev)`: callable return True if `low_rev` is an
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   475
                                        ancestors of `high_rev`,
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   476
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   477
    - `ismerged(path)`: callable return True if `path` have been merged in the
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   478
                        current revision,
46001
f9f8d8aa9a92 copies: clarify the return of _merge_copies_dict
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46000
diff changeset
   479
f9f8d8aa9a92 copies: clarify the return of _merge_copies_dict
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46000
diff changeset
   480
    return the resulting dict (in practice, the "minor" object, updated)
44858
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   481
    """
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   482
    for dest, value in major.items():
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   483
        other = minor.get(dest)
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   484
        if other is None:
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   485
            minor[dest] = value
45f3f35cefe7 copies: fix the changeset based algorithm regarding merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   486
        else:
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   487
            pick, overwrite = _compare_values(
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   488
                changes, isancestor, dest, other, value
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   489
            )
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   490
            if overwrite:
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   491
                if pick == PICK_MAJOR:
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   492
                    minor[dest] = (current_merge, value[1])
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   493
                else:
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   494
                    minor[dest] = (current_merge, other[1])
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   495
            elif pick == PICK_MAJOR:
45670
a8fb29b05f92 salvaged: properly deal with salvaged file during copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45642
diff changeset
   496
                minor[dest] = value
46001
f9f8d8aa9a92 copies: clarify the return of _merge_copies_dict
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46000
diff changeset
   497
    return minor
41765
49ad315b39ee copies: do copy tracing based on ctx.p[12]copies() if configured
Martin von Zweigbergk <martinvonz@google.com>
parents: 41763
diff changeset
   498
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   499
46162
6b9d65298484 copies: rename value/other variable to minor/major for clarity
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46161
diff changeset
   500
def _compare_values(changes, isancestor, dest, minor, major):
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   501
    """compare two value within a _merge_copies_dict loop iteration
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   502
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   503
    return (pick, overwrite).
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   504
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   505
    - pick is one of PICK_MINOR, PICK_MAJOR or PICK_EITHER
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   506
    - overwrite is True if pick is a return of an ambiguity that needs resolution.
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   507
    """
46183
ee63c1173c1b copies: deal with the "same revision" special case earlier
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46162
diff changeset
   508
    major_tt, major_value = major
ee63c1173c1b copies: deal with the "same revision" special case earlier
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46162
diff changeset
   509
    minor_tt, minor_value = minor
46161
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   510
46183
ee63c1173c1b copies: deal with the "same revision" special case earlier
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46162
diff changeset
   511
    if major_tt == minor_tt:
ee63c1173c1b copies: deal with the "same revision" special case earlier
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46162
diff changeset
   512
        # if it comes from the same revision it must be the same value
ee63c1173c1b copies: deal with the "same revision" special case earlier
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46162
diff changeset
   513
        assert major_value == minor_value
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   514
        return PICK_EITHER, False
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   515
    elif (
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   516
        changes is not None
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   517
        and minor_value is not None
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   518
        and major_value is None
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   519
        and dest in changes.salvaged
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   520
    ):
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   521
        # In this case, a deletion was reverted, the "alive" value overwrite
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   522
        # the deleted one.
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   523
        return PICK_MINOR, True
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   524
    elif (
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   525
        changes is not None
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   526
        and major_value is not None
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   527
        and minor_value is None
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   528
        and dest in changes.salvaged
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   529
    ):
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   530
        # In this case, a deletion was reverted, the "alive" value overwrite
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   531
        # the deleted one.
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   532
        return PICK_MAJOR, True
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   533
    elif isancestor(minor_tt, major_tt):
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   534
        if changes is not None and dest in changes.merged:
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   535
            # change to dest happened on the branch without copy-source change,
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   536
            # so both source are valid and "major" wins.
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   537
            return PICK_MAJOR, True
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   538
        else:
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   539
            return PICK_MAJOR, False
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   540
    elif isancestor(major_tt, minor_tt):
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   541
        if changes is not None and dest in changes.merged:
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   542
            # change to dest happened on the branch without copy-source change,
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   543
            # so both source are valid and "major" wins.
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   544
            return PICK_MAJOR, True
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   545
        else:
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   546
            return PICK_MINOR, False
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   547
    elif minor_value is None:
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   548
        # in case of conflict, the "alive" side wins.
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   549
        return PICK_MAJOR, True
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   550
    elif major_value is None:
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   551
        # in case of conflict, the "alive" side wins.
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   552
        return PICK_MINOR, True
46606
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   553
    else:
c692384bb559 copies: rearrange all value comparison conditional
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46482
diff changeset
   554
        # in case of conflict where both side are alive, major wins.
46607
c19c662097e1 copies: detect case when a merge decision overwrite previous data
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46606
diff changeset
   555
        return PICK_MAJOR, True
46161
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   556
3a0c41336961 copies: extract value comparison in the python copy tracing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46159
diff changeset
   557
45640
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   558
def _revinfo_getter_extra(repo):
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   559
    """return a function that return multiple data given a <rev>"i
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   560
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   561
    * p1: revision number of first parent
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   562
    * p2: revision number of first parent
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   563
    * p1copies: mapping of copies from p1
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   564
    * p2copies: mapping of copies from p2
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   565
    * removed: a list of removed files
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   566
    * ismerged: a callback to know if file was merged in that revision
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   567
    """
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   568
    cl = repo.changelog
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   569
    parents = cl.parentrevs
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   570
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   571
    def get_ismerged(rev):
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   572
        ctx = repo[rev]
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   573
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   574
        def ismerged(path):
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   575
            if path not in ctx.files():
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   576
                return False
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   577
            fctx = ctx[path]
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   578
            parents = fctx._filelog.parents(fctx._filenode)
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   579
            nb_parents = 0
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   580
            for n in parents:
47055
d55b71393907 node: replace nullid and friends with nodeconstants class
Joerg Sonnenberger <joerg@bec.de>
parents: 46843
diff changeset
   581
                if n != repo.nullid:
45640
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   582
                    nb_parents += 1
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   583
            return nb_parents >= 2
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   584
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   585
        return ismerged
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   586
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   587
    def revinfo(rev):
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   588
        p1, p2 = parents(rev)
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   589
        ctx = repo[rev]
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   590
        p1copies, p2copies = ctx._copies
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   591
        removed = ctx.filesremoved()
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   592
        return p1, p2, p1copies, p2copies, removed, get_ismerged(rev)
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   593
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   594
    return revinfo
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   595
4f876e6b30fa copies: use dedicated `_revinfo_getter` function and call
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45639
diff changeset
   596
45639
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   597
def _combine_changeset_copies_extra(
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   598
    revs, children, targetrev, revinfo, match, isancestor
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   599
):
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   600
    """version of `_combine_changeset_copies` that works with the Google
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   601
    specific "extra" based storage for copy information"""
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   602
    all_copies = {}
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   603
    alwaysmatch = match.always()
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   604
    for r in revs:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   605
        copies = all_copies.pop(r, None)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   606
        if copies is None:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   607
            # this is a root
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   608
            copies = {}
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   609
        for i, c in enumerate(children[r]):
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   610
            p1, p2, p1copies, p2copies, removed, ismerged = revinfo(c)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   611
            if r == p1:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   612
                parent = 1
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   613
                childcopies = p1copies
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   614
            else:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   615
                assert r == p2
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   616
                parent = 2
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   617
                childcopies = p2copies
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   618
            if not alwaysmatch:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   619
                childcopies = {
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   620
                    dst: src for dst, src in childcopies.items() if match(dst)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   621
                }
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   622
            newcopies = copies
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   623
            if childcopies:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   624
                newcopies = copies.copy()
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
   625
                for dest, source in childcopies.items():
45639
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   626
                    prev = copies.get(source)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   627
                    if prev is not None and prev[1] is not None:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   628
                        source = prev[1]
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   629
                    newcopies[dest] = (c, source)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   630
                assert newcopies is not copies
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   631
            for f in removed:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   632
                if f in newcopies:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   633
                    if newcopies is copies:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   634
                        # copy on write to avoid affecting potential other
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   635
                        # branches.  when there are no other branches, this
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   636
                        # could be avoided.
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   637
                        newcopies = copies.copy()
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   638
                    newcopies[f] = (c, None)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   639
            othercopies = all_copies.get(c)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   640
            if othercopies is None:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   641
                all_copies[c] = newcopies
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   642
            else:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   643
                # we are the second parent to work on c, we need to merge our
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   644
                # work with the other.
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   645
                #
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   646
                # In case of conflict, parent 1 take precedence over parent 2.
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   647
                # This is an arbitrary choice made anew when implementing
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   648
                # changeset based copies. It was made without regards with
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   649
                # potential filelog related behavior.
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   650
                if parent == 1:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   651
                    _merge_copies_dict_extra(
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   652
                        othercopies, newcopies, isancestor, ismerged
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   653
                    )
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   654
                else:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   655
                    _merge_copies_dict_extra(
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   656
                        newcopies, othercopies, isancestor, ismerged
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   657
                    )
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   658
                    all_copies[c] = newcopies
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   659
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   660
    final_copies = {}
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   661
    for dest, (tt, source) in all_copies[targetrev].items():
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   662
        if source is not None:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   663
            final_copies[dest] = source
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   664
    return final_copies
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   665
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   666
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   667
def _merge_copies_dict_extra(minor, major, isancestor, ismerged):
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   668
    """version of `_merge_copies_dict` that works with the Google
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   669
    specific "extra" based storage for copy information"""
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   670
    for dest, value in major.items():
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   671
        other = minor.get(dest)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   672
        if other is None:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   673
            minor[dest] = value
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   674
        else:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   675
            new_tt = value[0]
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   676
            other_tt = other[0]
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   677
            if value[1] == other[1]:
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   678
                continue
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   679
            # content from "major" wins, unless it is older
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   680
            # than the branch point or there is a merge
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   681
            if (
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   682
                new_tt == other_tt
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   683
                or not isancestor(new_tt, other_tt)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   684
                or ismerged(dest)
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   685
            ):
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   686
                minor[dest] = value
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   687
ad6ebb6f0dfe copies: make two version of the changeset centric algorithm
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45627
diff changeset
   688
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   689
def _forwardcopies(a, b, base=None, match=None):
35429
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35428
diff changeset
   690
    """find {dst@b: src@a} copy mapping where a is an ancestor of b"""
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35428
diff changeset
   691
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   692
    if base is None:
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   693
        base = a
40422
873f3682c8af narrow: make copies.pathcopies() filter with narrowspec again
Martin von Zweigbergk <martinvonz@google.com>
parents: 40077
diff changeset
   694
    match = a.repo().narrowmatch(match)
35429
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35428
diff changeset
   695
    # check for working copy
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35428
diff changeset
   696
    if b.rev() is None:
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   697
        cm = _committedforwardcopies(a, b.p1(), base, match)
35430
e54f02ec6a05 copies: group wdir-handling in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 35429
diff changeset
   698
        # combine copies from dirstate if necessary
42593
11ceb1b8fd74 copies: inline _chainandfilter() to prepare for next patch
Martin von Zweigbergk <martinvonz@google.com>
parents: 42592
diff changeset
   699
        copies = _chain(cm, _dirstatecopies(b._repo, match))
42592
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   700
    else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   701
        copies = _committedforwardcopies(a, b, base, match)
42592
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   702
    return copies
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   703
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   704
41762
3158cb74fbca copies: make _backwardrenames() filter out copies by destination
Martin von Zweigbergk <martinvonz@google.com>
parents: 41761
diff changeset
   705
def _backwardrenames(a, b, match):
46687
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   706
    """find renames from a to b"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   707
    if a._repo.ui.config(b'experimental', b'copytrace') == b'off':
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   708
        return {}
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   709
46687
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   710
    # We don't want to pass in "match" here, since that would filter
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   711
    # the destination by it. Since we're reversing the copies, we want
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   712
    # to filter the source instead.
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   713
    copies = _forwardcopies(b, a)
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   714
    return _reverse_renames(copies, a, match)
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   715
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   716
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   717
def _reverse_renames(copies, dst, match):
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   718
    """given copies to context 'dst', finds renames from that context"""
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   719
    # Even though we're not taking copies into account, 1:n rename situations
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   720
    # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   721
    # arbitrarily pick one of the renames.
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   722
    r = {}
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
   723
    for k, v in sorted(copies.items()):
41762
3158cb74fbca copies: make _backwardrenames() filter out copies by destination
Martin von Zweigbergk <martinvonz@google.com>
parents: 41761
diff changeset
   724
        if match and not match(v):
3158cb74fbca copies: make _backwardrenames() filter out copies by destination
Martin von Zweigbergk <martinvonz@google.com>
parents: 41761
diff changeset
   725
            continue
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   726
        # remove copies
46687
eca88f5fbcb2 copies: extract function _backwardcopies() for reversing renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 46673
diff changeset
   727
        if v in dst:
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   728
            continue
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   729
        r[v] = k
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   730
    return r
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   731
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   732
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   733
def pathcopies(x, y, match=None):
35428
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35427
diff changeset
   734
    """find {dst@y: src@x} copy mapping for directed compare"""
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   735
    repo = x._repo
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   736
    debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies')
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   737
    if debug:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   738
        repo.ui.debug(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   739
            b'debug.copies: searching copies from %s to %s\n' % (x, y)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   740
        )
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   741
    if x == y or not x or not y:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   742
        return {}
44323
30862e226339 copies: avoid filtering by short-circuit dirstate-only copies earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 44299
diff changeset
   743
    if y.rev() is None and x == y.p1():
30862e226339 copies: avoid filtering by short-circuit dirstate-only copies earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 44299
diff changeset
   744
        if debug:
30862e226339 copies: avoid filtering by short-circuit dirstate-only copies earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 44299
diff changeset
   745
            repo.ui.debug(b'debug.copies: search mode: dirstate\n')
30862e226339 copies: avoid filtering by short-circuit dirstate-only copies earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 44299
diff changeset
   746
        # short-circuit to avoid issues with merge states
30862e226339 copies: avoid filtering by short-circuit dirstate-only copies earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 44299
diff changeset
   747
        return _dirstatecopies(repo, match)
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   748
    a = y.ancestor(x)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   749
    if a == x:
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   750
        if debug:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   751
            repo.ui.debug(b'debug.copies: search mode: forward\n')
42592
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   752
        copies = _forwardcopies(x, y, match=match)
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   753
    elif a == y:
40058
25b2868206e2 copies: add a devel debug mode to trace what copy tracing does
Boris Feld <boris.feld@octobus.net>
parents: 39967
diff changeset
   754
        if debug:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   755
            repo.ui.debug(b'debug.copies: search mode: backward\n')
42592
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   756
        copies = _backwardrenames(x, y, match=match)
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   757
    else:
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   758
        if debug:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   759
            repo.ui.debug(b'debug.copies: search mode: combined\n')
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   760
        base = None
46114
59fa3890d40a node: import symbols explicitly
Joerg Sonnenberger <joerg@bec.de>
parents: 46110
diff changeset
   761
        if a.rev() != nullrev:
42595
819712deac69 copies: follow copies across merge base without source file (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42594
diff changeset
   762
            base = x
46688
324ded1aa2ab copies: inline _backwardrenames() in pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 46687
diff changeset
   763
        x_copies = _forwardcopies(a, x)
324ded1aa2ab copies: inline _backwardrenames() in pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 46687
diff changeset
   764
        y_copies = _forwardcopies(a, y, base, match=match)
46689
2803f94b7431 copies: filter out copies grafted from another branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 46688
diff changeset
   765
        same_keys = set(x_copies) & set(y_copies)
2803f94b7431 copies: filter out copies grafted from another branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 46688
diff changeset
   766
        for k in same_keys:
2803f94b7431 copies: filter out copies grafted from another branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 46688
diff changeset
   767
            if x_copies.get(k) == y_copies.get(k):
2803f94b7431 copies: filter out copies grafted from another branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 46688
diff changeset
   768
                del x_copies[k]
2803f94b7431 copies: filter out copies grafted from another branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 46688
diff changeset
   769
                del y_copies[k]
46688
324ded1aa2ab copies: inline _backwardrenames() in pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 46687
diff changeset
   770
        x_backward_renames = _reverse_renames(x_copies, x, match)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   771
        copies = _chain(
46688
324ded1aa2ab copies: inline _backwardrenames() in pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 46687
diff changeset
   772
            x_backward_renames,
324ded1aa2ab copies: inline _backwardrenames() in pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 46687
diff changeset
   773
            y_copies,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   774
        )
42594
d013099c551b copies: filter invalid copies only at end of pathcopies() (issue6163)
Martin von Zweigbergk <martinvonz@google.com>
parents: 42593
diff changeset
   775
    _filter(x, y, copies)
42592
a48f6f18dc6d copies: remove most early returns from pathcopies() and _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42591
diff changeset
   776
    return copies
15774
0bd17a4bed88 copies: split the copies api for "normal" and merge cases (API)
Matt Mackall <mpm@selenic.com>
parents: 14494
diff changeset
   777
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   778
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   779
def mergecopies(repo, c1, c2, base):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   780
    """
42118
967c098eed33 copies: move comment about implementation of mergecopies() to end
Martin von Zweigbergk <martinvonz@google.com>
parents: 42115
diff changeset
   781
    Finds moves and copies between context c1 and c2 that are relevant for
34095
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   782
    merging. 'base' will be used as the merge base.
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   783
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   784
    Copytracing is used in commands like rebase, merge, unshelve, etc to merge
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   785
    files that were moved/ copied in one merge parent and modified in another.
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   786
    For example:
33843
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   787
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   788
    o          ---> 4 another commit
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   789
    |
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   790
    |   o      ---> 3 commit that modifies a.txt
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   791
    |  /
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   792
    o /        ---> 2 commit that moves a.txt to b.txt
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   793
    |/
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   794
    o          ---> 1 merge base
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   795
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   796
    If we try to rebase revision 3 on revision 4, since there is no a.txt in
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   797
    revision 4, and if user have copytrace disabled, we prints the following
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   798
    message:
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   799
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   800
    ```other changed <file> which local deleted```
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32663
diff changeset
   801
44274
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   802
    Returns a tuple where:
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   803
44274
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   804
    "branch_copies" an instance of branch_copies.
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   805
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   806
    "diverge" is a mapping of source name -> list of destination names
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   807
    for divergent renames.
16794
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   808
42118
967c098eed33 copies: move comment about implementation of mergecopies() to end
Martin von Zweigbergk <martinvonz@google.com>
parents: 42115
diff changeset
   809
    This function calls different copytracing algorithms based on config.
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   810
    """
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   811
    # avoid silly behavior for update from empty dir
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
   812
    if not c1 or not c2 or c1 == c2:
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   813
        return branch_copies(), branch_copies(), {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   814
41761
012f695546aa copies: respect narrowmatcher in "parent -> working dir" case
Martin von Zweigbergk <martinvonz@google.com>
parents: 41735
diff changeset
   815
    narrowmatch = c1.repo().narrowmatch()
012f695546aa copies: respect narrowmatcher in "parent -> working dir" case
Martin von Zweigbergk <martinvonz@google.com>
parents: 41735
diff changeset
   816
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   817
    # avoid silly behavior for parent -> working dir
13878
a8d13ee0ce68 misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents: 12683
diff changeset
   818
    if c2.node() is None and c1.node() == repo.dirstate.p1():
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   819
        return (
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   820
            branch_copies(_dirstatecopies(repo, narrowmatch)),
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   821
            branch_copies(),
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   822
            {},
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   823
        )
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   824
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   825
    copytracing = repo.ui.config(b'experimental', b'copytrace')
42255
d8ca7b99fc51 copies: move check for experimental.copytrace==<falsy> earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 42254
diff changeset
   826
    if stringutil.parsebool(copytracing) is False:
d8ca7b99fc51 copies: move check for experimental.copytrace==<falsy> earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 42254
diff changeset
   827
        # stringutil.parsebool() returns None when it is unable to parse the
d8ca7b99fc51 copies: move check for experimental.copytrace==<falsy> earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 42254
diff changeset
   828
        # value, so we should rely on making sure copytracing is on such cases
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   829
        return branch_copies(), branch_copies(), {}
34095
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   830
42256
a6be3af3a397 copies: ignore heuristics copytracing when using changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 42255
diff changeset
   831
    if usechangesetcentricalgo(repo):
a6be3af3a397 copies: ignore heuristics copytracing when using changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 42255
diff changeset
   832
        # The heuristics don't make sense when we need changeset-centric algos
a6be3af3a397 copies: ignore heuristics copytracing when using changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 42255
diff changeset
   833
        return _fullcopytracing(repo, c1, c2, base)
a6be3af3a397 copies: ignore heuristics copytracing when using changeset-centric algos
Martin von Zweigbergk <martinvonz@google.com>
parents: 42255
diff changeset
   834
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   835
    # Copy trace disabling is explicitly below the node == p1 logic above
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   836
    # because the logic above is required for a simple copy to be kept across a
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   837
    # rebase.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   838
    if copytracing == b'heuristics':
34367
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34355
diff changeset
   839
        # Do full copytracing if only non-public revisions are involved as
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34355
diff changeset
   840
        # that will be fast enough and will also cover the copies which could
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34355
diff changeset
   841
        # be missed by heuristics
34318
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34295
diff changeset
   842
        if _isfullcopytraceable(repo, c1, base):
34295
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34191
diff changeset
   843
            return _fullcopytracing(repo, c1, c2, base)
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
   844
        return _heuristicscopytracing(repo, c1, c2, base)
34095
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   845
    else:
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   846
        return _fullcopytracing(repo, c1, c2, base)
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   847
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   848
34318
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34295
diff changeset
   849
def _isfullcopytraceable(repo, c1, base):
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
   850
    """Checks that if base, source and destination are all no-public branches,
34367
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34355
diff changeset
   851
    if yes let's use the full copytrace algorithm for increased capabilities
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34355
diff changeset
   852
    since it will be fast enough.
34516
e79b3611223b copies: add docs for config `experimental.copytrace.sourcecommitlimit`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34367
diff changeset
   853
e79b3611223b copies: add docs for config `experimental.copytrace.sourcecommitlimit`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34367
diff changeset
   854
    `experimental.copytrace.sourcecommitlimit` can be used to set a limit for
e79b3611223b copies: add docs for config `experimental.copytrace.sourcecommitlimit`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34367
diff changeset
   855
    number of changesets from c1 to base such that if number of changesets are
e79b3611223b copies: add docs for config `experimental.copytrace.sourcecommitlimit`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34367
diff changeset
   856
    more than the limit, full copytracing algorithm won't be used.
34295
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34191
diff changeset
   857
    """
34318
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34295
diff changeset
   858
    if c1.rev() is None:
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34295
diff changeset
   859
        c1 = c1.p1()
34367
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34355
diff changeset
   860
    if c1.mutable() and base.mutable():
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   861
        sourcecommitlimit = repo.ui.configint(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   862
            b'experimental', b'copytrace.sourcecommitlimit'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   863
        )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   864
        commits = len(repo.revs(b'%d::%d', base.rev(), c1.rev()))
34318
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34295
diff changeset
   865
        return commits < sourcecommitlimit
34295
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34191
diff changeset
   866
    return False
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34191
diff changeset
   867
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   868
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   869
def _checksinglesidecopies(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   870
    src, dsts1, m1, m2, mb, c2, base, copy, renamedelete
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   871
):
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   872
    if src not in m2:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   873
        # deleted on side 2
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   874
        if src not in m1:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   875
            # renamed on side 1, deleted on side 2
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   876
            renamedelete[src] = dsts1
44284
d0c3eead515a copies: fix crash when copy source is not in graft base
Martin von Zweigbergk <martinvonz@google.com>
parents: 44275
diff changeset
   877
    elif src not in mb:
d0c3eead515a copies: fix crash when copy source is not in graft base
Martin von Zweigbergk <martinvonz@google.com>
parents: 44275
diff changeset
   878
        # Work around the "short-circuit to avoid issues with merge states"
d0c3eead515a copies: fix crash when copy source is not in graft base
Martin von Zweigbergk <martinvonz@google.com>
parents: 44275
diff changeset
   879
        # thing in pathcopies(): pathcopies(x, y) can return a copy where the
d0c3eead515a copies: fix crash when copy source is not in graft base
Martin von Zweigbergk <martinvonz@google.com>
parents: 44275
diff changeset
   880
        # destination doesn't exist in y.
d0c3eead515a copies: fix crash when copy source is not in graft base
Martin von Zweigbergk <martinvonz@google.com>
parents: 44275
diff changeset
   881
        pass
44788
d452acc8cce8 flags: account for flag change when tracking rename relevant to merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   882
    elif mb[src] != m2[src] and not _related(c2[src], base[src]):
d452acc8cce8 flags: account for flag change when tracking rename relevant to merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   883
        return
d452acc8cce8 flags: account for flag change when tracking rename relevant to merge
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44323
diff changeset
   884
    elif mb[src] != m2[src] or mb.flags(src) != m2.flags(src):
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   885
        # modified on side 2
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   886
        for dst in dsts1:
44299
b4057d001760 merge: when rename was made on both sides, use ancestor as merge base
Martin von Zweigbergk <martinvonz@google.com>
parents: 44284
diff changeset
   887
            copy[dst] = src
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   888
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   889
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 49004
diff changeset
   890
class branch_copies:
44274
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   891
    """Information about copies made on one side of a merge/graft.
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   892
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   893
    "copy" is a mapping from destination name -> source name,
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   894
    where source is in c1 and destination is in c2 or vice-versa.
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   895
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   896
    "movewithdir" is a mapping from source name -> destination name,
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   897
    where the file at source present in one context but not the other
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   898
    needs to be moved to destination by the merge process, because the
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   899
    other context moved the directory it is in.
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   900
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   901
    "renamedelete" is a mapping of source name -> list of destination
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   902
    names for files deleted in c1 that were renamed in c2 or vice-versa.
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   903
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   904
    "dirmove" is a mapping of detected source dir -> destination dir renames.
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   905
    This is needed for handling changes to new files previously grafted into
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   906
    renamed directories.
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   907
    """
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   908
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   909
    def __init__(
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   910
        self, copy=None, renamedelete=None, dirmove=None, movewithdir=None
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   911
    ):
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   912
        self.copy = {} if copy is None else copy
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   913
        self.renamedelete = {} if renamedelete is None else renamedelete
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   914
        self.dirmove = {} if dirmove is None else dirmove
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   915
        self.movewithdir = {} if movewithdir is None else movewithdir
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   916
45014
cfd06649a1b8 copies: implement __repr__ on branch_copies for debugging
Martin von Zweigbergk <martinvonz@google.com>
parents: 44981
diff changeset
   917
    def __repr__(self):
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
   918
        return '<branch_copies\n  copy=%r\n  renamedelete=%r\n  dirmove=%r\n  movewithdir=%r\n>' % (
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
   919
            self.copy,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
   920
            self.renamedelete,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
   921
            self.dirmove,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
   922
            self.movewithdir,
45014
cfd06649a1b8 copies: implement __repr__ on branch_copies for debugging
Martin von Zweigbergk <martinvonz@google.com>
parents: 44981
diff changeset
   923
        )
cfd06649a1b8 copies: implement __repr__ on branch_copies for debugging
Martin von Zweigbergk <martinvonz@google.com>
parents: 44981
diff changeset
   924
44274
7f8bdee0034e copies: define a type to return from mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 44272
diff changeset
   925
34095
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   926
def _fullcopytracing(repo, c1, c2, base):
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
   927
    """The full copytracing algorithm which finds all the new files that were
34095
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   928
    added from merge base up to the top commit and for each file it checks if
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   929
    this file was copied from another file.
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   930
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   931
    This is pretty slow when a lot of changesets are involved but will track all
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   932
    the copies.
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34094
diff changeset
   933
    """
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   934
    m1 = c1.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   935
    m2 = c2.manifest()
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   936
    mb = base.manifest()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   937
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   938
    copies1 = pathcopies(base, c1)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   939
    copies2 = pathcopies(base, c2)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   940
44242
baf3fe2977cc copies: move early return in mergecopies() earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 44093
diff changeset
   941
    if not (copies1 or copies2):
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
   942
        return branch_copies(), branch_copies(), {}
44242
baf3fe2977cc copies: move early return in mergecopies() earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 44093
diff changeset
   943
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   944
    inversecopies1 = {}
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   945
    inversecopies2 = {}
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   946
    for dst, src in copies1.items():
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   947
        inversecopies1.setdefault(src, []).append(dst)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   948
    for dst, src in copies2.items():
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   949
        inversecopies2.setdefault(src, []).append(dst)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   950
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   951
    copy1 = {}
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   952
    copy2 = {}
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   953
    diverge = {}
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   954
    renamedelete1 = {}
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   955
    renamedelete2 = {}
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   956
    allsources = set(inversecopies1) | set(inversecopies2)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   957
    for src in allsources:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   958
        dsts1 = inversecopies1.get(src)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   959
        dsts2 = inversecopies2.get(src)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   960
        if dsts1 and dsts2:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   961
            # copied/renamed on both sides
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   962
            if src not in m1 and src not in m2:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   963
                # renamed on both sides
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   964
                dsts1 = set(dsts1)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   965
                dsts2 = set(dsts2)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   966
                # If there's some overlap in the rename destinations, we
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   967
                # consider it not divergent. For example, if side 1 copies 'a'
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   968
                # to 'b' and 'c' and deletes 'a', and side 2 copies 'a' to 'c'
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   969
                # and 'd' and deletes 'a'.
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   970
                if dsts1 & dsts2:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   971
                    for dst in dsts1 & dsts2:
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   972
                        copy1[dst] = src
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   973
                        copy2[dst] = src
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   974
                else:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   975
                    diverge[src] = sorted(dsts1 | dsts2)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   976
            elif src in m1 and src in m2:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   977
                # copied on both sides
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   978
                dsts1 = set(dsts1)
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   979
                dsts2 = set(dsts2)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   980
                for dst in dsts1 & dsts2:
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   981
                    copy1[dst] = src
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   982
                    copy2[dst] = src
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   983
            # TODO: Handle cases where it was renamed on one side and copied
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   984
            # on the other side
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   985
        elif dsts1:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   986
            # copied/renamed only on side 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   987
            _checksinglesidecopies(
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   988
                src, dsts1, m1, m2, mb, c2, base, copy1, renamedelete1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   989
            )
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   990
        elif dsts2:
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   991
            # copied/renamed only on side 2
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   992
            _checksinglesidecopies(
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
   993
                src, dsts2, m2, m1, mb, c1, base, copy2, renamedelete2
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
   994
            )
42252
57203e0210f8 copies: calculate mergecopies() based on pathcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42243
diff changeset
   995
26659
df66736a128e copies: group bothnew with other sets
Matt Mackall <mpm@selenic.com>
parents: 26658
diff changeset
   996
    # find interesting file sets from manifests
46110
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
   997
    cache = []
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
   998
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
   999
    def _get_addedfiles(idx):
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1000
        if not cache:
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1001
            addedinm1 = m1.filesnotin(mb, repo.narrowmatch())
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1002
            addedinm2 = m2.filesnotin(mb, repo.narrowmatch())
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1003
            u1 = sorted(addedinm1 - addedinm2)
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1004
            u2 = sorted(addedinm2 - addedinm1)
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1005
            cache.extend((u1, u2))
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1006
        return cache[idx]
42253
d69bc8ffbe6f copies: inline _computenonoverlap() in mergecopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 42252
diff changeset
  1007
46110
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1008
    u1fn = lambda: _get_addedfiles(0)
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1009
    u2fn = lambda: _get_addedfiles(1)
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1010
    if repo.ui.debugflag:
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1011
        u1 = u1fn()
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1012
        u2 = u2fn()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1013
46110
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1014
        header = b"  unmatched files in %s"
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1015
        if u1:
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1016
            repo.ui.debug(
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1017
                b"%s:\n   %s\n" % (header % b'local', b"\n   ".join(u1))
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1018
            )
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1019
        if u2:
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1020
            repo.ui.debug(
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1021
                b"%s:\n   %s\n" % (header % b'other', b"\n   ".join(u2))
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1022
            )
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1023
44243
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1024
        renamedeleteset = set()
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1025
        divergeset = set()
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1026
        for dsts in diverge.values():
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1027
            divergeset.update(dsts)
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1028
        for dsts in renamedelete1.values():
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1029
            renamedeleteset.update(dsts)
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1030
        for dsts in renamedelete2.values():
44243
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1031
            renamedeleteset.update(dsts)
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1032
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1033
        repo.ui.debug(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1034
            b"  all copies found (* = to merge, ! = divergent, "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1035
            b"% = renamed and deleted):\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1036
        )
44272
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1037
        for side, copies in ((b"local", copies1), (b"remote", copies2)):
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1038
            if not copies:
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1039
                continue
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1040
            repo.ui.debug(b"   on %s side:\n" % side)
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1041
            for f in sorted(copies):
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1042
                note = b""
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1043
                if f in copy1 or f in copy2:
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1044
                    note += b"*"
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1045
                if f in divergeset:
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1046
                    note += b"!"
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1047
                if f in renamedeleteset:
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1048
                    note += b"%"
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1049
                repo.ui.debug(
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1050
                    b"    src: '%s' -> dst: '%s' %s\n" % (copies[f], f, note)
17e12938f8e7 copies: print debug information about copies per side/branch
Martin von Zweigbergk <martinvonz@google.com>
parents: 44271
diff changeset
  1051
                )
44243
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1052
        del renamedeleteset
782e0d9c3b74 copies: avoid calculating debug-only stuff without --debug
Martin von Zweigbergk <martinvonz@google.com>
parents: 44242
diff changeset
  1053
        del divergeset
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1054
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1055
    repo.ui.debug(b"  checking for directory renames\n")
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1056
46110
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1057
    dirmove1, movewithdir2 = _dir_renames(repo, c1, copy1, copies1, u2fn)
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1058
    dirmove2, movewithdir1 = _dir_renames(repo, c2, copy2, copies2, u1fn)
44244
45192589555c copies: extract function for finding directory renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 44243
diff changeset
  1059
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1060
    branch_copies1 = branch_copies(copy1, renamedelete1, dirmove1, movewithdir1)
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1061
    branch_copies2 = branch_copies(copy2, renamedelete2, dirmove2, movewithdir2)
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1062
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1063
    return branch_copies1, branch_copies2, diverge
44244
45192589555c copies: extract function for finding directory renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 44243
diff changeset
  1064
45192589555c copies: extract function for finding directory renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 44243
diff changeset
  1065
46110
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1066
def _dir_renames(repo, ctx, copy, fullcopy, addedfilesfn):
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1067
    """Finds moved directories and files that should move with them.
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1068
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1069
    ctx: the context for one of the sides
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1070
    copy: files copied on the same side (as ctx)
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1071
    fullcopy: files copied on the same side (as ctx), including those that
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1072
              merge.manifestmerge() won't care about
46110
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1073
    addedfilesfn: function returning added files on the other side (compared to
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1074
                  ctx)
44271
6ca9f45b32b0 copies: make mergecopies() distinguish between copies on each side
Martin von Zweigbergk <martinvonz@google.com>
parents: 44244
diff changeset
  1075
    """
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1076
    # generate a directory move map
17055
8b7cd9a998f0 copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents: 16795
diff changeset
  1077
    invalid = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1078
    dirmove = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1079
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1080
    # examine each file copy for a potential directory move, which is
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1081
    # when all the files in a directory are moved to a new directory
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
  1082
    for dst, src in fullcopy.items():
25282
0f28815ef066 copies: switch to using pathutil.dirname
Durham Goode <durham@fb.com>
parents: 24782
diff changeset
  1083
        dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1084
        if dsrc in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1085
            # already seen to be uninteresting
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1086
            continue
46026
b9588ff9b66a copies: avoid materializing a full directory map during copy tracing
Kyle Lippincott <spectral@google.com>
parents: 46001
diff changeset
  1087
        elif ctx.hasdir(dsrc) and ctx.hasdir(ddst):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1088
            # directory wasn't entirely moved locally
39291
eebd591803ab copies: correctly skip directories that have already been considered
Kyle Lippincott <spectral@google.com>
parents: 38670
diff changeset
  1089
            invalid.add(dsrc)
eebd591803ab copies: correctly skip directories that have already been considered
Kyle Lippincott <spectral@google.com>
parents: 38670
diff changeset
  1090
        elif dsrc in dirmove and dirmove[dsrc] != ddst:
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1091
            # files from the same directory moved to two different places
39291
eebd591803ab copies: correctly skip directories that have already been considered
Kyle Lippincott <spectral@google.com>
parents: 38670
diff changeset
  1092
            invalid.add(dsrc)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1093
        else:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1094
            # looks good so far
39291
eebd591803ab copies: correctly skip directories that have already been considered
Kyle Lippincott <spectral@google.com>
parents: 38670
diff changeset
  1095
            dirmove[dsrc] = ddst
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1096
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1097
    for i in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1098
        if i in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1099
            del dirmove[i]
46026
b9588ff9b66a copies: avoid materializing a full directory map during copy tracing
Kyle Lippincott <spectral@google.com>
parents: 46001
diff changeset
  1100
    del invalid
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1101
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1102
    if not dirmove:
44244
45192589555c copies: extract function for finding directory renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 44243
diff changeset
  1103
        return {}, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1104
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
  1105
    dirmove = {k + b"/": v + b"/" for k, v in dirmove.items()}
39291
eebd591803ab copies: correctly skip directories that have already been considered
Kyle Lippincott <spectral@google.com>
parents: 38670
diff changeset
  1106
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1107
    for d in dirmove:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1108
        repo.ui.debug(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1109
            b"   discovered dir src: '%s' -> dst: '%s'\n" % (d, dirmove[d])
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1110
        )
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1111
46673
ad30b29bc23d copies: choose target directory based on longest match
Martin von Zweigbergk <martinvonz@google.com>
parents: 46627
diff changeset
  1112
    # Sort the directories in reverse order, so we find children first
ad30b29bc23d copies: choose target directory based on longest match
Martin von Zweigbergk <martinvonz@google.com>
parents: 46627
diff changeset
  1113
    # For example, if dir1/ was renamed to dir2/, and dir1/subdir1/
ad30b29bc23d copies: choose target directory based on longest match
Martin von Zweigbergk <martinvonz@google.com>
parents: 46627
diff changeset
  1114
    # was renamed to dir2/subdir2/, we want to move dir1/subdir1/file
ad30b29bc23d copies: choose target directory based on longest match
Martin von Zweigbergk <martinvonz@google.com>
parents: 46627
diff changeset
  1115
    # to dir2/subdir2/file (not dir2/subdir1/file)
ad30b29bc23d copies: choose target directory based on longest match
Martin von Zweigbergk <martinvonz@google.com>
parents: 46627
diff changeset
  1116
    dirmove_children_first = sorted(dirmove, reverse=True)
ad30b29bc23d copies: choose target directory based on longest match
Martin von Zweigbergk <martinvonz@google.com>
parents: 46627
diff changeset
  1117
30183
0106f93ca1d5 checkcopies: move 'movewithdir' initialisation right before its usage
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30138
diff changeset
  1118
    movewithdir = {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1119
    # check unaccounted nonoverlapping files against directory moves
46110
2f357d053df2 copies: make calculating lazy for dir move detection's "addedfiles"
Kyle Lippincott <spectral@google.com>
parents: 46061
diff changeset
  1120
    for f in addedfilesfn():
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1121
        if f not in fullcopy:
46673
ad30b29bc23d copies: choose target directory based on longest match
Martin von Zweigbergk <martinvonz@google.com>
parents: 46627
diff changeset
  1122
            for d in dirmove_children_first:
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1123
                if f.startswith(d):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1124
                    # new file added in a directory that was moved, move it
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1125
                    df = dirmove[d] + f[len(d) :]
6426
e2c49ef2dd6e copies: don't double-detect items in the directory copy check
Matt Mackall <mpm@selenic.com>
parents: 6425
diff changeset
  1126
                    if df not in copy:
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
  1127
                        movewithdir[f] = df
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1128
                        repo.ui.debug(
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
  1129
                            b"   pending file src: '%s' -> dst: '%s'\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1130
                            % (f, df)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1131
                        )
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1132
                    break
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
  1133
44244
45192589555c copies: extract function for finding directory renames
Martin von Zweigbergk <martinvonz@google.com>
parents: 44243
diff changeset
  1134
    return dirmove, movewithdir
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
  1135
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1136
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1137
def _heuristicscopytracing(repo, c1, c2, base):
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45907
diff changeset
  1138
    """Fast copytracing using filename heuristics
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1139
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1140
    Assumes that moves or renames are of following two types:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1141
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1142
    1) Inside a directory only (same directory name but different filenames)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1143
    2) Move from one directory to another
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1144
                    (same filenames but different directory names)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1145
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1146
    Works only when there are no merge commits in the "source branch".
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1147
    Source branch is commits from base up to c2 not including base.
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1148
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1149
    If merge is involved it fallbacks to _fullcopytracing().
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1150
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1151
    Can be used by setting the following config:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1152
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1153
        [experimental]
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1154
        copytrace = heuristics
34846
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1155
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1156
    In some cases the copy/move candidates found by heuristics can be very large
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1157
    in number and that will make the algorithm slow. The number of possible
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1158
    candidates to check can be limited by using the config
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1159
    `experimental.copytrace.movecandidateslimit` which defaults to 100.
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1160
    """
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1161
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1162
    if c1.rev() is None:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1163
        c1 = c1.p1()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1164
    if c2.rev() is None:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1165
        c2 = c2.p1()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1166
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1167
    changedfiles = set()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1168
    m1 = c1.manifest()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1169
    if not repo.revs(b'%d::%d', base.rev(), c2.rev()):
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1170
        # If base is not in c2 branch, we switch to fullcopytracing
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1171
        repo.ui.debug(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1172
            b"switching to full copytracing as base is not "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1173
            b"an ancestor of c2\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1174
        )
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1175
        return _fullcopytracing(repo, c1, c2, base)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1176
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1177
    ctx = c2
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1178
    while ctx != base:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1179
        if len(ctx.parents()) == 2:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1180
            # To keep things simple let's not handle merges
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1181
            repo.ui.debug(b"switching to full copytracing because of merges\n")
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1182
            return _fullcopytracing(repo, c1, c2, base)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1183
        changedfiles.update(ctx.files())
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1184
        ctx = ctx.p1()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1185
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1186
    copies2 = {}
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1187
    cp = _forwardcopies(base, c2)
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
  1188
    for dst, src in cp.items():
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1189
        if src in m1:
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1190
            copies2[dst] = src
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1192
    # file is missing if it isn't present in the destination, but is present in
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1193
    # the base and present in the source.
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1194
    # Presence in the base is important to exclude added files, presence in the
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1195
    # source is important to exclude removed files.
36379
f62369667a7c py3: use list comprehensions instead of filter where we need to eagerly filter
Augie Fackler <augie@google.com>
parents: 36155
diff changeset
  1196
    filt = lambda f: f not in m1 and f in base and f in c2
f62369667a7c py3: use list comprehensions instead of filter where we need to eagerly filter
Augie Fackler <augie@google.com>
parents: 36155
diff changeset
  1197
    missingfiles = [f for f in changedfiles if filt(f)]
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1198
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1199
    copies1 = {}
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1200
    if missingfiles:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1201
        basenametofilename = collections.defaultdict(list)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1202
        dirnametofilename = collections.defaultdict(list)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1203
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1204
        for f in m1.filesnotin(base.manifest()):
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1205
            basename = os.path.basename(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1206
            dirname = os.path.dirname(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1207
            basenametofilename[basename].append(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1208
            dirnametofilename[dirname].append(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1209
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1210
        for f in missingfiles:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1211
            basename = os.path.basename(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1212
            dirname = os.path.dirname(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1213
            samebasename = basenametofilename[basename]
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1214
            samedirname = dirnametofilename[dirname]
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1215
            movecandidates = samebasename + samedirname
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1216
            # f is guaranteed to be present in c2, that's why
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1217
            # c2.filectx(f) won't fail
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1218
            f2 = c2.filectx(f)
34846
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1219
            # we can have a lot of candidates which can slow down the heuristics
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1220
            # config value to limit the number of candidates moves to check
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1221
            maxcandidates = repo.ui.configint(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1222
                b'experimental', b'copytrace.movecandidateslimit'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1223
            )
34846
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1224
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1225
            if len(movecandidates) > maxcandidates:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1226
                repo.ui.status(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1227
                    _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1228
                        b"skipping copytracing for '%s', more "
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
  1229
                        b"candidates than the limit: %d\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1230
                    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1231
                    % (f, len(movecandidates))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1232
                )
34846
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1233
                continue
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
  1234
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1235
            for candidate in movecandidates:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1236
                f1 = c1.filectx(candidate)
37392
a4f02a17420d copies: clean up _related logic
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 36379
diff changeset
  1237
                if _related(f1, f2):
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1238
                    # if there are a few related copies then we'll merge
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1239
                    # changes into all of them. This matches the behaviour
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1240
                    # of upstream copytracing
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1241
                    copies1[candidate] = f
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1242
44275
fa9ad1da2e77 merge: start using the per-side copy dicts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44274
diff changeset
  1243
    return branch_copies(copies1), branch_copies(copies2), {}
34191
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34095
diff changeset
  1244
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1245
37392
a4f02a17420d copies: clean up _related logic
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 36379
diff changeset
  1246
def _related(f1, f2):
30138
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1247
    """return True if f1 and f2 filectx have a common ancestor
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1248
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1249
    Walk back to common ancestor to see if the two files originate
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1250
    from the same file. Since workingfilectx's rev() is None it messes
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1251
    up the integer comparison logic, hence the pre-step check for
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1252
    None (f1 and f2 can only be workingfilectx's initially).
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1253
    """
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1254
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1255
    if f1 == f2:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1256
        return True  # a match
30138
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1257
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1258
    g1, g2 = f1.ancestors(), f2.ancestors()
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1259
    try:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1260
        f1r, f2r = f1.linkrev(), f2.linkrev()
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1261
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1262
        if f1r is None:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1263
            f1 = next(g1)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1264
        if f2r is None:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1265
            f2 = next(g2)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1266
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1267
        while True:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1268
            f1r, f2r = f1.linkrev(), f2.linkrev()
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1269
            if f1r > f2r:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1270
                f1 = next(g1)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1271
            elif f2r > f1r:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1272
                f2 = next(g2)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1273
            else:  # f1 and f2 point to files in the same linkrev
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1274
                return f1 == f2  # true if they point to the same file
30138
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1275
    except StopIteration:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1276
        return False
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
  1277
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43022
diff changeset
  1278
44092
833210fbd900 graftcopies: remove `skip` and `repo` arguments
Martin von Zweigbergk <martinvonz@google.com>
parents: 44091
diff changeset
  1279
def graftcopies(wctx, ctx, base):
44093
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1280
    """reproduce copies between base and ctx in the wctx
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1281
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1282
    Unlike mergecopies(), this function will only consider copies between base
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1283
    and ctx; it will ignore copies between base and wctx. Also unlike
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1284
    mergecopies(), this function will apply copies to the working copy (instead
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1285
    of just returning information about the copies). That makes it cheaper
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1286
    (especially in the common case of base==ctx.p1()) and useful also when
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1287
    experimental.copytrace=off.
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1288
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1289
    merge.update() will have already marked most copies, but it will only
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1290
    mark copies if it thinks the source files are related (see
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1291
    merge._related()). It will also not mark copies if the file wasn't modified
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1292
    on the local side. This function adds the copies that were "missed"
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1293
    by merge.update().
06e7e7652ac0 graftcopies: document why the function is useful at all
Martin von Zweigbergk <martinvonz@google.com>
parents: 44092
diff changeset
  1294
    """
44091
3df0bd706c40 graftcopies: use _filter() for filtering out invalid copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 44090
diff changeset
  1295
    new_copies = pathcopies(base, ctx)
46469
f213b250fed0 copies: explicitly filter out existing file in graftcopies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46302
diff changeset
  1296
    parent = wctx.p1()
f213b250fed0 copies: explicitly filter out existing file in graftcopies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46302
diff changeset
  1297
    _filter(parent, wctx, new_copies)
46482
892eb7c5edaa copies: fix an incorrect comment in graftcopies() from recent D9802
Martin von Zweigbergk <martinvonz@google.com>
parents: 46480
diff changeset
  1298
    # Extra filtering to drop copy information for files that existed before
892eb7c5edaa copies: fix an incorrect comment in graftcopies() from recent D9802
Martin von Zweigbergk <martinvonz@google.com>
parents: 46480
diff changeset
  1299
    # the graft. This is to handle the case of grafting a rename onto a commit
892eb7c5edaa copies: fix an incorrect comment in graftcopies() from recent D9802
Martin von Zweigbergk <martinvonz@google.com>
parents: 46480
diff changeset
  1300
    # that already has the rename. Otherwise the presence of copy information
892eb7c5edaa copies: fix an incorrect comment in graftcopies() from recent D9802
Martin von Zweigbergk <martinvonz@google.com>
parents: 46480
diff changeset
  1301
    # would result in the creation of an empty commit where we would prefer to
892eb7c5edaa copies: fix an incorrect comment in graftcopies() from recent D9802
Martin von Zweigbergk <martinvonz@google.com>
parents: 46480
diff changeset
  1302
    # not create one.
46469
f213b250fed0 copies: explicitly filter out existing file in graftcopies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46302
diff changeset
  1303
    for dest, __ in list(new_copies.items()):
f213b250fed0 copies: explicitly filter out existing file in graftcopies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46302
diff changeset
  1304
        if dest in parent:
f213b250fed0 copies: explicitly filter out existing file in graftcopies
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46302
diff changeset
  1305
            del new_copies[dest]
49004
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
  1306
    for dst, src in new_copies.items():
44091
3df0bd706c40 graftcopies: use _filter() for filtering out invalid copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 44090
diff changeset
  1307
        wctx[dst].markcopied(src)