mercurial/copies.py
author Yuya Nishihara <yuya@tcha.org>
Thu, 03 May 2018 18:15:43 +0900
changeset 37974 b45f4c1532c0
parent 37448 d7114f883505
child 38046 ee7b6fa52d9d
permissions -rw-r--r--
extensions: extract closure that looks for commands from disabled module I'll rewrite this function to not load disabled extensions.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# copies.py - copy detection for Mercurial
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2008 Matt Mackall <mpm@selenic.com>
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
     5
# 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
     6
# 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
     7
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
     8
from __future__ import absolute_import
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
     9
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
    10
import collections
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
    11
import heapq
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
    12
import os
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
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
    14
from .i18n import _
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
    15
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    16
from . import (
33867
252fb66ee5bb copies: use intersectmatchers() in non-merge p1 optimization
Yuya Nishihara <yuya@tcha.org>
parents: 33822
diff changeset
    17
    match as matchmod,
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
    18
    node,
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    19
    pathutil,
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
    20
    scmutil,
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    21
    util,
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    22
)
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    23
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    24
def _findlimit(repo, a, b):
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    25
    """
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    26
    Find the last revision that needs to be checked to ensure that a full
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    27
    transitive closure for file copies can be properly calculated.
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    28
    Generally, this means finding the earliest revision number that's an
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    29
    ancestor of a or b but not both, except when a or b is a direct descendent
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    30
    of the other, in which case we can return the minimum revnum of a and b.
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    31
    None if no such revision exists.
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    32
    """
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    33
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    34
    # basic idea:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    35
    # - mark a and b with different sides
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    36
    # - if a parent's children are all on the same side, the parent is
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    37
    #   on that side, otherwise it is on no side
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    38
    # - walk the graph in topological order with the help of a heap;
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    39
    #   - add unseen parents to side map
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    40
    #   - clear side of any parent that has children on different sides
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    41
    #   - track number of interesting revs that might still be on a side
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    42
    #   - track the lowest interesting rev seen
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    43
    #   - quit when interesting revs is zero
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    44
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    45
    cl = repo.changelog
6750
fb42030d79d6 add __len__ and __iter__ methods to repo and revlog
Matt Mackall <mpm@selenic.com>
parents: 6646
diff changeset
    46
    working = len(cl) # pseudo rev for the working directory
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    47
    if a is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    48
        a = working
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    49
    if b is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    50
        b = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    51
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    52
    side = {a: -1, b: 1}
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    53
    visit = [-a, -b]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    54
    heapq.heapify(visit)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    55
    interesting = len(visit)
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    56
    hascommonancestor = False
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    57
    limit = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    58
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    59
    while interesting:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    60
        r = -heapq.heappop(visit)
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    61
        if r == working:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    62
            parents = [cl.rev(p) for p in repo.dirstate.parents()]
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    63
        else:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    64
            parents = cl.parentrevs(r)
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    65
        for p in parents:
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    66
            if p < 0:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    67
                continue
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    68
            if p not in side:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    69
                # first time we see p; add it to visit
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    70
                side[p] = side[r]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    71
                if side[p]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    72
                    interesting += 1
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    73
                heapq.heappush(visit, -p)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    74
            elif side[p] and side[p] != side[r]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    75
                # p was interesting but now we know better
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    76
                side[p] = 0
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    77
                interesting -= 1
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    78
                hascommonancestor = True
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    79
        if side[r]:
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    80
            limit = r # lowest rev visited
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    81
            interesting -= 1
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    82
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    83
    if not hascommonancestor:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    84
        return None
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    85
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    86
    # Consider the following flow (see test-commit-amend.t under issue4405):
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    87
    # 1/ File 'a0' committed
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    88
    # 2/ File renamed from 'a0' to 'a1' in a new commit (call it 'a1')
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    89
    # 3/ Move back to first commit
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    90
    # 4/ Create a new commit via revert to contents of 'a1' (call it 'a1-amend')
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    91
    # 5/ Rename file from 'a1' to 'a2' and commit --amend 'a1-msg'
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    92
    #
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    93
    # During the amend in step five, we will be in this state:
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    94
    #
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    95
    # @  3 temporary amend commit for a1-amend
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    96
    # |
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    97
    # o  2 a1-amend
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    98
    # |
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    99
    # | o  1 a1
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
   100
    # |/
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
   101
    # o  0 a0
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
   102
    #
23139
e53f6b72a0e4 spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents: 23071
diff changeset
   103
    # When _findlimit is called, a and b are revs 3 and 0, so limit will be 2,
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
   104
    # yet the filelog has the copy information in rev 1 and we will not look
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
   105
    # back far enough unless we also look at the a and b as candidates.
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
   106
    # This only occurs when a is a descendent of b or visa-versa.
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
   107
    return min(limit, a, b)
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
   108
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   109
def _chain(src, dst, a, b):
35421
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35420
diff changeset
   110
    """chain two sets of copies a->b"""
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   111
    t = a.copy()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   112
    for k, v in b.iteritems():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   113
        if v in t:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   114
            # found a chain
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   115
            if t[v] != k:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   116
                # file wasn't renamed back to itself
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   117
                t[k] = t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   118
            if v not in dst:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   119
                # chain was a rename, not a copy
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   120
                del t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   121
        if v in src:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   122
            # file is a copy of an existing file
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   123
            t[k] = v
15976
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   124
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   125
    # remove criss-crossed copies
36117
c02771617a70 py3: avoid changing dictionary during iteration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35423
diff changeset
   126
    for k, v in list(t.items()):
15976
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   127
        if k in src and v in dst:
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   128
            del t[k]
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   129
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   130
    return t
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   131
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   132
def _tracefile(fctx, am, limit=-1):
35421
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35420
diff changeset
   133
    """return file context that is the ancestor of fctx present in ancestor
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35420
diff changeset
   134
    manifest am, stopping after the first ancestor lower than limit"""
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   135
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   136
    for f in fctx.ancestors():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   137
        if am.get(f.path(), None) == f.filenode():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   138
            return f
23982
751d1138ce35 copies: use linkrev for file tracing limit
Matt Mackall <mpm@selenic.com>
parents: 23980
diff changeset
   139
        if limit >= 0 and f.linkrev() < limit and f.rev() < limit:
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   140
            return None
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   141
35420
7ddc1e96d9b0 copies: always respect matcher arg to _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 34846
diff changeset
   142
def _dirstatecopies(d, match=None):
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   143
    ds = d._repo.dirstate
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   144
    c = ds.copies().copy()
34348
1a5abc45e2fa py3: explicitly convert dict.keys() and dict.items() into a list
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34311
diff changeset
   145
    for k in list(c):
