85 if f not in man: |
85 if f not in man: |
86 action.append((f, "f")) |
86 action.append((f, "f")) |
87 |
87 |
88 return action |
88 return action |
89 |
89 |
90 def nonoverlap(d1, d2, d3): |
|
91 "Return list of elements in d1 not in d2 or d3" |
|
92 |
|
93 l = [] |
|
94 for d in d1: |
|
95 if d not in d3 and d not in d2: |
|
96 l.append(d) |
|
97 |
|
98 l.sort() |
|
99 return l |
|
100 |
|
101 def findold(fctx, limit): |
|
102 "find files that path was copied from, back to linkrev limit" |
|
103 |
|
104 old = {} |
|
105 orig = fctx.path() |
|
106 visit = [fctx] |
|
107 while visit: |
|
108 fc = visit.pop() |
|
109 if fc.rev() < limit: |
|
110 continue |
|
111 if fc.path() != orig and fc.path() not in old: |
|
112 old[fc.path()] = 1 |
|
113 visit += fc.parents() |
|
114 |
|
115 old = old.keys() |
|
116 old.sort() |
|
117 return old |
|
118 |
|
119 def findcopies(repo, m1, m2, ma, limit): |
90 def findcopies(repo, m1, m2, ma, limit): |
120 """ |
91 """ |
121 Find moves and copies between m1 and m2 back to limit linkrev |
92 Find moves and copies between m1 and m2 back to limit linkrev |
122 """ |
93 """ |
|
94 |
|
95 def findold(fctx): |
|
96 "find files that path was copied from, back to linkrev limit" |
|
97 old = {} |
|
98 orig = fctx.path() |
|
99 visit = [fctx] |
|
100 while visit: |
|
101 fc = visit.pop() |
|
102 if fc.rev() < limit: |
|
103 continue |
|
104 if fc.path() != orig and fc.path() not in old: |
|
105 old[fc.path()] = 1 |
|
106 visit += fc.parents() |
|
107 |
|
108 old = old.keys() |
|
109 old.sort() |
|
110 return old |
|
111 |
|
112 def nonoverlap(d1, d2, d3): |
|
113 "Return list of elements in d1 not in d2 or d3" |
|
114 l = [d for d in d1 if d not in d3 and d not in d2] |
|
115 l.sort() |
|
116 return l |
|
117 |
|
118 def checkcopies(c, man): |
|
119 '''check possible copies for filectx c''' |
|
120 for of in findold(c): |
|
121 if of not in man: |
|
122 return |
|
123 c2 = ctx(of, man[of]) |
|
124 ca = c.ancestor(c2) |
|
125 if not ca or c == ca or c2 == ca: |
|
126 return |
|
127 if ca.path() == c.path() or ca.path() == c2.path(): |
|
128 copy[c.path()] = of |
123 |
129 |
124 if not repo.ui.configbool("merge", "followcopies", True): |
130 if not repo.ui.configbool("merge", "followcopies", True): |
125 return {} |
131 return {} |
126 |
132 |
127 # avoid silly behavior for update from empty dir |
133 # avoid silly behavior for update from empty dir |
132 copy = {} |
138 copy = {} |
133 u1 = nonoverlap(m1, m2, ma) |
139 u1 = nonoverlap(m1, m2, ma) |
134 u2 = nonoverlap(m2, m1, ma) |
140 u2 = nonoverlap(m2, m1, ma) |
135 ctx = util.cachefunc(lambda f, n: repo.filectx(f, fileid=n[:20])) |
141 ctx = util.cachefunc(lambda f, n: repo.filectx(f, fileid=n[:20])) |
136 |
142 |
137 def checkpair(c, f2, man): |
|
138 ''' check if an apparent pair actually matches ''' |
|
139 if f2 not in man: |
|
140 return |
|
141 c2 = ctx(f2, man[f2]) |
|
142 ca = c.ancestor(c2) |
|
143 if not ca or c == ca or c2 == ca: |
|
144 return |
|
145 if ca.path() == c.path() or ca.path() == c2.path(): |
|
146 copy[c.path()] = f2 |
|
147 |
|
148 for f in u1: |
143 for f in u1: |
149 c = ctx(dcopies.get(f, f), m1[f]) |
144 checkcopies(ctx(dcopies.get(f, f), m1[f]), m2) |
150 for of in findold(c, limit): |
|
151 checkpair(c, of, m2) |
|
152 |
145 |
153 for f in u2: |
146 for f in u2: |
154 c = ctx(f, m2[f]) |
147 checkcopies(ctx(f, m2[f]), m1) |
155 for of in findold(c, limit): |
|
156 checkpair(c, of, m1) |
|
157 |
148 |
158 return copy |
149 return copy |
159 |
150 |
160 def manifestmerge(repo, p1, p2, pa, overwrite, partial): |
151 def manifestmerge(repo, p1, p2, pa, overwrite, partial): |
161 """ |
152 """ |