mercurial/copies.py
author Siddharth Agarwal <sid0@fb.com>
Wed, 26 Dec 2012 15:03:58 -0800
changeset 18135 a6fe1b9cc68f
parent 18134 6c35b53cd28b
child 18136 f23dea2b296e
permissions -rw-r--r--
copies: make debug messages more sensible The -> in debug messages is currently overloaded to mean both source to dest and dest to source. To fix this, we add explicit labels and make the arrow direction consistent.
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
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
     8
import util
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
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
def _nonoverlap(d1, d2, d3):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
    "Return list of elements in d1 not in d2 or d3"
8209
a1a5a57efe90 replace util.sort with sorted built-in
Matt Mackall <mpm@selenic.com>
parents: 8152
diff changeset
    13
    return sorted([d for d in d1 if d not in d3 and d not in d2])
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
def _dirname(f):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    16
    s = f.rfind("/")
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
    if s == -1:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    18
        return ""
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
    return f[:s]
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    21
def _findlimit(repo, a, b):
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    22
    """Find the earliest revision that's an ancestor of a or b but not both,
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    23
    None if no such revision exists.
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    24
    """
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    25
    # basic idea:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    26
    # - mark a and b with different sides
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    27
    # - 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
    28
    #   on that side, otherwise it is on no side
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    29
    # - 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
    30
    #   - add unseen parents to side map
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    31
    #   - 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
    32
    #   - 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
    33
    #   - track the lowest interesting rev seen
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    34
    #   - quit when interesting revs is zero
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    35
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    36
    cl = repo.changelog
6750
fb42030d79d6 add __len__ and __iter__ methods to repo and revlog
Matt Mackall <mpm@selenic.com>
parents: 6646
diff changeset
    37
    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
    38
    if a is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    39
        a = working
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    40
    if b is None:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    41
        b = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    42
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    43
    side = {a: -1, b: 1}
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    44
    visit = [-a, -b]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    45
    heapq.heapify(visit)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    46
    interesting = len(visit)
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    47
    hascommonancestor = False
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    48
    limit = working
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    49
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    50
    while interesting:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    51
        r = -heapq.heappop(visit)
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    52
        if r == working:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    53
            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
    54
        else:
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    55
            parents = cl.parentrevs(r)
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    56
        for p in parents:
10179
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    57
            if p < 0:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    58
                continue
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    59
            if p not in side:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    60
                # first time we see p; add it to visit
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    61
                side[p] = side[r]
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    62
                if side[p]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    63
                    interesting += 1
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    64
                heapq.heappush(visit, -p)
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    65
            elif side[p] and side[p] != side[r]:
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    66
                # p was interesting but now we know better
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    67
                side[p] = 0
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
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
                hascommonancestor = True
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
diff changeset
    70
        if side[r]:
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    71
            limit = r # lowest rev visited
6430
a6a66e812c34 copies: teach symmetric difference about working revisions
Matt Mackall <mpm@selenic.com>
parents: 6429
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
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    74
    if not hascommonancestor:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
    75
        return None
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
    76
    return limit
