mercurial/copies.py
author Ryan McElroy <rmcelroy@fb.com>
Tue, 21 Mar 2017 06:50:28 -0700
changeset 31537 c6cbe5720353
parent 31256 5a909a8098a1
child 32291 bd872f64a8ba
permissions -rw-r--r--
posix: use local reference to unlink We have a local reference to os.unlink in module scope, but we still used os.unlink inside functions. This changes util to use the local reference, which will pave the way for combining duplicated code in future patches.
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
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
    10
import heapq
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    12
from . import (
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
    13
    node,
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    14
    pathutil,
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
    15
    scmutil,
25924
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    16
    util,
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    17
)
cfc24c22454e copies: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25289
diff changeset
    18
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    19
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
    20
    """
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    21
    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
    22
    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
    23
    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
    24
    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
    25
    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
    26
    None if no such revision exists.
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    27
    """
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    28
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    29
    # basic idea:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    30
    # - mark a and b with different sides
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    31
    # - 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
    32
    #   on that side, otherwise it is on no side
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    33
    # - 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
    34
    #   - add unseen parents to side map
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    35
    #   - 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
    36
    #   - 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
    37
    #   - track the lowest interesting rev seen
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    38
    #   - quit when interesting revs is zero
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    39
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    40
    cl = repo.changelog
6750
fb42030d79d6 add __len__ and __iter__ methods to repo and revlog
Matt Mackall <mpm@selenic.com>
parents: 6646
diff changeset
    41
    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
    42
    if a is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    43
        a = working
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    44
    if b is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    45
        b = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    46
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    47
    side = {a: -1, b: 1}
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    48
    visit = [-a, -b]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    49
    heapq.heapify(visit)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    50
    interesting = len(visit)
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    51
    hascommonancestor = False
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    52
    limit = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    53
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    54
    while interesting:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    55
        r = -heapq.heappop(visit)
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    56
        if r == working:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    57
            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
    58
        else:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    59
            parents = cl.parentrevs(r)
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    60
        for p in parents:
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    61
            if p < 0:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    62
                continue
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    63
            if p not in side:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    64
                # first time we see p; add it to visit
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    65
                side[p] = side[r]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    66
                if side[p]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    67
                    interesting += 1
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    68
                heapq.heappush(visit, -p)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    69
            elif side[p] and side[p] != side[r]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    70
                # p was interesting but now we know better
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    71
                side[p] = 0
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    72
                interesting -= 1
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    73
                hascommonancestor = True
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    74
        if side[r]:
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    75
            limit = r # lowest rev visited
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    76
            interesting -= 1
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    77
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    78
    if not hascommonancestor:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    79
        return None
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    80
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    81
    # 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
    82
    # 1/ File 'a0' committed
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    83
    # 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
    84
    # 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
    85
    # 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
    86
    # 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
    87
    #
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    88
    # 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
    89
    #
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    90
    # @  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
    91
    # |
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    92
    # o  2 a1-amend
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    93
    # |
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    94
    # | o  1 a1
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    95
    # |/
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    96
    # o  0 a0
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    97
    #
23139
e53f6b72a0e4 spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents: 23071
diff changeset
    98
    # 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
    99
    # 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
   100
    # 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
   101
    # 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
   102
    return min(limit, a, b)
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
   103
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   104
def _chain(src, dst, a, b):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   105
    '''chain two sets of copies a->b'''
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   106
    t = a.copy()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   107
    for k, v in b.iteritems():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   108
        if v in t:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   109
            # found a chain
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   110
            if t[v] != k:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   111
                # 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
   112
                t[k] = t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   113
            if v not in dst:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   114
                # 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
   115
                del t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   116
        if v in src:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   117
            # 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
   118
            t[k] = v
