Mercurial > hg
annotate mercurial/copies.py @ 19966:7985e3469f58 stable
largefiles: systematic testing of merges to/from largefiles
427ce5633c1c fixed one problem with update and added a test case for it. The
test coverage was thus insufficient before that.
To make sure we have good test coverage in this area we add systematic testing
of all cases of merges that may or may not change normal files to largefiles or
vice versa.
The tests shows some annoying extra merge prompts in some cases, but these
prompts are hard to avoid and they are now "safe" - they do not leave the
system in a confused inconsistent state.
author | Mads Kiilerich <madski@unity3d.com> |
---|---|
date | Mon, 28 Oct 2013 22:34:05 +0100 |
parents | 4327687ca757 |
children | 243ea5ffdf31 |
rev | line source |
---|---|
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 | 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 = {} |
18878
3cfaace0441e
copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents:
18362
diff
changeset
|
136 missing = set(b.manifest().iterkeys()) |
3cfaace0441e
copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents:
18362
diff
changeset
|
137 missing.difference_update(a.manifest().iterkeys()) |
3cfaace0441e
copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents:
18362
diff
changeset
|
138 |
3cfaace0441e
copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents:
18362
diff
changeset
|
139 for f in missing: |
3cfaace0441e
copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents:
18362
diff
changeset
|
140 ofctx = _tracefile(b[f], a) |
3cfaace0441e
copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents:
18362
diff
changeset
|
141 if ofctx: |
3cfaace0441e
copies._forwardcopies: use set operations to find missing files
Siddharth Agarwal <sid0@fb.com>
parents:
18362
diff
changeset
|
142 cm[f] = ofctx.path() |
15775
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
143 |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
144 # combine copies from dirstate if necessary |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
145 if w is not None: |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
146 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
|
147 |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
148 return cm |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
149 |
18136
f23dea2b296e
copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents:
18135
diff
changeset
|
150 def _backwardrenames(a, b): |
f23dea2b296e
copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents:
18135
diff
changeset
|
151 # 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
|
152 # 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
|
153 # 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
|
154 f = _forwardcopies(b, a) |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
155 r = {} |
18355
2330d97e7707
copies: make the loss in _backwardcopies more stable
Mads Kiilerich <mads@kiilerich.com>
parents:
18136
diff
changeset
|
156 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
|
157 # remove copies |
f23dea2b296e
copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents:
18135
diff
changeset
|
158 if v in a: |
f23dea2b296e
copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents:
18135
diff
changeset
|
159 continue |
15775
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
160 r[v] = k |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
161 return r |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
162 |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
163 def pathcopies(x, y): |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
164 '''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
|
165 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
|
166 return {} |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
167 a = y.ancestor(x) |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
168 if a == x: |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
169 return _forwardcopies(x, y) |
91eb4512edd0
copies: rewrite copy detection for non-merge users
Matt Mackall <mpm@selenic.com>
parents:
15774
diff
changeset
|
170 if a == y: |
18136
f23dea2b296e
copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents:
18135
diff
changeset
|
171 return _backwardrenames(x, y) |
f23dea2b296e
copies: do not track backward copies, only renames (issue3739)
Siddharth Agarwal <sid0@fb.com>
parents:
18135
diff
changeset
|
172 return _chain(x, y, _backwardrenames(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
|
173 |
16169
c12d4aceba79
copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents:
16168
diff
changeset
|
174 def mergecopies(repo, c1, c2, ca): |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
175 """ |
16168
7bbabfe25321
copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents:
15994
diff
changeset
|
176 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
|
177 for merging. |
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 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
|
180 "renamedelete". |
16168
7bbabfe25321
copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents:
15994
diff
changeset
|
181 |
16177
b8c1a8a57540
copies: fix mergecopies doc mapping direction
Matt Mackall <mpm@selenic.com>
parents:
16169
diff
changeset
|
182 "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
|
183 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
|
184 |
18134
6c35b53cd28b
copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents:
17055
diff
changeset
|
185 "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
|
186 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
|
187 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
|
188 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
|
189 |
16168
7bbabfe25321
copies: add docstring for mergecopies
Matt Mackall <mpm@selenic.com>
parents:
15994
diff
changeset
|
190 "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
|
191 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
|
192 |
98687cdddcb1
merge: warn about file deleted in one branch and renamed in other (issue3074)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
16792
diff
changeset
|
193 "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
|
194 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
|
195 """ |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
196 # 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
|
197 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
|
198 return {}, {}, {}, {} |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
199 |
6646
9eb274d773d9
copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents:
6431
diff
changeset
|
200 # avoid silly behavior for parent -> working dir |
13878
a8d13ee0ce68
misc: replace .parents()[0] with p1()
Matt Mackall <mpm@selenic.com>
parents:
12683
diff
changeset
|
201 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
|
202 return repo.dirstate.copies(), {}, {}, {} |
6646
9eb274d773d9
copies: teach copies about dirstate.copies
Matt Mackall <mpm@selenic.com>
parents:
6431
diff
changeset
|
203 |
6431
a42d8d3e6ea9
copies: refactor symmetricdifference as _findlimit
Matt Mackall <mpm@selenic.com>
parents:
6430
diff
changeset
|
204 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
|
205 if limit is None: |
83cfa1baf8ad
copies: don't report copies with unrelated branch
Patrick Mezard <pmezard@gmail.com>
parents:
9467
diff
changeset
|
206 # 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
|
207 return {}, {}, {}, {} |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
208 m1 = c1.manifest() |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
209 m2 = c2.manifest() |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
210 ma = ca.manifest() |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
211 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
212 def makectx(f, n): |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
213 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
|
214 if c1.rev() is None: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
215 return c1.filectx(f) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
216 return c2.filectx(f) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
217 return repo.filectx(f, fileid=n) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
218 |
9097
431462bd8478
fix memory usage of revlog caches by limiting cache size [issue1639]
Matt Mackall <mpm@selenic.com>
parents:
8527
diff
changeset
|
219 ctx = util.lrucachefunc(makectx) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
220 copy = {} |
18134
6c35b53cd28b
copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents:
17055
diff
changeset
|
221 movewithdir = {} |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
222 fullcopy = {} |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
223 diverge = {} |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
224 |
19178
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
225 def _checkcopies(f, m1, m2): |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
226 checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
227 |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9102
diff
changeset
|
228 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
|
229 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
230 u1 = _nonoverlap(m1, m2, ma) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
231 u2 = _nonoverlap(m2, m1, ma) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
232 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
233 if u1: |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9102
diff
changeset
|
234 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
|
235 % "\n ".join(u1)) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
236 if u2: |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9102
diff
changeset
|
237 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
|
238 % "\n ".join(u2)) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
239 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
240 for f in u1: |
19178
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
241 _checkcopies(f, m1, m2) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
242 for f in u2: |
19178
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
243 _checkcopies(f, m2, m1) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
244 |
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
|
245 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
|
246 renamedelete2 = set() |
8152
08e1baf924ca
replace set-like dictionaries with real sets
Martin Geisler <mg@lazybytes.net>
parents:
7873
diff
changeset
|
247 diverge2 = set() |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
248 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
|
249 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
|
250 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
|
251 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
|
252 # 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
|
253 # 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
|
254 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
|
255 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
|
256 else: |
8152
08e1baf924ca
replace set-like dictionaries with real sets
Martin Geisler <mg@lazybytes.net>
parents:
7873
diff
changeset
|
257 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
|
258 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
259 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
|
260 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
|
261 "% = renamed and deleted):\n") |
18362
5a4f220fbfca
copies: report found copies sorted
Mads Kiilerich <mads@kiilerich.com>
parents:
18355
diff
changeset
|
262 for f in sorted(fullcopy): |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
263 note = "" |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
264 if f in copy: |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
265 note += "*" |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
266 if f in diverge2: |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
267 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
|
268 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
|
269 note += "%" |
18135
a6fe1b9cc68f
copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents:
18134
diff
changeset
|
270 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
|
271 note)) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
272 del diverge2 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
273 |
16169
c12d4aceba79
copies: remove checkdirs options
Matt Mackall <mpm@selenic.com>
parents:
16168
diff
changeset
|
274 if not fullcopy: |
18134
6c35b53cd28b
copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents:
17055
diff
changeset
|
275 return copy, movewithdir, diverge, renamedelete |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
276 |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
9102
diff
changeset
|
277 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
|
278 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
279 # generate a directory move map |
16178
828fe2ca7cbb
copies: use ctx.dirs() for directory rename detection
Matt Mackall <mpm@selenic.com>
parents:
16177
diff
changeset
|
280 d1, d2 = c1.dirs(), c2.dirs() |
18899
d8ff607ef721
scmutil: use new dirs class in dirstate and context
Bryan O'Sullivan <bryano@fb.com>
parents:
18878
diff
changeset
|
281 d1.addpath('/') |
d8ff607ef721
scmutil: use new dirs class in dirstate and context
Bryan O'Sullivan <bryano@fb.com>
parents:
18878
diff
changeset
|
282 d2.addpath('/') |
17055
8b7cd9a998f0
copies: re-include root directory in directory rename detection (issue3511)
Matt Mackall <mpm@selenic.com>
parents:
16795
diff
changeset
|
283 invalid = set() |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
284 dirmove = {} |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
285 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
286 # 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
|
287 # 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
|
288 for dst, src in fullcopy.iteritems(): |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
289 dsrc, ddst = _dirname(src), _dirname(dst) |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
290 if dsrc in invalid: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
291 # already seen to be uninteresting |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
292 continue |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
293 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
|
294 # 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
|
295 invalid.add(dsrc) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
296 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
|
297 # 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
|
298 invalid.add(dsrc) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
299 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
|
300 # 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
|
301 invalid.add(dsrc) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
302 else: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
303 # looks good so far |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
304 dirmove[dsrc + "/"] = ddst + "/" |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
305 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
306 for i in invalid: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
307 if i in dirmove: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
308 del dirmove[i] |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
309 del d1, d2, invalid |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
310 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
311 if not dirmove: |
18134
6c35b53cd28b
copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents:
17055
diff
changeset
|
312 return copy, movewithdir, diverge, renamedelete |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
313 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
314 for d in dirmove: |
18135
a6fe1b9cc68f
copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents:
18134
diff
changeset
|
315 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
|
316 (d, dirmove[d])) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
317 |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
318 # check unaccounted nonoverlapping files against directory moves |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
319 for f in u1 + u2: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
320 if f not in fullcopy: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
321 for d in dirmove: |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
322 if f.startswith(d): |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
323 # 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
|
324 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
|
325 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
|
326 movewithdir[f] = df |
18135
a6fe1b9cc68f
copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents:
18134
diff
changeset
|
327 repo.ui.debug((" pending file src: '%s' -> " |
a6fe1b9cc68f
copies: make debug messages more sensible
Siddharth Agarwal <sid0@fb.com>
parents:
18134
diff
changeset
|
328 "dst: '%s'\n") % (f, df)) |
6274
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
329 break |
f3f383efbeae
copies: move findcopies code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
330 |
18134
6c35b53cd28b
copies: separate moves via directory renames from explicit copies
Siddharth Agarwal <sid0@fb.com>
parents:
17055
diff
changeset
|
331 return copy, movewithdir, diverge, renamedelete |
19178
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
332 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
333 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
|
334 """ |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
335 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
|
336 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
337 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
|
338 f = the filename to check |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
339 m1 = the source manifest |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
340 m2 = the destination manifest |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
341 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
|
342 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
|
343 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
|
344 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
|
345 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
|
346 """ |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
347 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
348 ma = ca.manifest() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
349 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
350 def _related(f1, f2, limit): |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
351 # 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
|
352 # 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
|
353 # 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
|
354 # 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
|
355 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
356 if f1 == f2: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
357 return f1 # a match |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
358 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
359 g1, g2 = f1.ancestors(), f2.ancestors() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
360 try: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
361 f1r, f2r = f1.rev(), f2.rev() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
362 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
363 if f1r is None: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
364 f1 = g1.next() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
365 if f2r is None: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
366 f2 = g2.next() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
367 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
368 while True: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
369 f1r, f2r = f1.rev(), f2.rev() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
370 if f1r > f2r: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
371 f1 = g1.next() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
372 elif f2r > f1r: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
373 f2 = g2.next() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
374 elif f1 == f2: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
375 return f1 # a match |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
376 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
|
377 return False # copy no longer relevant |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
378 except StopIteration: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
379 return False |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
380 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
381 of = None |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
382 seen = set([f]) |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
383 for oc in ctx(f, m1[f]).ancestors(): |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
384 ocr = oc.rev() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
385 of = oc.path() |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
386 if of in seen: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
387 # 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
|
388 if ocr < limit: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
389 break |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
390 continue |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
391 seen.add(of) |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
392 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
393 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
|
394 if of not in m2: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
395 continue # no match, keep looking |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
396 if m2[of] == ma.get(of): |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
397 break # no merge needed, quit early |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
398 c2 = ctx(of, m2[of]) |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
399 cr = _related(oc, c2, ca.rev()) |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
400 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
|
401 copy[f] = of |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
402 of = None |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
403 break |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
404 |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
405 if of in ma: |
4327687ca757
copies: refactor checkcopies() into a top level method
Durham Goode <durham@fb.com>
parents:
18899
diff
changeset
|
406 diverge.setdefault(of, []).append(f) |