mercurial/copies.py
author Pierre-Yves David <pierre-yves.david@fb.com>
Tue, 30 Jun 2015 22:39:28 -0700
changeset 25694 5ede49f4383a
parent 25289 6ac860f700b5
child 25924 cfc24c22454e
permissions -rw-r--r--
amend: stop updating the bookmarks twice There was code to move the bookmarks around both in the 'cmdutil' help and in the main 'commit' function. We kill the 'commit' version as it is performed outside the transaction. The debug note is moved into cmdutil.
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
25282
0f28815ef066 copies: switch to using pathutil.dirname
Durham Goode <durham@fb.com>
parents: 24782
diff changeset
     8
import util, pathutil
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
     9
import heapq
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    10
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    11
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
    12
    """
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    13
    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
    14
    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
    15
    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
    16
    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
    17
    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
    18
    None if no such revision exists.
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    19
    """
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    20
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    21
    # basic idea:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    22
    # - mark a and b with different sides
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    23
    # - 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
    24
    #   on that side, otherwise it is on no side
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    25
    # - 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
    26
    #   - add unseen parents to side map
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    27
    #   - 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
    28
    #   - 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
    29
    #   - track the lowest interesting rev seen
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    30
    #   - quit when interesting revs is zero
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    31
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    32
    cl = repo.changelog
6750
fb42030d79d6 add __len__ and __iter__ methods to repo and revlog
Matt Mackall <mpm@selenic.com>
parents: 6646
diff changeset
    33
    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
    34
    if a is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    35
        a = working
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    36
    if b is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    37
        b = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    38
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    39
    side = {a: -1, b: 1}
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    40
    visit = [-a, -b]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    41
    heapq.heapify(visit)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    42
    interesting = len(visit)
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    43
    hascommonancestor = False
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    44
    limit = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    45
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    46
    while interesting:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    47
        r = -heapq.heappop(visit)
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    48
        if r == working:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    49
            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
    50
        else:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    51
            parents = cl.parentrevs(r)
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    52
        for p in parents:
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    53
            if p < 0:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    54
                continue
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    55
            if p not in side:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    56
                # first time we see p; add it to visit
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    57
                side[p] = side[r]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    58
                if side[p]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    59
                    interesting += 1
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    60
                heapq.heappush(visit, -p)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    61
            elif side[p] and side[p] != side[r]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    62
                # p was interesting but now we know better
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    63
                side[p] = 0
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    64
                interesting -= 1
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    65
                hascommonancestor = True
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    66
        if side[r]:
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    67
            limit = r # lowest rev visited
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    68
            interesting -= 1
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    69
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    70
    if not hascommonancestor:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    71
        return None
23071
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    72
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    73
    # 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
    74
    # 1/ File 'a0' committed
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    75
    # 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
    76
    # 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
    77
    # 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
    78
    # 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
    79
    #
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    80
    # 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
    81
    #
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    82
    # @  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
    83
    # |
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    84
    # o  2 a1-amend
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    85
    # |
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    86
    # | o  1 a1
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
    # o  0 a0
652ab726ba93 amend: fix amending rename commit with diverged topologies (issue4405)
Ryan McElroy <rmcelroy@fb.com>
parents: 22901
diff changeset
    89
    #
23139
e53f6b72a0e4 spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents: 23071
diff changeset
    90
    # 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
    91
    # 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
    92
    # 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
    93
    # 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
    94
    return min(limit, a, b)
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    95
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    96
def _chain(src, dst, a, b):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    97
    '''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
    98
    t = a.copy()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    99
    for k, v in b.iteritems():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   100
        if v in t:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   101
            # found a chain
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   102
            if t[v] != k:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   103
                # 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
   104
                t[k] = t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   105
            if v not in dst:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   106
                # 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
   107
                del t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   108
        if v in src:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   109
            # 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
   110
            t[k] = v
15976
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   111
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   112
    # remove criss-crossed copies
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   113
    for k, v in t.items():
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   114
        if k in src and v in dst:
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   115
            del t[k]
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
   116
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   117
    return t
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   118
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   119
def _tracefile(fctx, am, limit=-1):
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   120
    '''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
   121
    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
   122
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   123
    for f in fctx.ancestors():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   124
        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
   125
            return f