35420
7ddc1e96d9b0 copies: always respect matcher arg to _forwardcopies()
Martin von Zweigbergk <martinvonz@google.com>
parents: 34846
diff changeset
   146
        if ds[k] not in 'anm' 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
   147
            del c[k]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   148
    return c
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   149
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   150
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
   151
    """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
   152
    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
   153
    files _forwardcopies is about to process.
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   154
    """
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   155
    ma = a.manifest()
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   156
    mb = b.manifest()
31256
5a909a8098a1 copies: remove use of manifest.matches
Durham Goode <durham@fb.com>
parents: 30581
diff changeset
   157
    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
   158
35422
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   159
def _committedforwardcopies(a, b, match):
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   160
    """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
   161
    # 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
   162
    # one-side-only changeset, but not further back than that
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   163
    limit = _findlimit(a._repo, a.rev(), b.rev())
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   164
    if limit is None:
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   165
        limit = -1
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   166
    am = a.manifest()
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   167
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   168
    # find where new files came from
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   169
    # 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
   170
    # 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
   171
    cm = {}
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   172
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   173
    # 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
   174
    # 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
   175
    # 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
   176
    # 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
   177
    # 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
   178
    # this comparison.
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   179
    forwardmissingmatch = match
33867
252fb66ee5bb copies: use intersectmatchers() in non-merge p1 optimization
Yuya Nishihara <yuya@tcha.org>
parents: 33822
diff changeset
   180
    if b.p1() == a and b.p2().node() == node.nullid:
252fb66ee5bb copies: use intersectmatchers() in non-merge p1 optimization
Yuya Nishihara <yuya@tcha.org>
parents: 33822
diff changeset
   181
        filesmatcher = scmutil.matchfiles(a._repo, b.files())
252fb66ee5bb copies: use intersectmatchers() in non-merge p1 optimization
Yuya Nishihara <yuya@tcha.org>
parents: 33822
diff changeset
   182
        forwardmissingmatch = matchmod.intersectmatchers(match, filesmatcher)
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   183
    missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   184
23980
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   185
    ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True)
18878
3cfaace0441e copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents: 18362
diff changeset
   186
    for f in missing:
23980
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   187
        fctx = b[f]
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   188
        fctx._ancestrycontext = ancestrycontext
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   189
        ofctx = _tracefile(fctx, am, limit)
18878
3cfaace0441e copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents: 18362
diff changeset
   190
        if ofctx:
3cfaace0441e copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents: 18362
diff changeset
   191
            cm[f] = ofctx.path()
35422
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   192
    return cm
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   193
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   194
def _forwardcopies(a, b, match=None):
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   195
    """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: 35421
diff changeset
   196
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   197
    # check for working copy
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   198
    if b.rev() is None:
35423
e54f02ec6a05 copies: group wdir-handling in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 35422
diff changeset
   199
        if a == b.p1():
35422
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   200
            # short-circuit to avoid issues with merge states
35423
e54f02ec6a05 copies: group wdir-handling in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 35422
diff changeset
   201
            return _dirstatecopies(b, match)
35422
8801cdcea01f copies: extract method for getting non-wdir forward copies
Martin von Zweigbergk <martinvonz@google.com>
parents: 35421
diff changeset
   202
35423
e54f02ec6a05 copies: group wdir-handling in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 35422
diff changeset
   203
        cm = _committedforwardcopies(a, b.p1(), match)
e54f02ec6a05 copies: group wdir-handling in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 35422
diff changeset
   204
        # combine copies from dirstate if necessary
e54f02ec6a05 copies: group wdir-handling in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 35422
diff changeset
   205
        return _chain(a, b, cm, _dirstatecopies(b, match))
e54f02ec6a05 copies: group wdir-handling in one place
Martin von Zweigbergk <martinvonz@google.com>
parents: 35422
diff changeset
   206
    return _committedforwardcopies(a, b, match)
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   207
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   208
def _backwardrenames(a, b):
34077
26531db4647a copytrace: replace experimental.disablecopytrace config with copytrace (BC)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33880
diff changeset
   209
    if a._repo.ui.config('experimental', 'copytrace') == 'off':
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   210
        return {}
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   211
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   212
    # 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
   213
    # 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
   214
    # 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
   215
    f = _forwardcopies(b, a)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   216
    r = {}
18355
2330d97e7707 copies: make the loss in _backwardcopies more stable
Mads Kiilerich <mads@kiilerich.com>
parents: 18136
diff changeset
   217
    for k, v in sorted(f.iteritems()):
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   218
        # remove copies
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   219
        if v in a:
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   220
            continue
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   221
        r[v] = k
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   222
    return r
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   223
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   224
def pathcopies(x, y, match=None):
35421
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35420
diff changeset
   225
    """find {dst@y: src@x} copy mapping for directed compare"""
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   226
    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
   227
        return {}
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   228
    a = y.ancestor(x)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   229
    if a == x:
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   230
        return _forwardcopies(x, y, match=match)
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   231
    if a == y:
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   232
        return _backwardrenames(x, y)
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   233
    return _chain(x, y, _backwardrenames(x, a),
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   234
                  _forwardcopies(a, y, match=match))
15774
0bd17a4bed88 copies: split the copies api for "normal" and merge cases (API)
Matt Mackall <mpm@selenic.com>
parents: 14494
diff changeset
   235
30196
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   236
def _computenonoverlap(repo, c1, c2, addedinm1, addedinm2, baselabel=''):
24625
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   237
    """Computes, based on addedinm1 and addedinm2, the files exclusive to c1
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   238
    and c2. This is its own function so extensions can easily wrap this call
24187
30219bd46ed7 copies: only calculate 'addedinm[12]' sets once
Martin von Zweigbergk <martinvonz@google.com>
parents: 24186
diff changeset
   239
    to see what files mergecopies is about to process.
24273
ce847603040b copies: added manifests to computenonoverlap
Durham Goode <durham@fb.com>
parents: 24187
diff changeset
   240
24625
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   241
    Even though c1 and c2 are not used in this function, they are useful in
24273
ce847603040b copies: added manifests to computenonoverlap
Durham Goode <durham@fb.com>
parents: 24187
diff changeset
   242
    other extensions for being able to read the file nodes of the changed files.
30196
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   243
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   244
    "baselabel" can be passed to help distinguish the multiple computations
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   245
    done in the graft case.
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   246
    """
24185
3a3806fe3ddf copies: replace _nonoverlap() by calls to manifestdict.filesnotin()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24184
diff changeset
   247
    u1 = sorted(addedinm1 - addedinm2)
