Mercurial > hg
comparison mercurial/dagop.py @ 44659:67f757ed86e0
dagop: fix subsetparentswalker to set p1/p2 chains at merge revision
The previous implementation was wrong because the '1'/'2' key would be
appended at a fork revision. Since we traverse the graph from heads, a merge
revision is actually a branching point, where the sort key must be generated.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Thu, 26 Mar 2020 22:31:17 +0900 |
parents | 25436f83fb95 |
children | 4ebc5f325bed |
comparison
equal
deleted
inserted
replaced
44658:25436f83fb95 | 44659:67f757ed86e0 |
---|---|
389 # When a revision is visited, 'pointers[rev]' should be popped and | 389 # When a revision is visited, 'pointers[rev]' should be popped and |
390 # propagated to its parents accordingly. | 390 # propagated to its parents accordingly. |
391 # | 391 # |
392 # Once all pending paths have been resolved, 'pendingcnt[rev]' becomes | 392 # Once all pending paths have been resolved, 'pendingcnt[rev]' becomes |
393 # 0 and 'parents[rev]' contains the unsorted list of parent revisions | 393 # 0 and 'parents[rev]' contains the unsorted list of parent revisions |
394 # and p1/p2 chains (excluding linear paths.) | 394 # and p1/p2 chains (excluding linear paths.) The p1/p2 chains will be |
395 # used as a sort key preferring p1. 'len(chain)' should be the number | |
396 # of merges between two revisions. | |
395 | 397 |
396 subset = self._subset | 398 subset = self._subset |
397 tovisit = self._tovisit # heap queue of [-rev] | 399 tovisit = self._tovisit # heap queue of [-rev] |
398 pendingcnt = self._pendingcnt # {rev: count} for visited revisions | 400 pendingcnt = self._pendingcnt # {rev: count} for visited revisions |
399 pointers = self._pointers # {rev: [{unresolved_rev: chain}, resolved]} | 401 pointers = self._pointers # {rev: [{unresolved_rev: chain}, resolved]} |
456 parentpointers = [ | 458 parentpointers = [ |
457 (unresolved, resolved), | 459 (unresolved, resolved), |
458 (unresolved.copy(), resolved.copy()), | 460 (unresolved.copy(), resolved.copy()), |
459 ] | 461 ] |
460 # 'rev' is a merge revision. increment the pending count | 462 # 'rev' is a merge revision. increment the pending count |
461 # as the 'unresolved' dict will be duplicated. | 463 # as the 'unresolved' dict will be duplicated, and append |
464 # p1/p2 code to the existing chains. | |
462 for r in unresolved: | 465 for r in unresolved: |
463 pendingcnt[r] += 1 | 466 pendingcnt[r] += 1 |
467 parentpointers[0][0][r] += b'1' | |
468 parentpointers[1][0][r] += b'2' | |
464 for i, p in enumerate(parentrevs): | 469 for i, p in enumerate(parentrevs): |
465 assert p < rev | 470 assert p < rev |
466 heapq.heappush(tovisit, -p) | 471 heapq.heappush(tovisit, -p) |
467 if p in pointers: | 472 if p in pointers: |
468 # 'p' is a fork revision. concatenate tracking pointers | 473 # 'p' is a fork revision. concatenate tracking pointers |
469 # and decrement the pending count accordingly. | 474 # and decrement the pending count accordingly. |
470 knownunresolved, knownresolved = pointers[p] | 475 knownunresolved, knownresolved = pointers[p] |
471 unresolved, resolved = parentpointers[i] | 476 unresolved, resolved = parentpointers[i] |
472 for r, c in unresolved.items(): | 477 for r, c in unresolved.items(): |
473 c += [b'1', b'2'][i] | |
474 if r in knownunresolved: | 478 if r in knownunresolved: |
475 # unresolved at both paths | 479 # unresolved at both paths |
476 pendingcnt[r] -= 1 | 480 pendingcnt[r] -= 1 |
477 assert pendingcnt[r] > 0 | 481 assert pendingcnt[r] > 0 |
478 # take shorter chain | 482 # take shorter chain |
486 pointers[p] = parentpointers[i] | 490 pointers[p] = parentpointers[i] |
487 | 491 |
488 # then, populate the active parents directly and add the current | 492 # then, populate the active parents directly and add the current |
489 # 'rev' to the tracking pointers of the inactive parents. | 493 # 'rev' to the tracking pointers of the inactive parents. |
490 # 'pointers[p]' may be optimized out if both parents are active. | 494 # 'pointers[p]' may be optimized out if both parents are active. |
495 chaincodes = [b''] if len(parentrevs) <= 1 else [b'1', b'2'] | |
491 if curactive and bothparentsactive: | 496 if curactive and bothparentsactive: |
492 for i, p in enumerate(parentrevs): | 497 for i, p in enumerate(parentrevs): |
493 c = [b'1', b'2'][i] | 498 c = chaincodes[i] |
494 parents[rev].append((c, p)) | 499 parents[rev].append((c, p)) |
495 # no need to mark 'rev' as resolved since the 'rev' should | 500 # no need to mark 'rev' as resolved since the 'rev' should |
496 # be fully resolved (i.e. pendingcnt[rev] == 0) | 501 # be fully resolved (i.e. pendingcnt[rev] == 0) |
497 assert pendingcnt[rev] == 0 | 502 assert pendingcnt[rev] == 0 |
498 elif curactive: | 503 elif curactive: |
499 for i, p in enumerate(parentrevs): | 504 for i, p in enumerate(parentrevs): |
500 unresolved, resolved = pointers[p] | 505 unresolved, resolved = pointers[p] |
501 assert rev not in unresolved | 506 assert rev not in unresolved |
502 c = [b'1', b'2'][i] | 507 c = chaincodes[i] |
503 if p in subset: | 508 if p in subset: |
504 parents[rev].append((c, p)) | 509 parents[rev].append((c, p)) |
505 # mark 'rev' as resolved through this path | 510 # mark 'rev' as resolved through this path |
506 resolved.add(rev) | 511 resolved.add(rev) |
507 else: | 512 else: |