23982
751d1138ce35 copies: use linkrev for file tracing limit
Matt Mackall <mpm@selenic.com>
parents: 23980
diff changeset
   126
        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
   127
            return None
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   128
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   129
def _dirstatecopies(d):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   130
    ds = d._repo.dirstate
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   131
    c = ds.copies().copy()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   132
    for k in c.keys():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   133
        if ds[k] not in 'anm':
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   134
            del c[k]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   135
    return c
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   136
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   137
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
   138
    """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
   139
    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
   140
    files _forwardcopies is about to process.
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   141
    """
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   142
    ma = a.manifest()
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   143
    mb = b.manifest()
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   144
    if match:
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   145
        ma = ma.matches(match)
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   146
        mb = mb.matches(match)
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   147
    return mb.filesnotin(ma)
24011
d7d08337b3f6 copy: move _forwardcopies file logic to a function
Durham Goode <durham@fb.com>
parents: 24010
diff changeset
   148
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   149
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
   150
    '''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
   151
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   152
    # check for working copy
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   153
    w = None
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   154
    if b.rev() is None:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   155
        w = b
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   156
        b = w.p1()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   157
        if a == b:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   158
            # 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
   159
            return _dirstatecopies(w)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   160
20294
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   161
    # files might have to be traced back to the fctx parent of the last
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   162
    # one-side-only changeset, but not further back than that
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   163
    limit = _findlimit(a._repo, a.rev(), b.rev())
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   164
    if limit is None:
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   165
        limit = -1
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   166
    am = a.manifest()
243ea5ffdf31 diff: search beyond ancestor when detecting renames
Mads Kiilerich <madski@unity3d.com>
parents: 19178
diff changeset
   167
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   168
    # find where new files came from
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   169
    # we currently don't try to find where old files went, too expensive
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   170
    # this means we can miss a case like 'hg rm b; hg cp a b'
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   171
    cm = {}
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   172
    missing = _computeforwardmissing(a, b, match=match)
23980
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   173
    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
   174
    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
   175
        fctx = b[f]
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   176
        fctx._ancestrycontext = ancestrycontext
c1ce5442453f _adjustlinkrev: reuse ancestors set during rename detection (issue4514)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23139
diff changeset
   177
        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
   178
        if ofctx:
3cfaace0441e copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents: 18362
diff changeset
   179
            cm[f] = ofctx.path()
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   180
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   181
    # combine copies from dirstate if necessary
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   182
    if w is not None:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   183
        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
   184
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   185
    return cm
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   186
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   187
def _backwardrenames(a, b):
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   188
    # 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
   189
    # 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
   190
    # 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
   191
    f = _forwardcopies(b, a)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   192
    r = {}
18355
2330d97e7707 copies: make the loss in _backwardcopies more stable
Mads Kiilerich <mads@kiilerich.com>
parents: 18136
diff changeset
   193
    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
   194
        # remove copies
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   195
        if v in a:
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   196
            continue
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   197
        r[v] = k
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   198
    return r
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   199
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   200
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
   201
    '''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
   202
    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
   203
        return {}
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   204
    a = y.ancestor(x)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   205
    if a == x:
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   206
        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
   207
    if a == y:
18136
f23dea2b296e copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents: 18135
diff changeset
   208
        return _backwardrenames(x, y)