6429
532ca442b903 symmetricdifference: move back to copies
Matt Mackall <mpm@selenic.com>
parents: 6426
diff changeset
    77
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    78
def _chain(src, dst, a, b):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    79
    '''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
    80
    t = a.copy()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    81
    for k, v in b.iteritems():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    82
        if v in t:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    83
            # found a chain
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    84
            if t[v] != k:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    85
                # 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
    86
                t[k] = t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    87
            if v not in dst:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    88
                # 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
    89
                del t[v]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    90
        if v in src:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    91
            # 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
    92
            t[k] = v
15976
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
    93
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
    94
    # remove criss-crossed copies
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
    95
    for k, v in t.items():
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
    96
        if k in src and v in dst:
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
    97
            del t[k]
d1c74c6151c9 copies: eliminate criss-crosses when chaining
Matt Mackall <mpm@selenic.com>
parents: 15775
diff changeset
    98
15775
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
    99
    return t
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   100
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   101
def _tracefile(fctx, actx):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   102
    '''return file context that is the ancestor of fctx present in actx'''
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   103
    stop = actx.rev()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   104
    am = actx.manifest()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   105
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   106
    for f in fctx.ancestors():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   107
        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
   108
            return f
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   109
        if f.rev() < stop:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   110
            return None
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   111
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   112
def _dirstatecopies(d):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   113
    ds = d._repo.dirstate
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   114
    c = ds.copies().copy()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   115
    for k in c.keys():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   116
        if ds[k] not in 'anm':
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   117
            del c[k]
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   118
    return c
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   119
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   120
def _forwardcopies(a, b):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   121
    '''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
   122
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   123
    # check for working copy
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   124
    w = None
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   125
    if b.rev() is None:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   126
        w = b
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   127
        b = w.p1()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   128
        if a == b:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   129
            # 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
   130
            return _dirstatecopies(w)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   131
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   132
    # find where new files came from
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   133
    # 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
   134
    # 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
   135
    cm = {}
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   136
    for f in b:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   137
        if f not in a:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   138
            ofctx = _tracefile(b[f], a)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   139
            if ofctx:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   140
                cm[f] = ofctx.path()
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   141
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   142
    # combine copies from dirstate if necessary
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   143
    if w is not None:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   144
        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
   145
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   146
    return cm
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   147
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   148
def _backwardcopies(a, b):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   149
    # because the forward mapping is 1:n, we can lose renames here
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   150
    # in particular, we find renames better than copies
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   151
    f = _forwardcopies(b, a)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   152
    r = {}
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   153
    for k, v in f.iteritems():
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   154
        r[v] = k
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   155
    return r
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
def pathcopies(x, y):
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   158
    '''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
   159
    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
   160
        return {}
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   161
    a = y.ancestor(x)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   162
    if a == x:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   163
        return _forwardcopies(x, y)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   164
    if a == y:
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   165
        return _backwardcopies(x, y)
91eb4512edd0 copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents: 15774
diff changeset
   166
    return _chain(x, y, _backwardcopies(x, a), _forwardcopies(a, y))
15774
0bd17a4bed88 copies: split the copies api for "normal" and merge cases (API)
Matt Mackall <mpm@selenic.com>
parents: 14494
diff changeset
   167
16169
c12d4aceba79 copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents: 16168
diff changeset
   168
def mergecopies(repo, c1, c2, ca):
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
    """
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   170
    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
   171
    for merging.
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   172
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   173
    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
   174
    "renamedelete".
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   175
16177
b8c1a8a57540 copies: fix mergecopies doc mapping direction
Matt Mackall <mpm@selenic.com>
parents: 16169
diff changeset
   176
    "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
   177
    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
   178
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   179
    "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
   180
    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
   181
    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
   182
    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
   183
16168
7bbabfe25321 copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents: 15994
diff changeset
   184
    "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
   185
    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
   186
98687cdddcb1 merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16792
diff changeset
   187
    "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
   188
    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
   189
    """
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   190
    # 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
   191
    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
   192
        return {}, {}, {}, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   194
    # avoid silly behavior for parent -> working dir
13878
a8d13ee0ce68 misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents: 12683
diff changeset
   195
    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
   196
        return repo.dirstate.copies(), {}, {}, {}
6646
9eb274d773d9 copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents: 6431
diff changeset
   197
6431
a42d8d3e6ea9 copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents: 6430
diff changeset
   198
    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
   199
    if limit is None:
83cfa1baf8ad copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents: 9467
diff changeset
   200
        # 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
   201
        return {}, {}, {}, {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   202
    m1 = c1.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   203
    m2 = c2.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   204
    ma = ca.manifest()
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   205
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   206
    def makectx(f, n):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   207
        if len(n) != 20: # in a working context?
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   208
            if c1.rev() is None:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   209
                return c1.filectx(f)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   210
            return c2.filectx(f)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   211
        return repo.filectx(f, fileid=n)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   212
9097
431462bd8478 fix memory usage of revlog caches by limiting cache size [issue1639]
Matt Mackall <mpm@selenic.com>
parents: 8527
diff changeset
   213
    ctx = util.lrucachefunc(makectx)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
    copy = {}
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   215
    movewithdir = {}
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   216
    fullcopy = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   217
    diverge = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   218
10262
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   219
    def related(f1, f2, limit):
10874
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   220
        # Walk back to common ancestor to see if the two files originate
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   221
        # from the same file. Since workingfilectx's rev() is None it messes
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   222
        # up the integer comparison logic, hence the pre-step check for
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   223
        # None (f1 and f2 can only be workingfilectx's initially).
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   224
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   225
        if f1 == f2:
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   226
            return f1 # a match
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   227
10262
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   228
        g1, g2 = f1.ancestors(), f2.ancestors()
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   229
        try:
10874
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   230
            f1r, f2r = f1.rev(), f2.rev()
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   231
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   232
            if f1r is None:
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   233
                f1 = g1.next()
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   234
            if f2r is None:
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   235
                f2 = g2.next()
4f11978ae45d copies: properly visit file context ancestors on working file contexts
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 10463
diff changeset
   236
14494
1ffeeb91c55d check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents: 13878
diff changeset
   237
            while True:
10262
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   238
                f1r, f2r = f1.rev(), f2.rev()
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   239
                if f1r > f2r:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   240
                    f1 = g1.next()
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   241
                elif f2r > f1r:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   242
                    f2 = g2.next()
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   243
                elif f1 == f2:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   244
                    return f1 # a match
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   245
                elif f1r == f2r or f1r < limit or f2r < limit:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   246
                    return False # copy no longer relevant
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   247
        except StopIteration:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   248
            return False
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   249
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   250
    def checkcopies(f, m1, m2):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   251
        '''check possible copies of f from m1 to m2'''
10262
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   252
        of = None
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   253
        seen = set([f])
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   254
        for oc in ctx(f, m1[f]).ancestors():
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   255
            ocr = oc.rev()
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   256
            of = oc.path()
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   257
            if of in seen:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   258
                # check limit late - grab last rename before
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   259
                if ocr < limit:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   260
                    break
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   261
                continue
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   262
            seen.add(of)
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   263
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   264
            fullcopy[f] = of # remember for dir rename detection
10262
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   265
            if of not in m2:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   266
                continue # no match, keep looking
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   267
            if m2[of] == ma.get(of):
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   268
                break # no merge needed, quit early
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   269
            c2 = ctx(of, m2[of])
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   270
            cr = related(oc, c2, ca.rev())
10313
31141fd7c9cc copies: check if revisions are related (bug found with pylint)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10302
diff changeset
   271
            if cr and (of == f or of == c2.path()): # non-divergent
10262
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   272
                copy[f] = of
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   273
                of = None
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   274
                break
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   275
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   276
        if of in ma:
eb243551cbd8 copies: speed up copy detection
Matt Mackall <mpm@selenic.com>
parents: 10179
diff changeset
   277
            diverge.setdefault(of, []).append(f)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   278
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   279
    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
   280
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   281
    u1 = _nonoverlap(m1, m2, ma)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   282
    u2 = _nonoverlap(m2, m1, ma)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   283
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   284
    if u1:
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   285
        repo.ui.debug("  unmatched files in local:\n   %s\n"
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   286
                      % "\n   ".join(u1))
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   287
    if u2:
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   288
        repo.ui.debug("  unmatched files in other:\n   %s\n"
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   289
                      % "\n   ".join(u2))
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   290
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   291
    for f in u1:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   292
        checkcopies(f, m1, m2)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   293
    for f in u2:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   294
        checkcopies(f, m2, m1)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   295
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
   296
    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
   297
    renamedelete2 = set()
8152
08e1baf924ca replace set-like dictionaries with real sets
Martin Geisler <mg@lazybytes.net>
parents: 7873
diff changeset
   298
    diverge2 = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   299
    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
   300
        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
   301
            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
   302
            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
   303
                # 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
   304
                # 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
   305
                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
   306
                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
   307
        else:
8152
08e1baf924ca replace set-like dictionaries with real sets
Martin Geisler <mg@lazybytes.net>
parents: 7873
diff changeset
   308
            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
   309
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   310
    if fullcopy:
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
   311
        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
   312
                      "% = renamed and deleted):\n")
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   313
        for f in fullcopy:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   314
            note = ""
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   315
            if f in copy:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   316
                note += "*"
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   317
            if f in diverge2:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   318
                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
   319
            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
   320
                note += "%"
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   321
            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
   322
                                                              note))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   323
    del diverge2
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   324
16169
c12d4aceba79 copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents: 16168
diff changeset
   325
    if not fullcopy:
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   326
        return copy, movewithdir, diverge, renamedelete
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   327
9467
4c041f1ee1b4 do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents: 9102
diff changeset
   328
    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
   329
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   330
    # generate a directory move map
16178
828fe2ca7cbb copies: use ctx.dirs() for directory rename detection
Matt Mackall <mpm@selenic.com>
parents: 16177
diff changeset
   331
    d1, d2 = c1.dirs(), c2.dirs()
17055
8b7cd9a998f0 copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents: 16795
diff changeset
   332
    d1.add('')
8b7cd9a998f0 copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents: 16795
diff changeset
   333
    d2.add('')
8b7cd9a998f0 copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents: 16795
diff changeset
   334
    invalid = set()
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   335
    dirmove = {}
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   336
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   337
    # 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
   338
    # 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
   339
    for dst, src in fullcopy.iteritems():
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   340
        dsrc, ddst = _dirname(src), _dirname(dst)
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   341
        if dsrc in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   342
            # already seen to be uninteresting
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   343
            continue
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   344
        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
   345
            # 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
   346
            invalid.add(dsrc)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   347
        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
   348
            # 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
   349
            invalid.add(dsrc)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   350
        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
   351
            # 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
   352
            invalid.add(dsrc)
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   353
        else:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   354
            # looks good so far
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   355
            dirmove[dsrc + "/"] = ddst + "/"
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   356
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   357
    for i in invalid:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   358
        if i in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   359
            del dirmove[i]
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   360
    del d1, d2, invalid
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   361
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   362
    if not dirmove:
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   363
        return copy, movewithdir, diverge, renamedelete
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   364
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   365
    for d in dirmove:
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   366
        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
   367
                      (d, dirmove[d]))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   368
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   369
    # check unaccounted nonoverlapping files against directory moves
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   370
    for f in u1 + u2:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   371
        if f not in fullcopy:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   372
            for d in dirmove:
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   373
                if f.startswith(d):
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   374
                    # 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
   375
                    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
   376
                    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
   377
                        movewithdir[f] = df
18135
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   378
                        repo.ui.debug(("   pending file src: '%s' -> "
a6fe1b9cc68f copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents: 18134
diff changeset
   379
                                       "dst: '%s'\n") % (f, df))
6274
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   380
                    break
f3f383efbeae copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   381
18134
6c35b53cd28b copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents: 17055
diff changeset
   382
    return copy, movewithdir, diverge, renamedelete