15976
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   119
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   120
    # remove criss-crossed copies
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   121
    for k, v in t.items():
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   122
        if k in src and v in dst:
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   123
            del t[k]
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   124
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   125
    return t
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   126
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   127
def _tracefile(fctx, am, limit=-1):
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   128
    '''return file context that is the ancestor of fctx present in ancestor
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   129
    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
   130
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   131
    for f in fctx.ancestors():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   132
        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
   133
            return f
23982
751d1138ce35 copies: use linkrev for file tracing limit
Matt Mackall <mpm@selenic.com>
parents: 23980
diff changeset
   134
        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
   135
            return None
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   136
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   137
def _dirstatecopies(d):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   138
    ds = d._repo.dirstate
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   139
    c = ds.copies().copy()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   140
    for k in c.keys():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   141
        if ds[k] not in 'anm':
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   142
            del c[k]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   143
    return c
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   144
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   145
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
   146
    """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
   147
    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
   148
    files _forwardcopies is about to process.
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   149
    """
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   150
    ma = a.manifest()
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   151
    mb = b.manifest()
31256
5a909a8098a1 copies: remove use of manifest.matches
Durham Goode <durham@fb.com>
parents: 30581
diff changeset
   152
    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
   153
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   154
def _forwardcopies(a, b, match=None):
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   155
    '''find {dst@b: src@a} copy mapping where a is an ancestor of b'''
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   156
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   157
    # check for working copy
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   158
    w = None
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   159
    if b.rev() is None:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   160
        w = b
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   161
        b = w.p1()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   162
        if a == b:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   163
            # short-circuit to avoid issues with merge states
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   164
            return _dirstatecopies(w)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   165
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   166
    # 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
   167
    # 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
   168
    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
   169
    if limit is None:
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   170
        limit = -1
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   171
    am = a.manifest()
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   172
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   173
    # find where new files came from
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   174
    # 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
   175
    # 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
   176
    cm = {}
28000
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   177
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   178
    # 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
   179
    # 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
   180
    # 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
   181
    # 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
   182
    # 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
   183
    # this comparison.
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   184
    forwardmissingmatch = match
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   185
    if not match and b.p1() == a and b.p2().node() == node.nullid:
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   186
        forwardmissingmatch = scmutil.matchfiles(a._repo, b.files())
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   187
    missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
d4247c306d82 copies: optimize forward copy detection logic for rebases
Durham Goode <durham@fb.com>
parents: 27876
diff changeset
   188
23980
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   189
    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
   190
    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
   191
        fctx = b[f]
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   192
        fctx._ancestrycontext = ancestrycontext
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   193
        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
   194
        if ofctx:
3cfaace0441e copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents: 18362
diff changeset
   195
            cm[f] = ofctx.path()
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   196
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   197
    # combine copies from dirstate if necessary
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   198
    if w is not None:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   199
        cm = _chain(a, w, cm, _dirstatecopies(w))
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   200
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   201
    return cm
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   202
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   203
def _backwardrenames(a, b):
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   204
    if a._repo.ui.configbool('experimental', 'disablecopytrace'):
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   205
        return {}
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   206
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   207
    # 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
   208
    # 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
   209
    # 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
   210
    f = _forwardcopies(b, a)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   211
    r = {}
18355
2330d97e7707 copies: make the loss in _backwardcopies more stable
Mads Kiilerich <mads@kiilerich.com>
parents: 18136
diff changeset
   212
    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
   213
        # remove copies
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   214
        if v in a:
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   215
            continue
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   216
        r[v] = k
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   217
    return r
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   218
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   219
def pathcopies(x, y, match=None):
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   220
    '''find {dst@y: src@x} copy mapping for directed compare'''
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   221
    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
   222
        return {}
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   223
    a = y.ancestor(x)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   224
    if a == x:
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   225
        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
   226
    if a == y:
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   227
        return _backwardrenames(x, y)
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   228
    return _chain(x, y, _backwardrenames(x, a),
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   229
                  _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
   230
30196
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   231
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
   232
    """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
   233
    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
   234
    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
   235
24625
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   236
    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
   237
    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
   238
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   239
    "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
   240
    done in the graft case.
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   241
    """
24185
3a3806fe3ddf copies: replace _nonoverlap() by calls to manifestdict.filesnotin()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24184
diff changeset
   242
    u1 = sorted(addedinm1 - addedinm2)
3a3806fe3ddf copies: replace _nonoverlap() by calls to manifestdict.filesnotin()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24184
diff changeset
   243
    u2 = sorted(addedinm2 - addedinm1)
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   244
30196
d738cda70894 copies: make it possible to distinguish betwen _computenonoverlap invocations
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30195
diff changeset
   245
    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
   246
    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
   247
        header += ' (from %s)' % baselabel
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   248
    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
   249
        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
   250
    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
   251
        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
   252
    return u1, u2
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   253
26656
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   254
def _makegetfctx(ctx):
30048
91a3c58ecf93 copies: mark checkcopies as internal with the _ prefix
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30047
diff changeset
   255
    """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
   256
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   257
    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
   258
    '_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
   259
    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
   260
    detection. Moreover, having a proper '_ancestrycontext' setup ensures
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   261
    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
   262
    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
   263
    the operation explode (see issue4537).
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   264
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   265
    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
   266
    free to refactor on default.
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   267
    """
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   268
    rev = ctx.rev()
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   269
    repo = ctx._repo
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   270
    ac = getattr(ctx, '_ancestrycontext', None)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   271
    if ac is None:
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   272
        revs = [rev]
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   273
        if rev is None:
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   274
            revs = [p.rev() for p in ctx.parents()]
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   275
        ac = repo.changelog.ancestors(revs, inclusive=True)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   276
        ctx._ancestrycontext = ac
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   277
    def makectx(f, n):
30361
1070df141718 dirstate: change added/modified placeholder hash length to 20 bytes
Durham Goode <durham@fb.com>
parents: 30360
diff changeset
   278
        if n in node.wdirnodes:  # in a working context?
26656
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   279
            if ctx.rev() is None:
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   280
                return ctx.filectx(f)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   281
            return repo[None][f]
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   282
        fctx = repo.filectx(f, fileid=n)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   283
        # 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
   284
        fctx._ancestrycontext = ac
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   285
        fctx._descendantrev = rev
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   286
        return fctx
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   287
    return util.lrucachefunc(makectx)
3e3d783b0d59 copies: factor out setupctx into _makegetfctx
Matt Mackall <mpm@selenic.com>
parents: 26655
diff changeset
   288
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   289
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
   290
    """combine partial copy paths"""
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   291
    remainder = {}
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   292
    for f in copyfrom:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   293
        if f in copyto:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   294
            finalcopy[copyto[f]] = copyfrom[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   295
            del copyto[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   296
    for f in incompletediverge:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   297
        assert f not in diverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   298
        ic = incompletediverge[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   299
        if ic[0] in copyto:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   300
            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
   301
        else:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   302
            remainder[f] = ic
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   303
    return remainder
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   304
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   305
def mergecopies(repo, c1, c2, base):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   306
    """
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   307
    Find moves and copies between context c1 and c2 that are relevant
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   308
    for merging. 'base' will be used as the merge base.
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   309
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   310
    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
   311
    "dirmove".
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   312
16177
b8c1a8a57540 copies: fix mergecopies doc mapping direction
Matt Mackall <mpm@selenic.com>
parents: 16169
diff changeset
   313
    "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
   314
    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
   315
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   316
    "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
   317
    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
   318
    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
   319
    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
   320
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   321
    "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
   322
    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
   323
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   324
    "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
   325
    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
   326
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   327
    "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
   328
    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
   329
    renamed directories.
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   330
    """
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   331
    # 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
   332
    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
   333
        return {}, {}, {}, {}, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   334
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   335
    # avoid silly behavior for parent -> working dir
13878
a8d13ee0ce68 misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents: 12683
diff changeset
   336
    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
   337
        return repo.dirstate.copies(), {}, {}, {}, {}
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   338
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   339
    # 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
   340
    # 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
   341
    # rebase.
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   342
    if repo.ui.configbool('experimental', 'disablecopytrace'):
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   343
        return {}, {}, {}, {}, {}
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   344
30193
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   345
    # 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
   346
    # 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
   347
    # 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
   348
    # 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
   349
    # 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
   350
    # 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
   351
    # determine that here.
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   352
    #
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   353
    # 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
   354
    _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
   355
    _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
   356
    # 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
   357
    # 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
   358
    # keep track of which endpoint is dirty
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   359
    dirtyc1 = not (base == _c1 or base.descendant(_c1))
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   360
    dirtyc2 = not (base== _c2 or base.descendant(_c2))
368e27eb1ffa copies: detect graft-like merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30188
diff changeset
   361
    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
   362
    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
   363
    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
   364
        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
   365
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
   366
    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
   367
    if limit is None:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
   368
        # 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
   369
        return {}, {}, {}, {}, {}
26319
4b9bb1616195 copies: move debug statement to appropriate place
Matt Mackall <mpm@selenic.com>
parents: 26317
diff changeset
   370
    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
   371
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   372
    m1 = c1.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   373
    m2 = c2.manifest()
30186
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   374
    mb = base.manifest()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   375
30185
e2bfe2d52d7a copies: move variable document from checkcopies to mergecopies
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30184
diff changeset
   376
    # 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
   377
    # - 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
   378
    # - 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
   379
    # - 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
   380
    # - 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
   381
    # - 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
   382
    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
   383
    incompletediverge  = {}
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   384
    data1 = {'copy': {},
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   385
             'fullcopy': {},
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   386
             'incomplete': {},
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   387
             'diverge': diverge,
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   388
             '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
   389
            }
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   390
    data2 = {'copy': {},
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   391
             'fullcopy': {},
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   392
             'incomplete': {},
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   393
             'diverge': diverge,
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   394
             '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
   395
            }
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   396
26659
df66736a128e copies: group bothnew with other sets
Matt Mackall <mpm@selenic.com>
parents: 26658
diff changeset
   397
    # 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
   398
    addedinm1 = m1.filesnotin(mb)
f7ed5af31242 mergecopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30185
diff changeset
   399
    addedinm2 = m2.filesnotin(mb)
26659
df66736a128e copies: group bothnew with other sets
Matt Mackall <mpm@selenic.com>
parents: 26658
diff changeset
   400
    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
   401
    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
   402
        # 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
   403
        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
   404
        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
   405
    else:
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   406
        # 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
   407
        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
   408
                                      baselabel='base')
0accd5a5ad04 mergecopies: invoke _computenonoverlap for both base and tca during merges
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30196
diff changeset
   409
        # 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
   410
        # 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
   411
        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
   412
        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
   413
                                                    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
   414
                                      baselabel='topological common ancestor')
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   415
30047
d13a7c8bf0a5 copies: split u1/u2 to u1u/u2u and u1r/u2r
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30046
diff changeset
   416
    for f in u1u:
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   417
        _checkcopies(c1, f, m1, m2, base, tca, dirtyc1, limit, data1)
20989
e8533ec2d222 copies: remove _checkcopies wrapper - it does no good
Mads Kiilerich <madski@unity3d.com>
parents: 20641
diff changeset
   418
30047
d13a7c8bf0a5 copies: split u1/u2 to u1u/u2u and u1r/u2r
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30046
diff changeset
   419
    for f in u2u:
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   420
        _checkcopies(c2, f, m2, m1, base, tca, dirtyc2, limit, data2)
26316
d5618e210191 copies: begin separating mergecopies sides
Matt Mackall <mpm@selenic.com>
parents: 26315
diff changeset
   421
30184
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   422
    copy = dict(data1['copy'].items() + data2['copy'].items())
7321c6b0c9fd checkcopies: pass data as a dictionary of dictionaries
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30183
diff changeset
   423
    fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items())
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   424
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   425
    if dirtyc1:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   426
        _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
   427
                       incompletediverge)
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   428
    else:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   429
        _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
   430
                       incompletediverge)
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   431
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
   432
    renamedelete = {}
26658
aabfa0fb7e3e copies: rename renamedelete to renamedeleteset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26657
diff changeset
   433
    renamedeleteset = set()
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   434
    divergeset = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   435
    for of, fl in 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
   436
        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
   437
            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
   438
            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
   439
                # 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
   440
                # 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
   441
                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
   442
                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
   443
        else:
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   444
            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
   445
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   446
    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
   447
        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
   448
                      % "\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
   449
    bothdiverge = {}
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   450
    bothincompletediverge = {}
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   451
    remainder = {}
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   452
    both1 = {'copy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   453
             'fullcopy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   454
             'incomplete': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   455
             'diverge': bothdiverge,
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   456
             'incompletediverge': bothincompletediverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   457
            }
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   458
    both2 = {'copy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   459
             'fullcopy': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   460
             'incomplete': {},
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   461
             'diverge': bothdiverge,
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   462
             'incompletediverge': bothincompletediverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   463
            }
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   464
    for f in bothnew:
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   465
        _checkcopies(c1, f, m1, m2, base, tca, dirtyc1, limit, both1)
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   466
        _checkcopies(c2, f, m2, m1, 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
   467
    if dirtyc1:
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   468
        # 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
   469
        assert not both2['incomplete']
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   470
        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
   471
                                   bothincompletediverge)
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   472
    elif dirtyc2:
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   473
        assert not both1['incomplete']
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   474
        remainder = _combinecopies({}, both2['incomplete'], copy, bothdiverge,
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   475
                                   bothincompletediverge)
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   476
    else:
30208
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   477
        # 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
   478
        assert not both1['incomplete']
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   479
        assert not both2['incomplete']
87a7c0d403ff copies: improve assertions during copy recombination
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30204
diff changeset
   480
        assert not bothincompletediverge
30202
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   481
    for f in remainder:
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   482
        assert f not in bothdiverge
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   483
        ic = remainder[f]
a005c33d0bd7 mergecopies: add logic to process incomplete data
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30201
diff changeset
   484
        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
   485
            # 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
   486
            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
   487
    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
   488
        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
   489
            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
   490
20990
d9e211a658eb copies: guard debug section with ui.debugflag
Mads Kiilerich <madski@unity3d.com>
parents: 20989
diff changeset
   491
    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
   492
        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
   493
                      "% = renamed and deleted):\n")
18362
5a4f220fbfca copies: report found copies sorted
Mads Kiilerich <mads@kiilerich.com>
parents: 18355
diff changeset
   494
        for f in sorted(fullcopy):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   495
            note = ""
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   496
            if f in copy:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   497
                note += "*"
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   498
            if f in divergeset:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   499
                note += "!"
26658
aabfa0fb7e3e copies: rename renamedelete to renamedeleteset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26657
diff changeset
   500
            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
   501
                note += "%"
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   502
            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
   503
                                                              note))
26317
07ac78ba2e37 copies: rename diverge2 to divergeset for clarity
Matt Mackall <mpm@selenic.com>
parents: 26316
diff changeset
   504
    del divergeset
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   505
16169
c12d4aceba79 copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents: 16168
diff changeset
   506
    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
   507
        return copy, {}, diverge, renamedelete, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   508
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   509
    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
   510
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   511
    # generate a directory move map
16178
828fe2ca7cbb copies: use ctx.dirs() for directory rename detection
Matt Mackall <mpm@selenic.com>
parents: 16177
diff changeset
   512
    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
   513
    # 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
   514
    d1.addpath('/')
d8ff607ef721 scmutil: use new dirs class in dirstate and context
Bryan O'Sullivan <bryano@fb.com>
parents: 18878
diff changeset
   515
    d2.addpath('/')
17055
8b7cd9a998f0 copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents: 16795
diff changeset
   516
    invalid = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   517
    dirmove = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   518
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   519
    # 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
   520
    # 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
   521
    for dst, src in fullcopy.iteritems():
25282
0f28815ef066 copies: switch to using pathutil.dirname
Durham Goode <durham@fb.com>
parents: 24782
diff changeset
   522
        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
   523
        if dsrc in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   524
            # already seen to be uninteresting
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   525
            continue
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   526
        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
   527
            # directory wasn't entirely moved locally
27876
602add6ad9e5 copies: fix detection of divergent directory renames
Matt Mackall <mpm@selenic.com>
parents: 26781
diff changeset
   528
            invalid.add(dsrc + "/")
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   529
        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
   530
            # directory wasn't entirely moved remotely
27876
602add6ad9e5 copies: fix detection of divergent directory renames
Matt Mackall <mpm@selenic.com>
parents: 26781
diff changeset
   531
            invalid.add(dsrc + "/")
602add6ad9e5 copies: fix detection of divergent directory renames
Matt Mackall <mpm@selenic.com>
parents: 26781
diff changeset
   532
        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
   533
            # 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
   534
            invalid.add(dsrc + "/")
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   535
        else:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   536
            # looks good so far
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   537
            dirmove[dsrc + "/"] = ddst + "/"
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   538
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   539
    for i in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   540
        if i in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   541
            del dirmove[i]
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   542
    del d1, d2, invalid
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   543
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   544
    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
   545
        return copy, {}, diverge, renamedelete, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   546
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   547
    for d in dirmove:
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   548
        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
   549
                      (d, dirmove[d]))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   550
30183
0106f93ca1d5 checkcopies: move 'movewithdir' initialisation right before its usage
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30138
diff changeset
   551
    movewithdir = {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   552
    # 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
   553
    for f in u1r + u2r:
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   554
        if f not in fullcopy:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   555
            for d in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   556
                if f.startswith(d):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   557
                    # 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
   558
                    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
   559
                    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
   560
                        movewithdir[f] = df
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   561
                        repo.ui.debug(("   pending file src: '%s' -> "
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   562
                                       "dst: '%s'\n") % (f, df))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   563
                    break
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   564
30581
43a9e02a7b7f graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30361
diff changeset
   565
    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
   566
30138
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   567
def _related(f1, f2, limit):
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   568
    """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
   569
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   570
    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
   571
    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
   572
    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
   573
    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
   574
    """
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   575
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   576
    if f1 == f2:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   577
        return f1 # a match
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   578
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   579
    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
   580
    try:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   581
        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
   582
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   583
        if f1r is None:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   584
            f1 = next(g1)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   585
        if f2r is None:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   586
            f2 = next(g2)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   587
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   588
        while True:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   589
            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
   590
            if f1r > f2r:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   591
                f1 = next(g1)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   592
            elif f2r > f1r:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   593
                f2 = next(g2)
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   594
            elif f1 == f2:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   595
                return f1 # a match
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   596
            elif f1r == f2r or f1r < limit or f2r < limit:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   597
                return False # copy no longer relevant
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   598
    except StopIteration:
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   599
        return False
733fb9f7bc92 checkcopies: extract the '_related' closure
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30137
diff changeset
   600
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   601
def _checkcopies(ctx, f, m1, m2, base, tca, remotebase, limit, data):
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   602
    """
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   603
    check possible copies of f from m1 to m2
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   604
26657
1ae898cfe857 copies: move _makegetfctx calls into checkcopies
Matt Mackall <mpm@selenic.com>
parents: 26656
diff changeset
   605
    ctx = starting context for f in m1
30136
8797eadb5d90 checkcopies: minor change to comment
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30135
diff changeset
   606
    f = the filename to check (as in m1)
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   607
    m1 = the source manifest
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   608
    m2 = the destination manifest
30135
3eae81c0a09d checkcopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30075
diff changeset
   609
    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
   610
    tca = topological common ancestor for graft-like scenarios
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   611
    remotebase = True if base is outside tca::ctx, False otherwise
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   612
    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
   613
    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
   614
12cac1e4d6d9 copies: limit is an optimization, and doesn't provide guarantees
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29216
diff changeset
   615
    note: limit is only an optimization, and there is no guarantee that
12cac1e4d6d9 copies: limit is an optimization, and doesn't provide guarantees
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29216
diff changeset
   616
    irrelevant revisions will not be limited
12cac1e4d6d9 copies: limit is an optimization, and doesn't provide guarantees
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29216
diff changeset
   617
    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
   618
    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
   619
    """
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   620
30135
3eae81c0a09d checkcopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30075
diff changeset
   621
    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
   622
    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
   623
    # 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
   624
    # 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
   625
    # 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
   626
    # 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
   627
    # traversed backwards.
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   628
    #
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   629
    # 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
   630
    # 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
   631
    # 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
   632
    backwards = not remotebase and base != tca and f in mb
26657
1ae898cfe857 copies: move _makegetfctx calls into checkcopies
Matt Mackall <mpm@selenic.com>
parents: 26656
diff changeset
   633
    getfctx = _makegetfctx(ctx)
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   634
30229
69ffbbe73dd0 merge: avoid superfluous filemerges when grafting through renames (issue5407)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30208
diff changeset
   635
    if m1[f] == mb.get(f) and not remotebase:
69ffbbe73dd0 merge: avoid superfluous filemerges when grafting through renames (issue5407)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30208
diff changeset
   636
        # Nothing to merge
69ffbbe73dd0 merge: avoid superfluous filemerges when grafting through renames (issue5407)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30208
diff changeset
   637
        return
69ffbbe73dd0 merge: avoid superfluous filemerges when grafting through renames (issue5407)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30208
diff changeset
   638
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   639
    of = None
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   640
    seen = set([f])
26315
3c6902ed9f07 copies: rename ctx() to getfctx() for clarity
Matt Mackall <mpm@selenic.com>
parents: 26013
diff changeset
   641
    for oc in getfctx(f, m1[f]).ancestors():
25279
708b19c18adf mergecopies: avoid slowdown from linkrev adjustment (issue4680)
Matt Mackall <mpm@selenic.com>
parents: 24782
diff changeset
   642
        ocr = oc.linkrev()
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   643
        of = oc.path()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   644
        if of in seen:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   645
            # 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
   646
            if ocr < limit:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   647
                break
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   648
            continue
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   649
        seen.add(of)
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   650
30195
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   651
        # 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
   652
        if backwards:
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   653
            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
   654
        else:
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   655
            data['fullcopy'][f] = of
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   656
        if of not in m2:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   657
            continue # no match, keep looking
30135
3eae81c0a09d checkcopies: rename 'ca' to 'base'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30075
diff changeset
   658
        if m2[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
   659
            return # no merge needed, quit early
26315
3c6902ed9f07 copies: rename ctx() to getfctx() for clarity
Matt Mackall <mpm@selenic.com>
parents: 26013
diff changeset
   660
        c2 = getfctx(of, m2[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
   661
        # 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
   662
        # unrelated to the droids we are looking for.
30195
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   663
        cr = _related(oc, c2, tca.rev())
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   664
        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
   665
            if backwards:
88626de195f8 copies: make _checkcopies handle simple renames in a rotated DAG
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30194
diff changeset
   666
                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
   667
            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
   668
                data['copy'][f] = of
30203
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   669
            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
   670
                data['copy'][of] = f
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   671
                del data['fullcopy'][f]
b94b92f0c683 checkcopies: add logic to handle remotebase
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30202
diff changeset
   672
                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
   673
            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
   674
                for sf in seen:
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   675
                    if sf in mb:
856ead835f56 checkcopies: handle divergences contained entirely in tca::ctx
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30197
diff changeset
   676
                        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
   677
                        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
   678
                        break
30075
2c8ec8c2ddfe copies: don't record divergence for files needing no merge
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30048
diff changeset
   679
            return
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   680
30204
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   681
    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
   682
        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
   683
            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
   684
        else:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   685
            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
   686
                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
   687
                    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
   688
                        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
   689
                    else:
1894c830ee74 copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30203
diff changeset
   690
                        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
   691
                    return
22901
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   692
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   693
def duplicatecopies(repo, rev, fromrev, skiprev=None):
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   694
    '''reproduce copies from fromrev to rev in the dirstate
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   695
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   696
    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
   697
    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
   698
    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
   699
    copies between fromrev and rev.
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   700
    '''
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   701
    exclude = {}
26013
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   702
    if (skiprev is not None and
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   703
        not repo.ui.configbool('experimental', 'disablecopytrace')):
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   704
        # disablecopytrace skips this line, but not the entire function because
38f92d12357c copy: add flag for disabling copy tracing
Durham Goode <durham@fb.com>
parents: 25924
diff changeset
   705
        # 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
   706
        # 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
   707
        # metadata across the rebase anyway).
22901
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   708
        exclude = pathcopies(repo[fromrev], repo[skiprev])
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   709
    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
   710
        # 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
   711
        # actually be in the dirstate
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   712
        if dst in exclude:
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   713
            continue
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   714
        if repo.dirstate[dst] in "nma":
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   715
            repo.dirstate.copy(src, dst)