24782
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   209
    return _chain(x, y, _backwardrenames(x, a),
4906dc0e038c copies: add matcher parameter to copy logic
Durham Goode <durham@fb.com>
parents: 24625
diff changeset
   210
                  _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
   211
24625
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   212
def _computenonoverlap(repo, c1, c2, addedinm1, addedinm2):
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   213
    """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
   214
    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
   215
    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
   216
24625
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   217
    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
   218
    other extensions for being able to read the file nodes of the changed files.
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   219
    """
24185
3a3806fe3ddf copies: replace _nonoverlap() by calls to manifestdict.filesnotin()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24184
diff changeset
   220
    u1 = sorted(addedinm1 - addedinm2)
3a3806fe3ddf copies: replace _nonoverlap() by calls to manifestdict.filesnotin()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24184
diff changeset
   221
    u2 = sorted(addedinm2 - addedinm1)
24010
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   222
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   223
    if u1:
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   224
        repo.ui.debug("  unmatched files in local:\n   %s\n"
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   225
                      % "\n   ".join(u1))
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   226
    if u2:
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   227
        repo.ui.debug("  unmatched files in other:\n   %s\n"
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   228
                      % "\n   ".join(u2))
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   229
    return u1, u2
a63c2b159df4 copy: move mergecopies file logic to a function
Durham Goode <durham@fb.com>
parents: 23982
diff changeset
   230
16169
c12d4aceba79 copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents: 16168
diff changeset
   231
def mergecopies(repo, c1, c2, ca):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   232
    """
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   233
    Find moves and copies between context c1 and c2 that are relevant
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   234
    for merging.
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   235
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   236
    Returns four dicts: "copy", "movewithdir", "diverge", and
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   237
    "renamedelete".
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   238
16177
b8c1a8a57540 copies: fix mergecopies doc mapping direction
Matt Mackall <mpm@selenic.com>
parents: 16169
diff changeset
   239
    "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
   240
    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
   241
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   242
    "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
   243
    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
   244
    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
   245
    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
   246
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   247
    "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
   248
    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
   249
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   250
    "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
   251
    names for files deleted in c1 that were renamed in c2 or vice-versa.
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   252
    """
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   253
    # 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
   254
    if not c1 or not c2 or c1 == c2:
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   255
        return {}, {}, {}, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   256
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   257
    # avoid silly behavior for parent -> working dir
13878
a8d13ee0ce68 misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents: 12683
diff changeset
   258
    if c2.node() is None and c1.node() == repo.dirstate.p1():
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   259
        return repo.dirstate.copies(), {}, {}, {}
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   260
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
   261
    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
   262
    if limit is None:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
   263
        # no common ancestor, no copies
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   264
        return {}, {}, {}, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   265
    m1 = c1.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   266
    m2 = c2.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   267
    ma = ca.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   268
24412
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   269
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   270
    def setupctx(ctx):
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   271
        """return a 'makectx' function suitable for checkcopies usage from ctx
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   272
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   273
        We have to re-setup the function building 'filectx' for each
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   274
        'checkcopies' to ensure the linkrev adjustement is properly setup for
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   275
        each. Linkrev adjustment is important to avoid bug in rename
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   276
        detection. Moreover, having a proper '_ancestrycontext' setup ensures
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   277
        the performance impact of this adjustment is kept limited. Without it,
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   278
        each file could do a full dag traversal making the time complexity of
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   279
        the operation explode (see issue4537).
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   280
24412
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   281
        This function exists here mostly to limit the impact on stable. Feel
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   282
        free to refactor on default.
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   283
        """
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   284
        rev = ctx.rev()
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   285
        ac = getattr(ctx, '_ancestrycontext', None)
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   286
        if ac is None:
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   287
            revs = [rev]
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   288
            if rev is None:
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   289
                revs = [p.rev() for p in ctx.parents()]
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   290
            ac = ctx._repo.changelog.ancestors(revs, inclusive=True)
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   291
            ctx._ancestrycontext = ac
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   292
        def makectx(f, n):
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   293
            if len(n) != 20:  # in a working context?
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   294
                if c1.rev() is None:
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   295
                    return c1.filectx(f)
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   296
                return c2.filectx(f)
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   297
            fctx = repo.filectx(f, fileid=n)
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   298
            # setup only needed for filectx not create from a changectx
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   299
            fctx._ancestrycontext = ac
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   300
            fctx._descendantrev = rev
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   301
            return fctx
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   302
        return util.lrucachefunc(makectx)
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   303
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   304
    copy = {}
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   305
    movewithdir = {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   306
    fullcopy = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   307
    diverge = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   308
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   309
    repo.ui.debug("  searching for copies back to rev %d\n" % limit)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   310
24187
30219bd46ed7 copies: only calculate 'addedinm[12]' sets once
Martin von Zweigbergk <martinvonz@google.com>
parents: 24186
diff changeset
   311
    addedinm1 = m1.filesnotin(ma)
30219bd46ed7 copies: only calculate 'addedinm[12]' sets once
Martin von Zweigbergk <martinvonz@google.com>
parents: 24186
diff changeset
   312
    addedinm2 = m2.filesnotin(ma)
24625
2cebf17c0fcc copies: pass changectx instead of manifest to _computenonoverlap
Durham Goode <durham@fb.com>
parents: 24415
diff changeset
   313
    u1, u2 = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   314
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   315
    for f in u1:
24412
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   316
        ctx = setupctx(c1)
20989
e8533ec2d222 copies: remove _checkcopies wrapper - it does no good
Mads Kiilerich <madski@unity3d.com>
parents: 20641
diff changeset
   317
        checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy)
e8533ec2d222 copies: remove _checkcopies wrapper - it does no good
Mads Kiilerich <madski@unity3d.com>
parents: 20641
diff changeset
   318
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   319
    for f in u2:
24412
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   320
        ctx = setupctx(c2)
20989
e8533ec2d222 copies: remove _checkcopies wrapper - it does no good
Mads Kiilerich <madski@unity3d.com>
parents: 20641
diff changeset
   321
        checkcopies(ctx, f, m2, m1, ca, limit, diverge, copy, fullcopy)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   322
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
    renamedelete = {}
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
   324
    renamedelete2 = set()
8152
08e1baf924ca replace set-like dictionaries with real sets
Martin Geisler <mg@lazybytes.net>
parents: 7873
diff changeset
   325
    diverge2 = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   326
    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
   327
        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
   328
            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
   329
            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
   330
                # 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
   331
                # 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
   332
                renamedelete[of] = [f for f in fl if f in c1 or f in c2]
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
   333
                renamedelete2.update(fl) # reverse map for below
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   334
        else:
8152
08e1baf924ca replace set-like dictionaries with real sets
Martin Geisler <mg@lazybytes.net>
parents: 7873
diff changeset
   335
            diverge2.update(fl) # reverse map for below
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   336
24186
61aadba2396e copies: calculate 'bothnew' from manifestdict.filesnotin()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24185
diff changeset
   337
    bothnew = sorted(addedinm1 & addedinm2)
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   338
    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
   339
        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
   340
                      % "\n   ".join(bothnew))
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   341
    bothdiverge, _copy, _fullcopy = {}, {}, {}
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   342
    for f in bothnew:
