227 children = {} |
226 children = {} |
228 revinfo = _revinfogetter(repo) |
227 revinfo = _revinfogetter(repo) |
229 |
228 |
230 cl = repo.changelog |
229 cl = repo.changelog |
231 missingrevs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()]) |
230 missingrevs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()]) |
|
231 mrset = set(missingrevs) |
|
232 roots = set() |
232 for r in missingrevs: |
233 for r in missingrevs: |
233 for p in cl.parentrevs(r): |
234 for p in cl.parentrevs(r): |
234 if p == node.nullrev: |
235 if p == node.nullrev: |
235 continue |
236 continue |
236 if p not in children: |
237 if p not in children: |
237 children[p] = [r] |
238 children[p] = [r] |
238 else: |
239 else: |
239 children[p].append(r) |
240 children[p].append(r) |
240 |
241 if p not in mrset: |
241 roots = set(children) - set(missingrevs) |
242 roots.add(p) |
242 work = list(roots) |
243 if not roots: |
|
244 # no common revision to track copies from |
|
245 return {} |
|
246 min_root = min(roots) |
|
247 |
|
248 from_head = set( |
|
249 cl.reachableroots(min_root, [b.rev()], list(roots), includepath=True) |
|
250 ) |
|
251 |
|
252 iterrevs = set(from_head) |
|
253 iterrevs &= mrset |
|
254 iterrevs.update(roots) |
|
255 iterrevs.remove(b.rev()) |
243 all_copies = {r: {} for r in roots} |
256 all_copies = {r: {} for r in roots} |
244 heapq.heapify(work) |
|
245 alwaysmatch = match.always() |
257 alwaysmatch = match.always() |
246 while work: |
258 for r in sorted(iterrevs): |
247 r = heapq.heappop(work) |
|
248 copies = all_copies.pop(r) |
259 copies = all_copies.pop(r) |
249 if r == b.rev(): |
|
250 return copies |
|
251 for i, c in enumerate(children[r]): |
260 for i, c in enumerate(children[r]): |
252 p1, p2, p1copies, p2copies, removed = revinfo(c) |
261 p1, p2, p1copies, p2copies, removed = revinfo(c) |
253 if r == p1: |
262 if r == p1: |
254 parent = 1 |
263 parent = 1 |
255 childcopies = p1copies |
264 childcopies = p1copies |
271 for f in removed: |
280 for f in removed: |
272 if f in newcopies: |
281 if f in newcopies: |
273 del newcopies[f] |
282 del newcopies[f] |
274 othercopies = all_copies.get(c) |
283 othercopies = all_copies.get(c) |
275 if othercopies is None: |
284 if othercopies is None: |
276 heapq.heappush(work, c) |
|
277 all_copies[c] = newcopies |
285 all_copies[c] = newcopies |
278 else: |
286 else: |
279 # we are the second parent to work on c, we need to merge our |
287 # we are the second parent to work on c, we need to merge our |
280 # work with the other. |
288 # work with the other. |
281 # |
289 # |
291 if parent == 1: |
299 if parent == 1: |
292 othercopies.update(newcopies) |
300 othercopies.update(newcopies) |
293 else: |
301 else: |
294 newcopies.update(othercopies) |
302 newcopies.update(othercopies) |
295 all_copies[c] = newcopies |
303 all_copies[c] = newcopies |
296 assert False |
304 return all_copies[b.rev()] |
297 |
305 |
298 |
306 |
299 def _forwardcopies(a, b, base=None, match=None): |
307 def _forwardcopies(a, b, base=None, match=None): |
300 """find {dst@b: src@a} copy mapping where a is an ancestor of b""" |
308 """find {dst@b: src@a} copy mapping where a is an ancestor of b""" |
301 |
309 |