3a3806fe3ddf copies: replace _nonoverlap() by calls to manifestdict.filesnotin()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24184
diff changeset
   248
    u2 = sorted(addedinm2 - addedinm1)
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   249
30196
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   250
    header = "  unmatched files in %s"
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   251
    if baselabel:
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   252
        header += ' (from %s)' % baselabel
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   253
    if u1:
30196
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   254
        repo.ui.debug("%s:\n   %s\n" % (header % 'local', "\n   ".join(u1)))
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   255
    if u2:
30196
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   256
        repo.ui.debug("%s:\n   %s\n" % (header % 'other', "\n   ".join(u2)))
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   257
    return u1, u2
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   258
26656
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   259
def _makegetfctx(ctx):
30048
91a3c58ecf93 copies: mark checkcopies as internal with the _ prefix
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30047
diff changeset
   260
    """return a 'getfctx' function suitable for _checkcopies usage
26656
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   261
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   262
    We have to re-setup the function building 'filectx' for each
30048
91a3c58ecf93 copies: mark checkcopies as internal with the _ prefix
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30047
diff changeset
   263
    '_checkcopies' to ensure the linkrev adjustment is properly setup for
26656
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   264
    each. Linkrev adjustment is important to avoid bug in rename
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   265
    detection. Moreover, having a proper '_ancestrycontext' setup ensures
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   266
    the performance impact of this adjustment is kept limited. Without it,
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   267
    each file could do a full dag traversal making the time complexity of
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   268
    the operation explode (see issue4537).
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   269
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   270
    This function exists here mostly to limit the impact on stable. Feel
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   271
    free to refactor on default.
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   272
    """
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   273
    rev = ctx.rev()
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   274
    repo = ctx._repo
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   275
    ac = getattr(ctx, '_ancestrycontext', None)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   276
    if ac is None:
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   277
        revs = [rev]
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   278
        if rev is None:
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   279
            revs = [p.rev() for p in ctx.parents()]
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   280
        ac = repo.changelog.ancestors(revs, inclusive=True)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   281
        ctx._ancestrycontext = ac
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   282
    def makectx(f, n):
37448
d7114f883505 node: rename wdirnodes to clarify they are for manifest/filelogs
Yuya Nishihara <yuya@tcha.org>
parents: 37392
diff changeset
   283
        if n in node.wdirfilenodeids:  # in a working context?