24412
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   343
        ctx = setupctx(c1)
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   344
        checkcopies(ctx, f, m1, m2, ca, limit, bothdiverge, _copy, _fullcopy)
24412
9372180b8c9b mergecopies: reuse ancestry context when traversing file history (issue4537)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23982
diff changeset
   345
        ctx = setupctx(c2)
20641
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   346
        checkcopies(ctx, f, m2, m1, ca, limit, bothdiverge, _copy, _fullcopy)
3db9e798e004 copies: when both sides made the same copy, report it as a copy
Mads Kiilerich <madski@unity3d.com>
parents: 20294
diff changeset
   347
    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
   348
        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
   349
            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
   350
20990
d9e211a658eb copies: guard debug section with ui.debugflag
Mads Kiilerich <madski@unity3d.com>
parents: 20989
diff changeset
   351
    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
   352
        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
   353
                      "% = renamed and deleted):\n")
18362
5a4f220fbfca copies: report found copies sorted
Mads Kiilerich <mads@kiilerich.com>
parents: 18355
diff changeset
   354
        for f in sorted(fullcopy):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   355
            note = ""
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   356
            if f in copy:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   357
                note += "*"
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   358
            if f in diverge2:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   359
                note += "!"
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
   360
            if f in renamedelete2:
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
   361
                note += "%"
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   362
            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
   363
                                                              note))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   364
    del diverge2
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   365
16169
c12d4aceba79 copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents: 16168
diff changeset
   366
    if not fullcopy:
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   367
        return copy, movewithdir, diverge, renamedelete
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   368
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   369
    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
   370
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   371
    # generate a directory move map
16178
828fe2ca7cbb copies: use ctx.dirs() for directory rename detection
Matt Mackall <mpm@selenic.com>
parents: 16177
diff changeset
   372
    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
   373
    # 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
   374
    d1.addpath('/')
d8ff607ef721 scmutil: use new dirs class in dirstate and context
Bryan O'Sullivan <bryano@fb.com>
parents: 18878
diff changeset
   375
    d2.addpath('/')
17055
8b7cd9a998f0 copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents: 16795
diff changeset
   376
    invalid = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   377
    dirmove = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   378
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   379
    # 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
   380
    # 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
   381
    for dst, src in fullcopy.iteritems():
25282
0f28815ef066 copies: switch to using pathutil.dirname
Durham Goode <durham@fb.com>
parents: 24782
diff changeset
   382
        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
   383
        if dsrc in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   384
            # already seen to be uninteresting
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   385
            continue
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   386
        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
   387
            # directory wasn't entirely moved locally
8468
b35d11d10646 copies: use set instead of dict
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8337
diff changeset
   388
            invalid.add(dsrc)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   389
        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
   390
            # directory wasn't entirely moved remotely
8468
b35d11d10646 copies: use set instead of dict
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8337
diff changeset
   391
            invalid.add(dsrc)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   392
        elif dsrc in dirmove and dirmove[dsrc] != ddst:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   393
            # files from the same directory moved to two different places
8468
b35d11d10646 copies: use set instead of dict
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8337
diff changeset
   394
            invalid.add(dsrc)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   395
        else:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   396
            # looks good so far
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   397
            dirmove[dsrc + "/"] = ddst + "/"
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   398
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   399
    for i in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   400
        if i in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   401
            del dirmove[i]
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   402
    del d1, d2, invalid
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   403
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   404
    if not dirmove:
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   405
        return copy, movewithdir, diverge, renamedelete
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   406
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   407
    for d in dirmove:
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   408
        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
   409
                      (d, dirmove[d]))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   410
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   411
    # check unaccounted nonoverlapping files against directory moves
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   412
    for f in u1 + u2:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   413
        if f not in fullcopy:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   414
            for d in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   415
                if f.startswith(d):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   416
                    # 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
   417
                    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
   418
                    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
   419
                        movewithdir[f] = df
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   420
                        repo.ui.debug(("   pending file src: '%s' -> "
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   421
                                       "dst: '%s'\n") % (f, df))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   422
                    break
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   423
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   424
    return copy, movewithdir, diverge, renamedelete
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   425
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   426
def checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy):
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   427
    """
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   428
    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
   429
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   430
    ctx = function accepting (filename, node) that returns a filectx.
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   431
    f = the filename to check
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   432
    m1 = the source manifest
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   433
    m2 = the destination manifest
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   434
    ca = the changectx of the common ancestor
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   435
    limit = the rev number to not search beyond
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   436
    diverge = record all diverges in this dict
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   437
    copy = record all non-divergent copies in this dict
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   438
    fullcopy = record all copies in this dict
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   439
    """
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   440
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   441
    ma = ca.manifest()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   442
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   443
    def _related(f1, f2, limit):
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   444
        # Walk back to common ancestor to see if the two files originate
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   445
        # from the same file. Since workingfilectx's rev() is None it messes
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   446
        # up the integer comparison logic, hence the pre-step check for
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   447
        # None (f1 and f2 can only be workingfilectx's initially).
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   448
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   449
        if f1 == f2:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   450
            return f1 # a match
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   451
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   452
        g1, g2 = f1.ancestors(), f2.ancestors()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   453
        try:
25279
708b19c18adf mergecopies: avoid slowdown from linkrev adjustment (issue4680)
Matt Mackall <mpm@selenic.com>
parents: 24782
diff changeset
   454
            f1r, f2r = f1.linkrev(), f2.linkrev()
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   455
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   456
            if f1r is None:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   457
                f1 = g1.next()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   458
            if f2r is None:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   459
                f2 = g2.next()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   460
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   461
            while True:
25279
708b19c18adf mergecopies: avoid slowdown from linkrev adjustment (issue4680)
Matt Mackall <mpm@selenic.com>
parents: 24782
diff changeset
   462
                f1r, f2r = f1.linkrev(), f2.linkrev()
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   463
                if f1r > f2r:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   464
                    f1 = g1.next()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   465
                elif f2r > f1r:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   466
                    f2 = g2.next()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   467
                elif f1 == f2:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   468
                    return f1 # a match
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   469
                elif f1r == f2r or f1r < limit or f2r < limit:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   470
                    return False # copy no longer relevant
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   471
        except StopIteration:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   472
            return False
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   473
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   474
    of = None
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   475
    seen = set([f])
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   476
    for oc in ctx(f, m1[f]).ancestors():
25279
708b19c18adf mergecopies: avoid slowdown from linkrev adjustment (issue4680)
Matt Mackall <mpm@selenic.com>
parents: 24782
diff changeset
   477
        ocr = oc.linkrev()
19178
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   478
        of = oc.path()
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   479
        if of in seen:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   480
            # 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
   481
            if ocr < limit:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   482
                break
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   483
            continue
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   484
        seen.add(of)
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   485
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   486
        fullcopy[f] = of # remember for dir rename detection
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   487
        if of not in m2:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   488
            continue # no match, keep looking
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   489
        if m2[of] == ma.get(of):
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   490
            break # no merge needed, quit early
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   491
        c2 = ctx(of, m2[of])
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   492
        cr = _related(oc, c2, ca.rev())
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   493
        if cr and (of == f or of == c2.path()): # non-divergent
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   494
            copy[f] = of
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   495
            of = None
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   496
            break
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   497
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   498
    if of in ma:
4327687ca757 copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents: 18899
diff changeset
   499
        diverge.setdefault(of, []).append(f)
22901
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   500
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   501
def duplicatecopies(repo, rev, fromrev, skiprev=None):
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   502
    '''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
   503
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   504
    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
   505
    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
   506
    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
   507
    copies between fromrev and rev.
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   508
    '''
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   509
    exclude = {}
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   510
    if skiprev is not None:
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   511
        exclude = pathcopies(repo[fromrev], repo[skiprev])
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   512
    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
   513
        # 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
   514
        # actually be in the dirstate
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   515
        if dst in exclude:
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   516
            continue
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   517
        if repo.dirstate[dst] in "nma":
722117c8e023 duplicatecopies: move from cmdutil to copies
Matt Mackall <mpm@selenic.com>
parents: 20990
diff changeset
   518
            repo.dirstate.copy(src, dst)