26656
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   284
            if ctx.rev() is None:
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   285
                return ctx.filectx(f)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   286
            return repo[None][f]
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   287
        fctx = repo.filectx(f, fileid=n)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   288
        # setup only needed for filectx not create from a changectx
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   289
        fctx._ancestrycontext = ac
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   290
        fctx._descendantrev = rev
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   291
        return fctx
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   292
    return util.lrucachefunc(makectx)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   293
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   294
def _combinecopies(copyfrom, copyto, finalcopy, diverge, incompletediverge):
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   295
    """combine partial copy paths"""
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   296
    remainder = {}
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   297
    for f in copyfrom:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   298
        if f in copyto:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   299
            finalcopy[copyto[f]] = copyfrom[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   300
            del copyto[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   301
    for f in incompletediverge:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   302
        assert f not in diverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   303
        ic = incompletediverge[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   304
        if ic[0] in copyto:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   305
            diverge[f] = [copyto[ic[0]], ic[1]]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   306
        else:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   307
            remainder[f] = ic
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   308
    return remainder
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   309
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   310
def mergecopies(repo, c1, c2, base):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   311
    """
34078
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   312
    The function calling different copytracing algorithms on the basis of config
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   313
    which find moves and copies between context c1 and c2 that are relevant for
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   314
    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: 34077
diff changeset
   315
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   316
    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: 34077
diff changeset
   317
    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: 34077
diff changeset
   318
    For example:
33822
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   319
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   320
    o          ---> 4 another commit
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   321
    |
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   322
    |   o      ---> 3 commit that modifies a.txt
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   323
    |  /
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   324
    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: 32640
diff changeset
   325
    |/
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   326
    o          ---> 1 merge base
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   327
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   328
    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: 32640
diff changeset
   329
    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: 32640
diff changeset
   330
    message:
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   331
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   332
    ```other changed <file> which local deleted```
42ad7cc645a4 copies: add more details to the documentation of mergecopies()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32640
diff changeset
   333
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   334
    Returns five dicts: "copy", "movewithdir", "diverge", "renamedelete" and
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   335
    "dirmove".
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   336
16177
b8c1a8a57540 copies: fix mergecopies doc mapping direction
Matt Mackall <mpm@selenic.com>
parents: 16169
diff changeset
   337
    "copy" is a mapping from destination name -> source name,
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   338
    where source is in c1 and destination is in c2 or vice-versa.
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   339
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   340
    "movewithdir" is a mapping from source name -> destination name,
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   341
    where the file at source present in one context but not the other
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   342
    needs to be moved to destination by the merge process, because the
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   343
    other context moved the directory it is in.
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   344
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   345
    "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
   346
    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
   347
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   348
    "renamedelete" is a mapping of source name -> list of destination
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   349
    names for files deleted in c1 that were renamed in c2 or vice-versa.
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   350
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   351
    "dirmove" is a mapping of detected source dir -> destination dir renames.
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   352
    This is needed for handling changes to new files previously grafted into
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   353
    renamed directories.
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   354
    """
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   355
    # 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
   356
    if not c1 or not c2 or c1 == c2:
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   357
        return {}, {}, {}, {}, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   358
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   359
    # avoid silly behavior for parent -> working dir
13878
a8d13ee0ce68 misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents: 12683
diff changeset
   360
    if c2.node() is None and c1.node() == repo.dirstate.p1():
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   361
        return repo.dirstate.copies(), {}, {}, {}, {}
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   362
34078
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   363
    copytracing = repo.ui.config('experimental', 'copytrace')
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   364
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   365
    # 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
   366
    # 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
   367
    # rebase.
34078
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   368
    if copytracing == 'off':
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   369
        return {}, {}, {}, {}, {}
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   370
    elif copytracing == 'heuristics':
34366
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34348
diff changeset
   371
        # 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: 34348
diff changeset
   372
        # 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: 34348
diff changeset
   373
        # be missed by heuristics
34311
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34288
diff changeset
   374
        if _isfullcopytraceable(repo, c1, base):
34288
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34179
diff changeset
   375
            return _fullcopytracing(repo, c1, c2, base)
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   376
        return _heuristicscopytracing(repo, c1, c2, base)
34078
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   377
    else:
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   378
        return _fullcopytracing(repo, c1, c2, base)
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   379
34311
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34288
diff changeset
   380
def _isfullcopytraceable(repo, c1, base):
34366
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34348
diff changeset
   381
    """ Checks that if base, source and destination are all no-public branches,
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34348
diff changeset
   382
    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: 34348
diff changeset
   383
    since it will be fast enough.
34516
e79b3611223b copies: add docs for config `experimental.copytrace.sourcecommitlimit`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34366
diff changeset
   384
e79b3611223b copies: add docs for config `experimental.copytrace.sourcecommitlimit`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34366
diff changeset
   385
    `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: 34366
diff changeset
   386
    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: 34366
diff changeset
   387
    more than the limit, full copytracing algorithm won't be used.
34288
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34179
diff changeset
   388
    """
34311
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34288
diff changeset
   389
    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: 34288
diff changeset
   390
        c1 = c1.p1()
34366
d00910b286cd copytrace: use ctx.mutable() instead of adhoc constant of non-public phases
Yuya Nishihara <yuya@tcha.org>
parents: 34348
diff changeset
   391
    if c1.mutable() and base.mutable():
34311
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34288
diff changeset
   392
        sourcecommitlimit = repo.ui.configint('experimental',
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34288
diff changeset
   393
                                              'copytrace.sourcecommitlimit')
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34288
diff changeset
   394
        commits = len(repo.revs('%d::%d', base.rev(), c1.rev()))
1826d695ad58 copytrace: add a a new config to limit the number of drafts in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34288
diff changeset
   395
        return commits < sourcecommitlimit
34288
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34179
diff changeset
   396
    return False
fc3b8483c6cb copytrace: use the full copytracing method if only drafts are involved
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34179
diff changeset
   397
34078
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   398
def _fullcopytracing(repo, c1, c2, base):
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   399
    """ The full copytracing algorithm which finds all the new files that were
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   400
    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: 34077
diff changeset
   401
    this file was copied from another file.
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   402
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   403
    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: 34077
diff changeset
   404
    the copies.
b4b196092cc3 copytrace: move the default copytracing algorithm in a new function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34077
diff changeset
   405
    """
30193
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   406
    # In certain scenarios (e.g. graft, update or rebase), base can be
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   407
    # overridden We still need to know a real common ancestor in this case We
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   408
    # can't just compute _c1.ancestor(_c2) and compare it to ca, because there
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   409
    # can be multiple common ancestors, e.g. in case of bidmerge.  Because our
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   410
    # caller may not know if the revision passed in lieu of the CA is a genuine
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   411
    # common ancestor or not without explicitly checking it, it's better to
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   412
    # determine that here.
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   413
    #
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   414
    # base.descendant(wc) and base.descendant(base) are False, work around that
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   415
    _c1 = c1.p1() if c1.rev() is None else c1
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   416
    _c2 = c2.p1() if c2.rev() is None else c2
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   417
    # an endpoint is "dirty" if it isn't a descendant of the merge base
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   418
    # if we have a dirty endpoint, we need to trigger graft logic, and also
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   419
    # keep track of which endpoint is dirty
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   420
    dirtyc1 = not (base == _c1 or base.descendant(_c1))
33880
edf503e5dfd4 copies: fix misaligned lines
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 33879
diff changeset
   421
    dirtyc2 = not (base == _c2 or base.descendant(_c2))
30193
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   422
    graft = dirtyc1 or dirtyc2
30194
8c69c52ced98 copies: compute a suitable TCA if base turns out to be unsuitable
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30193
diff changeset
   423
    tca = base
8c69c52ced98 copies: compute a suitable TCA if base turns out to be unsuitable
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30193
diff changeset
   424
    if graft:
8c69c52ced98 copies: compute a suitable TCA if base turns out to be unsuitable
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30193
diff changeset
   425
        tca = _c1.ancestor(_c2)
8c69c52ced98 copies: compute a suitable TCA if base turns out to be unsuitable
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30193
diff changeset
   426
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
   427
    limit = _findlimit(repo, c1.rev(), c2.rev())
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
   428
    if limit is None:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
   429
        # no common ancestor, no copies
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   430
        return {}, {}, {}, {}, {}
26319
4b9bb1616195 copies: move debug statement to appropriate place
Matt Mackall <mpm@selenic.com>
parents: 26317
diff changeset
   431
    repo.ui.debug("  searching for copies back to rev %d\n" % limit)
4b9bb1616195 copies: move debug statement to appropriate place
Matt Mackall <mpm@selenic.com>
parents: 26317
diff changeset
   432
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   433
    m1 = c1.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   434
    m2 = c2.manifest()
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   435
    mb = base.manifest()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   436
30185
e2bfe2d52d7a copies: move variable document from checkcopies to mergecopies
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30184
diff changeset
   437
    # gather data from _checkcopies:
e2bfe2d52d7a copies: move variable document from checkcopies to mergecopies
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30184
diff changeset
   438
    # - diverge = record all diverges in this dict
e2bfe2d52d7a copies: move variable document from checkcopies to mergecopies
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30184
diff changeset
   439
    # - copy = record all non-divergent copies in this dict
e2bfe2d52d7a copies: move variable document from checkcopies to mergecopies
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30184
diff changeset
   440
    # - fullcopy = record all copies in this dict
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   441
    # - incomplete = record non-divergent partial copies here
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   442
    # - incompletediverge = record divergent partial copies here
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   443
    diverge = {} # divergence data is shared
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   444
    incompletediverge  = {}
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   445
    data1 = {'copy': {},
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   446
             'fullcopy': {},
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   447
             'incomplete': {},
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   448
             'diverge': diverge,
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   449
             'incompletediverge': incompletediverge,
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   450
            }
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   451
    data2 = {'copy': {},
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   452
             'fullcopy': {},
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   453
             'incomplete': {},
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   454
             'diverge': diverge,
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   455
             'incompletediverge': incompletediverge,
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   456
            }
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   457
26659
df66736a128e copies: group bothnew with other sets
Matt Mackall <mpm@selenic.com>
parents: 26658
diff changeset
   458
    # find interesting file sets from manifests
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   459
    addedinm1 = m1.filesnotin(mb)
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   460
    addedinm2 = m2.filesnotin(mb)
26659
df66736a128e copies: group bothnew with other sets
Matt Mackall <mpm@selenic.com>
parents: 26658
diff changeset
   461
    bothnew = sorted(addedinm1 & addedinm2)
30197
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   462
    if tca == base:
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   463
        # unmatched file from base
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   464
        u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   465
        u1u, u2u = u1r, u2r
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   466
    else:
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   467
        # unmatched file from base (DAG rotation in the graft case)
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   468
        u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2,
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   469
                                      baselabel='base')
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   470
        # unmatched file from topological common ancestors (no DAG rotation)
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   471
        # need to recompute this for directory move handling when grafting
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   472
        mta = tca.manifest()
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   473
        u1u, u2u = _computenonoverlap(repo, c1, c2, m1.filesnotin(mta),
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   474
                                                    m2.filesnotin(mta),
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   475
                                      baselabel='topological common ancestor')
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   476
30047
d13a7c8bf0a5 copies: split u1/u2 to u1u/u2u and u1r/u2r
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30046
diff changeset
   477
    for f in u1u:
32563
e1e1cc97e05a copies: remove msrc and mdst parameters
Stanislau Hlebik <stash@fb.com>
parents: 32562
diff changeset
   478
        _checkcopies(c1, c2, f, base, tca, dirtyc1, limit, data1)
20989
e8533ec2d222 copies: remove _checkcopies wrapper - it does no good
Mads Kiilerich <madski@unity3d.com>
parents: 20641
diff changeset
   479
30047
d13a7c8bf0a5 copies: split u1/u2 to u1u/u2u and u1r/u2r
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30046
diff changeset
   480
    for f in u2u:
32563
e1e1cc97e05a copies: remove msrc and mdst parameters
Stanislau Hlebik <stash@fb.com>
parents: 32562
diff changeset
   481
        _checkcopies(c2, c1, f, base, tca, dirtyc2, limit, data2)
26316
d5618e210191 copies: begin separating mergecopies sides
Matt Mackall <mpm@selenic.com>
parents: 26315
diff changeset
   482
32640
aeac3cbcbbc1 py3: use dict.update() instead of constructing lists and adding them
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32565
diff changeset
   483
    copy = dict(data1['copy'])
aeac3cbcbbc1 py3: use dict.update() instead of constructing lists and adding them
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32565
diff changeset
   484
    copy.update(data2['copy'])
aeac3cbcbbc1 py3: use dict.update() instead of constructing lists and adding them
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32565
diff changeset
   485
    fullcopy = dict(data1['fullcopy'])
aeac3cbcbbc1 py3: use dict.update() instead of constructing lists and adding them
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32565
diff changeset
   486
    fullcopy.update(data2['fullcopy'])
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   487
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   488
    if dirtyc1:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   489
        _combinecopies(data2['incomplete'], data1['incomplete'], copy, diverge,
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   490
                       incompletediverge)
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   491
    else:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   492
        _combinecopies(data1['incomplete'], data2['incomplete'], copy, diverge,
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   493
                       incompletediverge)
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   494
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
   495
    renamedelete = {}
26658
aabfa0fb7e3e copies: rename renamedelete to renamedeleteset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26657
diff changeset
   496
    renamedeleteset = set()
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   497
    divergeset = set()
34348
1a5abc45e2fa py3: explicitly convert dict.keys() and dict.items() into a list
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34311
diff changeset
   498
    for of, fl in list(diverge.items()):
16792
ad394c897b16 merge: do not warn about copy and rename in the same transaction (issue2113)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16178
diff changeset
   499
        if len(fl) == 1 or of in c1 or of in c2:
12683
ada47c38f4e5 copies: don't detect copies as "divergent renames"
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 10874
diff changeset
   500
            del diverge[of] # not actually divergent, or not a rename
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
   501
            if of not in c1 and of not in c2:
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   502
                # renamed on one side, deleted on the other side, but filter
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   503
                # out files that have been renamed and then deleted
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   504
                renamedelete[of] = [f for f in fl if f in c1 or f in c2]
26658
aabfa0fb7e3e copies: rename renamedelete to renamedeleteset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26657
diff changeset
   505
                renamedeleteset.update(fl) # reverse map for below
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   506
        else:
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   507
            divergeset.update(fl) # reverse map for below
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   508
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   509
    if bothnew:
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   510
        repo.ui.debug("  unmatched files new in both:\n   %s\n"
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   511
                      % "\n   ".join(bothnew))
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   512
    bothdiverge = {}
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   513
    bothincompletediverge = {}
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   514
    remainder = {}
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   515
    both1 = {'copy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   516
             'fullcopy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   517
             'incomplete': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   518
             'diverge': bothdiverge,
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   519
             'incompletediverge': bothincompletediverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   520
            }
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   521
    both2 = {'copy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   522
             'fullcopy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   523
             'incomplete': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   524
             'diverge': bothdiverge,
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   525
             'incompletediverge': bothincompletediverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   526
            }
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   527
    for f in bothnew:
32563
e1e1cc97e05a copies: remove msrc and mdst parameters
Stanislau Hlebik <stash@fb.com>
parents: 32562
diff changeset
   528
        _checkcopies(c1, c2, f, base, tca, dirtyc1, limit, both1)
e1e1cc97e05a copies: remove msrc and mdst parameters
Stanislau Hlebik <stash@fb.com>
parents: 32562
diff changeset
   529
        _checkcopies(c2, c1, f, base, tca, dirtyc2, limit, both2)
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   530
    if dirtyc1:
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   531
        # incomplete copies may only be found on the "dirty" side for bothnew
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   532
        assert not both2['incomplete']
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   533
        remainder = _combinecopies({}, both1['incomplete'], copy, bothdiverge,
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   534
                                   bothincompletediverge)
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   535
    elif dirtyc2:
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   536
        assert not both1['incomplete']
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   537
        remainder = _combinecopies({}, both2['incomplete'], copy, bothdiverge,
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   538
                                   bothincompletediverge)
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   539
    else:
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   540
        # incomplete copies and divergences can't happen outside grafts
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   541
        assert not both1['incomplete']
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   542
        assert not both2['incomplete']
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   543
        assert not bothincompletediverge
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   544
    for f in remainder:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   545
        assert f not in bothdiverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   546
        ic = remainder[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   547
        if ic[0] in (m1 if dirtyc1 else m2):
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   548
            # backed-out rename on one side, but watch out for deleted files
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   549
            bothdiverge[f] = ic
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   550
    for of, fl in bothdiverge.items():
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   551
        if len(fl) == 2 and fl[0] == fl[1]:
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   552
            copy[fl[0]] = of # not actually divergent, just matching renames
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   553
20990
d9e211a658eb copies: guard debug section with ui.debugflag
Mads Kiilerich <madski@unity3d.com>
parents: 20989
diff changeset
   554
    if fullcopy and repo.ui.debugflag:
16795
e9ae770eff1c merge: show renamed on one and deleted on the other side in debug output
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16794
diff changeset
   555
        repo.ui.debug("  all copies found (* = to merge, ! = divergent, "
e9ae770eff1c merge: show renamed on one and deleted on the other side in debug output
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16794
diff changeset
   556
                      "% = renamed and deleted):\n")
18362
5a4f220fbfca copies: report found copies sorted
Mads Kiilerich <mads@kiilerich.com>
parents: 18355
diff changeset
   557
        for f in sorted(fullcopy):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   558
            note = ""
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   559
            if f in copy:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   560
                note += "*"
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   561
            if f in divergeset:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   562
                note += "!"
26658
aabfa0fb7e3e copies: rename renamedelete to renamedeleteset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26657
diff changeset
   563
            if f in renamedeleteset:
16795
e9ae770eff1c merge: show renamed on one and deleted on the other side in debug output
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16794
diff changeset
   564
                note += "%"
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   565
            repo.ui.debug("   src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f,
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   566
                                                              note))
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   567
    del divergeset
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   568
16169
c12d4aceba79 copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents: 16168
diff changeset
   569
    if not fullcopy:
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   570
        return copy, {}, diverge, renamedelete, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   571
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   572
    repo.ui.debug("  checking for directory renames\n")
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   573
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   574
    # generate a directory move map
16178
828fe2ca7cbb copies: use ctx.dirs() for directory rename detection
Matt Mackall <mpm@selenic.com>
parents: 16177
diff changeset
   575
    d1, d2 = c1.dirs(), c2.dirs()
25288
947771ad5174 copies: document hack for adding '' to set of dirs
Martin von Zweigbergk <martinvonz@google.com>
parents: 25282
diff changeset
   576
    # Hack for adding '', which is not otherwise added, to d1 and d2
18899
d8ff607ef721 scmutil: use new dirs class in dirstate and context
Bryan O'Sullivan <bryano@fb.com>
parents: 18878
diff changeset
   577
    d1.addpath('/')
d8ff607ef721 scmutil: use new dirs class in dirstate and context
Bryan O'Sullivan <bryano@fb.com>
parents: 18878
diff changeset
   578
    d2.addpath('/')
17055
8b7cd9a998f0 copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents: 16795
diff changeset
   579
    invalid = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   580
    dirmove = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   581
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   582
    # 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
   583
    # when all the files in a directory are moved to a new directory
7622
4dd7b28003d2 use dict.iteritems() rather than dict.items()
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6762
diff changeset
   584
    for dst, src in fullcopy.iteritems():
25282
0f28815ef066 copies: switch to using pathutil.dirname
Durham Goode <durham@fb.com>
parents: 24782
diff changeset
   585
        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
   586
        if dsrc in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   587
            # already seen to be uninteresting
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   588
            continue
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   589
        elif dsrc in d1 and ddst in d1:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   590
            # directory wasn't entirely moved locally
27876
602add6ad9e5 copies: fix detection of divergent directory renames
Matt Mackall <mpm@selenic.com>
parents: 26781
diff changeset
   591
            invalid.add(dsrc + "/")
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   592
        elif dsrc in d2 and ddst in d2:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   593
            # directory wasn't entirely moved remotely
27876
602add6ad9e5 copies: fix detection of divergent directory renames
Matt Mackall <mpm@selenic.com>
parents: 26781
diff changeset
   594
            invalid.add(dsrc + "/")
602add6ad9e5 copies: fix detection of divergent directory renames
Matt Mackall <mpm@selenic.com>
parents: 26781
diff changeset
   595
        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
   596
            # files from the same directory moved to two different places
27876
602add6ad9e5 copies: fix detection of divergent directory renames
Matt Mackall <mpm@selenic.com>
parents: 26781
diff changeset
   597
            invalid.add(dsrc + "/")
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   598
        else:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   599
            # looks good so far
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   600
            dirmove[dsrc + "/"] = ddst + "/"
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   601
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   602
    for i in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   603
        if i in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   604
            del dirmove[i]
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   605
    del d1, d2, invalid
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   606
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   607
    if not dirmove:
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   608
        return copy, {}, diverge, renamedelete, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   609
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   610
    for d in dirmove:
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   611
        repo.ui.debug("   discovered dir src: '%s' -> dst: '%s'\n" %
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   612
                      (d, dirmove[d]))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   613
30183
0106f93ca1d5 checkcopies: move 'movewithdir' initialisation right before its usage
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30138
diff changeset
   614
    movewithdir = {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   615
    # check unaccounted nonoverlapping files against directory moves
30047
d13a7c8bf0a5 copies: split u1/u2 to u1u/u2u and u1r/u2r
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30046
diff changeset
   616
    for f in u1r + u2r:
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   617
        if f not in fullcopy:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   618
            for d in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   619
                if f.startswith(d):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   620
                    # new file added in a directory that was moved, move it
6425
2d9328a2f81f copies: skip directory rename checks when not merging
Matt Mackall <mpm@selenic.com>
parents: 6424
diff changeset
   621
                    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
   622
                    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
   623
                        movewithdir[f] = df
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   624
                        repo.ui.debug(("   pending file src: '%s' -> "
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   625
                                       "dst: '%s'\n") % (f, df))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   626
                    break
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   627
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   628
    return copy, movewithdir, diverge, renamedelete, dirmove
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   629
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   630
def _heuristicscopytracing(repo, c1, c2, base):
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   631
    """ Fast copytracing using filename heuristics
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   632
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   633
    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: 34078
diff changeset
   634
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   635
    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: 34078
diff changeset
   636
    2) Move from one directory to another
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   637
                    (same filenames but different directory names)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   638
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   639
    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: 34078
diff changeset
   640
    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: 34078
diff changeset
   641
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   642
    If merge is involved it fallbacks to _fullcopytracing().
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   643
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   644
    Can be used by setting the following config:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   645
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   646
        [experimental]
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   647
        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
   648
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   649
    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
   650
    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
   651
    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
   652
    `experimental.copytrace.movecandidateslimit` which defaults to 100.
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   653
    """
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   654
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   655
    if c1.rev() is None:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   656
        c1 = c1.p1()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   657
    if c2.rev() is None:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   658
        c2 = c2.p1()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   659
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   660
    copies = {}
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   661
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   662
    changedfiles = set()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   663
    m1 = c1.manifest()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   664
    if not repo.revs('%d::%d', base.rev(), c2.rev()):
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   665
        # If base is not in c2 branch, we switch to fullcopytracing
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   666
        repo.ui.debug("switching to full copytracing as base is not "
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   667
                      "an ancestor of c2\n")
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   668
        return _fullcopytracing(repo, c1, c2, base)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   669
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   670
    ctx = c2
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   671
    while ctx != base:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   672
        if len(ctx.parents()) == 2:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   673
            # To keep things simple let's not handle merges
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   674
            repo.ui.debug("switching to full copytracing because of merges\n")
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   675
            return _fullcopytracing(repo, c1, c2, base)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   676
        changedfiles.update(ctx.files())
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   677
        ctx = ctx.p1()
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   678
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   679
    cp = _forwardcopies(base, c2)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   680
    for dst, src in cp.iteritems():
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   681
        if src in m1:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   682
            copies[dst] = src
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   683
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   684
    # 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: 34078
diff changeset
   685
    # the base and present in the source.
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   686
    # 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: 34078
diff changeset
   687
    # source is important to exclude removed files.
36346
f62369667a7c py3: use list comprehensions instead of filter where we need to eagerly filter
Augie Fackler <augie@google.com>
parents: 36117
diff changeset
   688
    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: 36117
diff changeset
   689
    missingfiles = [f for f in changedfiles if filt(f)]
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   690
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   691
    if missingfiles:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   692
        basenametofilename = collections.defaultdict(list)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   693
        dirnametofilename = collections.defaultdict(list)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   694
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   695
        for f in m1.filesnotin(base.manifest()):
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   696
            basename = os.path.basename(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   697
            dirname = os.path.dirname(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   698
            basenametofilename[basename].append(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   699
            dirnametofilename[dirname].append(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   700
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   701
        for f in missingfiles:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   702
            basename = os.path.basename(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   703
            dirname = os.path.dirname(f)
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   704
            samebasename = basenametofilename[basename]
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   705
            samedirname = dirnametofilename[dirname]
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   706
            movecandidates = samebasename + samedirname
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   707
            # 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: 34078
diff changeset
   708
            # c2.filectx(f) won't fail
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   709
            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
   710
            # 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
   711
            # config value to limit the number of candidates moves to check
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   712
            maxcandidates = repo.ui.configint('experimental',
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   713
                                              'copytrace.movecandidateslimit')
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   714
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   715
            if len(movecandidates) > maxcandidates:
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   716
                repo.ui.status(_("skipping copytracing for '%s', more "
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   717
                                 "candidates than the limit: %d\n")
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   718
                               % (f, len(movecandidates)))
f05a6e015ecc copies: add a config to limit the number of candidates to check in heuristics
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34787
diff changeset
   719
                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
   720
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   721
            for candidate in movecandidates:
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   722
                f1 = c1.filectx(candidate)
37392
a4f02a17420d copies: clean up _related logic
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 36346
diff changeset
   723
                if _related(f1, f2):
34179
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   724
                    # 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: 34078
diff changeset
   725
                    # changes into all of them. This matches the behaviour
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   726
                    # of upstream copytracing
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   727
                    copies[candidate] = f
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   728
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   729
    return copies, {}, {}, {}, {}
036d47d7cf39 copytrace: move fast heuristic copytracing algorithm to core
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34078
diff changeset
   730
37392
a4f02a17420d copies: clean up _related logic
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 36346
diff changeset
   731
def _related(f1, f2):
30138
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   732
    """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
   733
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   734
    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
   735
    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
   736
    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
   737
    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
   738
    """
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   739
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   740
    if f1 == f2:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   741
        return f1 # a match
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   742
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   743
    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
   744
    try:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   745
        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
   746
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   747
        if f1r is None:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   748
            f1 = next(g1)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   749
        if f2r is None:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   750
            f2 = next(g2)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   751
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   752
        while True:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   753
            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
   754
            if f1r > f2r:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   755
                f1 = next(g1)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   756
            elif f2r > f1r:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   757
                f2 = next(g2)
37392
a4f02a17420d copies: clean up _related logic
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 36346
diff changeset
   758
            else: # f1 and f2 point to files in the same linkrev
a4f02a17420d copies: clean up _related logic
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 36346
diff changeset
   759
                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
   760
    except StopIteration:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   761
        return False
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   762
32563
e1e1cc97e05a copies: remove msrc and mdst parameters
Stanislau Hlebik <stash@fb.com>
parents: 32562
diff changeset
   763
def _checkcopies(srcctx, dstctx, f, base, tca, remotebase, limit, data):
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   764
    """
32560
931b7707179f copies: rename m2 to mdst
Stanislau Hlebik <stash@fb.com>
parents: 32559
diff changeset
   765
    check possible copies of f from msrc to mdst
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   766
32561
52cdbdd208d8 copies: rename ctx to srcctx
Stanislau Hlebik <stash@fb.com>
parents: 32560
diff changeset
   767
    srcctx = starting context for f in msrc
32562
e4d1bc14e39a copies: add dstctx parameter
Stanislau Hlebik <stash@fb.com>
parents: 32561
diff changeset
   768
    dstctx = destination context for f in mdst
32559
c8c9feffbd35 copies: rename m1 to msrc
Stanislau Hlebik <stash@fb.com>
parents: 32291
diff changeset
   769
    f = the filename to check (as in msrc)
30135
3eae81c0a09d checkcopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30075
diff changeset
   770
    base = the changectx used as a merge base
30195
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   771
    tca = topological common ancestor for graft-like scenarios
32561
52cdbdd208d8 copies: rename ctx to srcctx
Stanislau Hlebik <stash@fb.com>
parents: 32560
diff changeset
   772
    remotebase = True if base is outside tca::srcctx, False otherwise
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   773
    limit = the rev number to not search beyond
30185
e2bfe2d52d7a copies: move variable document from checkcopies to mergecopies
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30184
diff changeset
   774
    data = dictionary of dictionary to store copy data. (see mergecopies)
30045
12cac1e4d6d9 copies: limit is an optimization, and doesn't provide guarantees
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29216
diff changeset
   775
33879
169baf3d1d3c copies: fix typo in comment
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 33867
diff changeset
   776
    note: limit is only an optimization, and provides no guarantee that
169baf3d1d3c copies: fix typo in comment
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 33867
diff changeset
   777
    irrelevant revisions will not be visited
30045
12cac1e4d6d9 copies: limit is an optimization, and doesn't provide guarantees
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29216
diff changeset
   778
    there is no easy way to make this algorithm stop in a guaranteed way
12cac1e4d6d9 copies: limit is an optimization, and doesn't provide guarantees
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29216
diff changeset
   779
    once it "goes behind a certain revision".
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   780
    """
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   781
32563
e1e1cc97e05a copies: remove msrc and mdst parameters
Stanislau Hlebik <stash@fb.com>
parents: 32562
diff changeset
   782
    msrc = srcctx.manifest()
e1e1cc97e05a copies: remove msrc and mdst parameters
Stanislau Hlebik <stash@fb.com>
parents: 32562
diff changeset
   783
    mdst = dstctx.manifest()
30135
3eae81c0a09d checkcopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30075
diff changeset
   784
    mb = base.manifest()
30204
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   785
    mta = tca.manifest()
30195
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   786
    # Might be true if this call is about finding backward renames,
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   787
    # This happens in the case of grafts because the DAG is then rotated.
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   788
    # If the file exists in both the base and the source, we are not looking
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   789
    # for a rename on the source side, but on the part of the DAG that is
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   790
    # traversed backwards.
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   791
    #
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   792
    # In the case there is both backward and forward renames (before and after
30201
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   793
    # the base) this is more complicated as we must detect a divergence.
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   794
    # We use 'backwards = False' in that case.
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   795
    backwards = not remotebase and base != tca and f in mb
32564
6966e42f833a copies: rename getfctx to getsrcfctx
Stanislau Hlebik <stash@fb.com>
parents: 32563
diff changeset
   796
    getsrcfctx = _makegetfctx(srcctx)
32565
5313d98089f5 copies: introduce getdstfctx
Stanislau Hlebik <stash@fb.com>
parents: 32564
diff changeset
   797
    getdstfctx = _makegetfctx(dstctx)
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   798
32559
c8c9feffbd35 copies: rename m1 to msrc
Stanislau Hlebik <stash@fb.com>
parents: 32291
diff changeset
   799
    if msrc[f] == mb.get(f) and not remotebase:
30229
69ffbbe73dd0 merge: avoid superfluous filemerges when grafting through renames (issue5407)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30208
diff changeset
   800
        # Nothing to merge
69ffbbe73dd0 merge: avoid superfluous filemerges when grafting through renames (issue5407)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30208
diff changeset
   801
        return
69ffbbe73dd0 merge: avoid superfluous filemerges when grafting through renames (issue5407)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30208
diff changeset
   802
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   803
    of = None
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31256
diff changeset
   804
    seen = {f}
32564
6966e42f833a copies: rename getfctx to getsrcfctx
Stanislau Hlebik <stash@fb.com>
parents: 32563
diff changeset
   805
    for oc in getsrcfctx(f, msrc[f]).ancestors():
25279
708b19c18adf mergecopies: avoid slowdown from linkrev adjustment (issue4680)
Matt Mackall <mpm@selenic.com>
parents: 24782
diff changeset
   806
        ocr = oc.linkrev()
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   807
        of = oc.path()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   808
        if of in seen:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   809
            # check limit late - grab last rename before
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   810
            if ocr < limit:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   811
                break
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   812
            continue
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   813
        seen.add(of)
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   814
30195
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   815
        # remember for dir rename detection
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   816
        if backwards:
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   817
            data['fullcopy'][of] = f # grafting backwards through renames
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   818
        else:
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   819
            data['fullcopy'][f] = of
32560
931b7707179f copies: rename m2 to mdst
Stanislau Hlebik <stash@fb.com>
parents: 32559
diff changeset
   820
        if of not in mdst:
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   821
            continue # no match, keep looking
32560
931b7707179f copies: rename m2 to mdst
Stanislau Hlebik <stash@fb.com>
parents: 32559
diff changeset
   822
        if mdst[of] == mb.get(of):
30075
2c8ec8c2ddfe copies: don't record divergence for files needing no merge
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30048
diff changeset
   823
            return # no merge needed, quit early
32565
5313d98089f5 copies: introduce getdstfctx
Stanislau Hlebik <stash@fb.com>
parents: 32564
diff changeset
   824
        c2 = getdstfctx(of, mdst[of])
30137
f85f9e069e09 checkcopies: add an inline comment about the '_related' call
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30136
diff changeset
   825
        # c2 might be a plain new file on added on destination side that is
f85f9e069e09 checkcopies: add an inline comment about the '_related' call
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30136
diff changeset
   826
        # unrelated to the droids we are looking for.
37392
a4f02a17420d copies: clean up _related logic
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 36346
diff changeset
   827
        cr = _related(oc, c2)
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   828
        if cr and (of == f or of == c2.path()): # non-divergent
30195
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   829
            if backwards:
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   830
                data['copy'][of] = f
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   831
            elif of in mb:
30188
8a864844d5a0 checkcopies: add a sanity check against false-positive copies
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30186
diff changeset
   832
                data['copy'][f] = of
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   833
            elif remotebase: # special case: a <- b <- a -> b "ping-pong" rename
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   834
                data['copy'][of] = f
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   835
                del data['fullcopy'][f]
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   836
                data['fullcopy'][of] = f
30201
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   837
            else: # divergence w.r.t. graft CA on one side of topological CA
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   838
                for sf in seen:
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   839
                    if sf in mb:
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   840
                        assert sf not in data['diverge']
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   841
                        data['diverge'][sf] = [f, of]
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   842
                        break
30075
2c8ec8c2ddfe copies: don't record divergence for files needing no merge
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30048
diff changeset
   843
            return
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   844
30204
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   845
    if of in mta:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   846
        if backwards or remotebase:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   847
            data['incomplete'][of] = f
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   848
        else:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   849
            for sf in seen:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   850
                if sf in mb:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   851
                    if tca == base:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   852
                        data['diverge'].setdefault(sf, []).append(f)
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   853
                    else:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   854
                        data['incompletediverge'][sf] = [of, f]
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   855
                    return
22901
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   856
34787
754b5117622f context: add workingfilectx.markcopied
Phil Cohen <phillco@fb.com>
parents: 34516
diff changeset
   857
def duplicatecopies(repo, wctx, rev, fromrev, skiprev=None):
35421
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35420
diff changeset
   858
    """reproduce copies from fromrev to rev in the dirstate
22901
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   859
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   860
    If skiprev is specified, it's a revision that should be used to
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   861
    filter copy records. Any copies that occur between fromrev and
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   862
    skiprev will not be duplicated, even if they appear in the set of
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   863
    copies between fromrev and rev.
35421
9cf37d111acb copies: consistently use """ for docstrings
Martin von Zweigbergk <martinvonz@google.com>
parents: 35420
diff changeset
   864
    """
22901
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   865
    exclude = {}
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   866
    if (skiprev is not None and
34077
26531db4647a copytrace: replace experimental.disablecopytrace config with copytrace (BC)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33880
diff changeset
   867
        repo.ui.config('experimental', 'copytrace') != 'off'):
26531db4647a copytrace: replace experimental.disablecopytrace config with copytrace (BC)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 33880
diff changeset
   868
        # copytrace='off' skips this line, but not the entire function because
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   869
        # the line below is O(size of the repo) during a rebase, while the rest
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   870
        # of the function is much faster (and is required for carrying copy
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   871
        # metadata across the rebase anyway).
22901
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   872
        exclude = pathcopies(repo[fromrev], repo[skiprev])
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   873
    for dst, src in pathcopies(repo[fromrev], repo[rev]).iteritems():
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   874
        # copies.pathcopies returns backward renames, so dst might not
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   875
        # actually be in the dirstate
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   876
        if dst in exclude:
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   877
            continue
34787
754b5117622f context: add workingfilectx.markcopied
Phil Cohen <phillco@fb.com>
parents: 34516
diff changeset
   878
        wctx[dst].markcopied(src)