Show More
@@ -4073,7 +4073,7 b' def mqphasedefaults(repo, roots):' | |||||
4073 | else: |
|
4073 | else: | |
4074 | mqphase = phases.draft |
|
4074 | mqphase = phases.draft | |
4075 | qbase = repo[repo.mq.applied[0].node] |
|
4075 | qbase = repo[repo.mq.applied[0].node] | |
4076 |
roots[mqphase].add(qbase. |
|
4076 | roots[mqphase].add(qbase.rev()) | |
4077 | return roots |
|
4077 | return roots | |
4078 |
|
4078 | |||
4079 |
|
4079 |
@@ -58,7 +58,7 b' class index:' | |||||
58 | def get_rev(self, value: bytes) -> Optional[int]: ... |
|
58 | def get_rev(self, value: bytes) -> Optional[int]: ... | |
59 | def has_node(self, value: Union[int, bytes]) -> bool: ... |
|
59 | def has_node(self, value: Union[int, bytes]) -> bool: ... | |
60 | def rev(self, node: bytes) -> int: ... |
|
60 | def rev(self, node: bytes) -> int: ... | |
61 |
def computephasesmapsets(self, root: Dict[int, Set[ |
|
61 | def computephasesmapsets(self, root: Dict[int, Set[int]]) -> Tuple[int, Dict[int, Set[bytes]]]: ... | |
62 | def reachableroots2(self, minroot: int, heads: List[int], roots: List[int], includepath: bool) -> List[int]: ... |
|
62 | def reachableroots2(self, minroot: int, heads: List[int], roots: List[int], includepath: bool) -> List[int]: ... | |
63 | def headrevs(self, filteredrevs: Optional[List[int]]) -> List[int]: ... |
|
63 | def headrevs(self, filteredrevs: Optional[List[int]]) -> List[int]: ... | |
64 | def headrevsfiltered(self, filteredrevs: Optional[List[int]]) -> List[int]: ... |
|
64 | def headrevsfiltered(self, filteredrevs: Optional[List[int]]) -> List[int]: ... |
@@ -1081,7 +1081,6 b' static int add_roots_get_min(indexObject' | |||||
1081 | PyObject *item; |
|
1081 | PyObject *item; | |
1082 | PyObject *iterator; |
|
1082 | PyObject *iterator; | |
1083 | int rev, minrev = -1; |
|
1083 | int rev, minrev = -1; | |
1084 | char *node; |
|
|||
1085 |
|
1084 | |||
1086 | if (!PySet_Check(roots)) { |
|
1085 | if (!PySet_Check(roots)) { | |
1087 | PyErr_SetString(PyExc_TypeError, |
|
1086 | PyErr_SetString(PyExc_TypeError, | |
@@ -1092,9 +1091,10 b' static int add_roots_get_min(indexObject' | |||||
1092 | if (iterator == NULL) |
|
1091 | if (iterator == NULL) | |
1093 | return -2; |
|
1092 | return -2; | |
1094 | while ((item = PyIter_Next(iterator))) { |
|
1093 | while ((item = PyIter_Next(iterator))) { | |
1095 | if (node_check(self->nodelen, item, &node) == -1) |
|
1094 | rev = (int)PyLong_AsLong(item); | |
|
1095 | if (rev == -1 && PyErr_Occurred()) { | |||
1096 | goto failed; |
|
1096 | goto failed; | |
1097 | rev = index_find_node(self, node); |
|
1097 | } | |
1098 | /* null is implicitly public, so negative is invalid */ |
|
1098 | /* null is implicitly public, so negative is invalid */ | |
1099 | if (rev < 0 || rev >= len) |
|
1099 | if (rev < 0 || rev >= len) | |
1100 | goto failed; |
|
1100 | goto failed; |
@@ -133,7 +133,7 b' from . import (' | |||||
133 | util, |
|
133 | util, | |
134 | ) |
|
134 | ) | |
135 |
|
135 | |||
136 |
Phaseroots = Dict[int, Set[ |
|
136 | Phaseroots = Dict[int, Set[int]] | |
137 |
|
137 | |||
138 | if typing.TYPE_CHECKING: |
|
138 | if typing.TYPE_CHECKING: | |
139 | from . import ( |
|
139 | from . import ( | |
@@ -210,7 +210,7 b' def _readroots(' | |||||
210 | repo = repo.unfiltered() |
|
210 | repo = repo.unfiltered() | |
211 | dirty = False |
|
211 | dirty = False | |
212 | roots = {i: set() for i in allphases} |
|
212 | roots = {i: set() for i in allphases} | |
213 |
|
|
213 | to_rev = repo.changelog.index.get_rev | |
214 | unknown_msg = b'removing unknown node %s from %i-phase boundary\n' |
|
214 | unknown_msg = b'removing unknown node %s from %i-phase boundary\n' | |
215 | try: |
|
215 | try: | |
216 | f, pending = txnutil.trypending(repo.root, repo.svfs, b'phaseroots') |
|
216 | f, pending = txnutil.trypending(repo.root, repo.svfs, b'phaseroots') | |
@@ -219,11 +219,12 b' def _readroots(' | |||||
219 | str_phase, hex_node = line.split() |
|
219 | str_phase, hex_node = line.split() | |
220 | phase = int(str_phase) |
|
220 | phase = int(str_phase) | |
221 | node = bin(hex_node) |
|
221 | node = bin(hex_node) | |
222 |
|
|
222 | rev = to_rev(node) | |
|
223 | if rev is None: | |||
223 | repo.ui.debug(unknown_msg % (short(hex_node), phase)) |
|
224 | repo.ui.debug(unknown_msg % (short(hex_node), phase)) | |
224 | dirty = True |
|
225 | dirty = True | |
225 | else: |
|
226 | else: | |
226 |
roots[phase].add( |
|
227 | roots[phase].add(rev) | |
227 | finally: |
|
228 | finally: | |
228 | f.close() |
|
229 | f.close() | |
229 | except FileNotFoundError: |
|
230 | except FileNotFoundError: | |
@@ -391,7 +392,7 b' class phasecache:' | |||||
391 |
|
392 | |||
392 | def nonpublicphaseroots( |
|
393 | def nonpublicphaseroots( | |
393 | self, repo: "localrepo.localrepository" |
|
394 | self, repo: "localrepo.localrepository" | |
394 |
) -> Set[ |
|
395 | ) -> Set[int]: | |
395 | """returns the roots of all non-public phases |
|
396 | """returns the roots of all non-public phases | |
396 |
|
397 | |||
397 | The roots are not minimized, so if the secret revisions are |
|
398 | The roots are not minimized, so if the secret revisions are | |
@@ -499,7 +500,7 b' class phasecache:' | |||||
499 | self._phasesets = {phase: set() for phase in allphases} |
|
500 | self._phasesets = {phase: set() for phase in allphases} | |
500 | lowerroots = set() |
|
501 | lowerroots = set() | |
501 | for phase in reversed(trackedphases): |
|
502 | for phase in reversed(trackedphases): | |
502 |
roots = |
|
503 | roots = self._phaseroots[phase] | |
503 | if roots: |
|
504 | if roots: | |
504 | ps = set(cl.descendants(roots)) |
|
505 | ps = set(cl.descendants(roots)) | |
505 | for root in roots: |
|
506 | for root in roots: | |
@@ -551,8 +552,10 b' class phasecache:' | |||||
551 |
|
552 | |||
552 | def _write(self, repo, fp): |
|
553 | def _write(self, repo, fp): | |
553 | assert repo.filtername is None |
|
554 | assert repo.filtername is None | |
|
555 | to_node = repo.changelog.node | |||
554 | for phase, roots in self._phaseroots.items(): |
|
556 | for phase, roots in self._phaseroots.items(): | |
555 |
for |
|
557 | for r in sorted(roots): | |
|
558 | h = to_node(r) | |||
556 | fp.write(b'%i %s\n' % (phase, hex(h))) |
|
559 | fp.write(b'%i %s\n' % (phase, hex(h))) | |
557 | self.dirty = False |
|
560 | self.dirty = False | |
558 |
|
561 | |||
@@ -584,7 +587,7 b' class phasecache:' | |||||
584 | repo.invalidatevolatilesets() |
|
587 | repo.invalidatevolatilesets() | |
585 |
|
588 | |||
586 | def advanceboundary( |
|
589 | def advanceboundary( | |
587 | self, repo, tr, targetphase, nodes, revs=None, dryrun=None |
|
590 | self, repo, tr, targetphase, nodes=None, revs=None, dryrun=None | |
588 | ): |
|
591 | ): | |
589 | """Set all 'nodes' to phase 'targetphase' |
|
592 | """Set all 'nodes' to phase 'targetphase' | |
590 |
|
593 | |||
@@ -598,6 +601,8 b' class phasecache:' | |||||
598 | # phaseroots values, replace them. |
|
601 | # phaseroots values, replace them. | |
599 | if revs is None: |
|
602 | if revs is None: | |
600 | revs = [] |
|
603 | revs = [] | |
|
604 | if not revs and not nodes: | |||
|
605 | return set() | |||
601 | if tr is None: |
|
606 | if tr is None: | |
602 | phasetracking = None |
|
607 | phasetracking = None | |
603 | else: |
|
608 | else: | |
@@ -616,7 +621,7 b' class phasecache:' | |||||
616 |
|
621 | |||
617 | olds = self._phaseroots[phase] |
|
622 | olds = self._phaseroots[phase] | |
618 |
|
623 | |||
619 |
affected = repo.revs(b'%l |
|
624 | affected = repo.revs(b'%ld::%ld', olds, revs) | |
620 | changes.update(affected) |
|
625 | changes.update(affected) | |
621 | if dryrun: |
|
626 | if dryrun: | |
622 | continue |
|
627 | continue | |
@@ -625,10 +630,7 b' class phasecache:' | |||||
625 | phasetracking, r, self.phase(repo, r), targetphase |
|
630 | phasetracking, r, self.phase(repo, r), targetphase | |
626 | ) |
|
631 | ) | |
627 |
|
632 | |||
628 | roots = { |
|
633 | roots = set(repo.revs(b'roots((%ld::) - %ld)', olds, affected)) | |
629 | ctx.node() |
|
|||
630 | for ctx in repo.set(b'roots((%ln::) - %ld)', olds, affected) |
|
|||
631 | } |
|
|||
632 | if olds != roots: |
|
634 | if olds != roots: | |
633 | self._updateroots(repo, phase, roots, tr) |
|
635 | self._updateroots(repo, phase, roots, tr) | |
634 | # some roots may need to be declared for lower phases |
|
636 | # some roots may need to be declared for lower phases | |
@@ -636,7 +638,7 b' class phasecache:' | |||||
636 | if not dryrun: |
|
638 | if not dryrun: | |
637 | # declare deleted root in the target phase |
|
639 | # declare deleted root in the target phase | |
638 | if targetphase != 0: |
|
640 | if targetphase != 0: | |
639 | self._retractboundary(repo, tr, targetphase, delroots) |
|
641 | self._retractboundary(repo, tr, targetphase, revs=delroots) | |
640 | repo.invalidatevolatilesets() |
|
642 | repo.invalidatevolatilesets() | |
641 | return changes |
|
643 | return changes | |
642 |
|
644 | |||
@@ -651,21 +653,19 b' class phasecache:' | |||||
651 | else: |
|
653 | else: | |
652 | phasetracking = tr.changes.get(b'phases') |
|
654 | phasetracking = tr.changes.get(b'phases') | |
653 | repo = repo.unfiltered() |
|
655 | repo = repo.unfiltered() | |
654 | if ( |
|
656 | retracted = self._retractboundary(repo, tr, targetphase, nodes) | |
655 | self._retractboundary(repo, tr, targetphase, nodes) |
|
657 | if retracted and phasetracking is not None: | |
656 | and phasetracking is not None |
|
|||
657 | ): |
|
|||
658 |
|
658 | |||
659 | # find the affected revisions |
|
659 | # find the affected revisions | |
660 | new = self._phaseroots[targetphase] |
|
660 | new = self._phaseroots[targetphase] | |
661 | old = oldroots[targetphase] |
|
661 | old = oldroots[targetphase] | |
662 |
affected = set(repo.revs(b'(%l |
|
662 | affected = set(repo.revs(b'(%ld::) - (%ld::)', new, old)) | |
663 |
|
663 | |||
664 | # find the phase of the affected revision |
|
664 | # find the phase of the affected revision | |
665 | for phase in range(targetphase, -1, -1): |
|
665 | for phase in range(targetphase, -1, -1): | |
666 | if phase: |
|
666 | if phase: | |
667 | roots = oldroots.get(phase, []) |
|
667 | roots = oldroots.get(phase, []) | |
668 |
revs = set(repo.revs(b'%l |
|
668 | revs = set(repo.revs(b'%ld::%ld', roots, affected)) | |
669 | affected -= revs |
|
669 | affected -= revs | |
670 | else: # public phase |
|
670 | else: # public phase | |
671 | revs = affected |
|
671 | revs = affected | |
@@ -673,11 +673,15 b' class phasecache:' | |||||
673 | _trackphasechange(phasetracking, r, phase, targetphase) |
|
673 | _trackphasechange(phasetracking, r, phase, targetphase) | |
674 | repo.invalidatevolatilesets() |
|
674 | repo.invalidatevolatilesets() | |
675 |
|
675 | |||
676 | def _retractboundary(self, repo, tr, targetphase, nodes, revs=None): |
|
676 | def _retractboundary(self, repo, tr, targetphase, nodes=None, revs=None): | |
677 | # Be careful to preserve shallow-copied values: do not update |
|
677 | # Be careful to preserve shallow-copied values: do not update | |
678 | # phaseroots values, replace them. |
|
678 | # phaseroots values, replace them. | |
679 | if revs is None: |
|
679 | if revs is None: | |
680 | revs = [] |
|
680 | revs = [] | |
|
681 | if nodes is None: | |||
|
682 | nodes = [] | |||
|
683 | if not revs and not nodes: | |||
|
684 | return False | |||
681 | if ( |
|
685 | if ( | |
682 | targetphase == internal |
|
686 | targetphase == internal | |
683 | and not supportinternal(repo) |
|
687 | and not supportinternal(repo) | |
@@ -688,10 +692,8 b' class phasecache:' | |||||
688 | msg = b'this repository does not support the %s phase' % name |
|
692 | msg = b'this repository does not support the %s phase' % name | |
689 | raise error.ProgrammingError(msg) |
|
693 | raise error.ProgrammingError(msg) | |
690 |
|
694 | |||
691 |
|
|
695 | torev = repo.changelog.index.rev | |
692 | torev = repo.changelog.rev |
|
696 | currentroots = self._phaseroots[targetphase] | |
693 | tonode = repo.changelog.node |
|
|||
694 | currentroots = {torev(node) for node in self._phaseroots[targetphase]} |
|
|||
695 | finalroots = oldroots = set(currentroots) |
|
697 | finalroots = oldroots = set(currentroots) | |
696 | newroots = [torev(node) for node in nodes] + [r for r in revs] |
|
698 | newroots = [torev(node) for node in nodes] + [r for r in revs] | |
697 | newroots = [ |
|
699 | newroots = [ | |
@@ -701,6 +703,8 b' class phasecache:' | |||||
701 | if newroots: |
|
703 | if newroots: | |
702 | if nullrev in newroots: |
|
704 | if nullrev in newroots: | |
703 | raise error.Abort(_(b'cannot change null revision phase')) |
|
705 | raise error.Abort(_(b'cannot change null revision phase')) | |
|
706 | # do not break the CoW assumption of the shallow copy | |||
|
707 | currentroots = currentroots.copy() | |||
704 | currentroots.update(newroots) |
|
708 | currentroots.update(newroots) | |
705 |
|
709 | |||
706 | # Only compute new roots for revs above the roots that are being |
|
710 | # Only compute new roots for revs above the roots that are being | |
@@ -712,18 +716,13 b' class phasecache:' | |||||
712 | finalroots = {rev for rev in currentroots if rev < minnewroot} |
|
716 | finalroots = {rev for rev in currentroots if rev < minnewroot} | |
713 | finalroots.update(updatedroots) |
|
717 | finalroots.update(updatedroots) | |
714 | if finalroots != oldroots: |
|
718 | if finalroots != oldroots: | |
715 | self._updateroots( |
|
719 | self._updateroots(repo, targetphase, finalroots, tr) | |
716 | repo, |
|
|||
717 | targetphase, |
|
|||
718 | {tonode(rev) for rev in finalroots}, |
|
|||
719 | tr, |
|
|||
720 | ) |
|
|||
721 | return True |
|
720 | return True | |
722 | return False |
|
721 | return False | |
723 |
|
722 | |||
724 | def register_strip( |
|
723 | def register_strip( | |
725 | self, |
|
724 | self, | |
726 | repo: "localrepo.localrepository", |
|
725 | repo, | |
727 | tr, |
|
726 | tr, | |
728 | strip_rev: int, |
|
727 | strip_rev: int, | |
729 | ): |
|
728 | ): | |
@@ -731,12 +730,10 b' class phasecache:' | |||||
731 |
|
730 | |||
732 | Any roots higher than the stripped revision should be dropped. |
|
731 | Any roots higher than the stripped revision should be dropped. | |
733 | """ |
|
732 | """ | |
734 | assert repo.filtername is None |
|
733 | for targetphase, roots in list(self._phaseroots.items()): | |
735 | to_rev = repo.changelog.index.rev |
|
734 | filtered = {r for r in roots if r >= strip_rev} | |
736 | for targetphase, nodes in list(self._phaseroots.items()): |
|
|||
737 | filtered = {n for n in nodes if to_rev(n) >= strip_rev} |
|
|||
738 | if filtered: |
|
735 | if filtered: | |
739 |
self._updateroots(repo, targetphase, |
|
736 | self._updateroots(repo, targetphase, roots - filtered, tr) | |
740 | self.invalidate() |
|
737 | self.invalidate() | |
741 |
|
738 | |||
742 |
|
739 | |||
@@ -793,9 +790,10 b' def listphases(repo: "localrepo.localrep' | |||||
793 | keys = util.sortdict() |
|
790 | keys = util.sortdict() | |
794 | value = b'%i' % draft |
|
791 | value = b'%i' % draft | |
795 | cl = repo.unfiltered().changelog |
|
792 | cl = repo.unfiltered().changelog | |
|
793 | to_node = cl.node | |||
796 | for root in repo._phasecache._phaseroots[draft]: |
|
794 | for root in repo._phasecache._phaseroots[draft]: | |
797 |
if repo._phasecache.phase(repo, |
|
795 | if repo._phasecache.phase(repo, root) <= draft: | |
798 | keys[hex(root)] = value |
|
796 | keys[hex(to_node(root))] = value | |
799 |
|
797 | |||
800 | if repo.publishing(): |
|
798 | if repo.publishing(): | |
801 | # Add an extra data to let remote know we are a publishing |
|
799 | # Add an extra data to let remote know we are a publishing |
@@ -160,7 +160,7 b' def computeimpactable(repo, visibilityex' | |||||
160 | firstmutable = len(cl) |
|
160 | firstmutable = len(cl) | |
161 | roots = repo._phasecache.nonpublicphaseroots(repo) |
|
161 | roots = repo._phasecache.nonpublicphaseroots(repo) | |
162 | if roots: |
|
162 | if roots: | |
163 |
firstmutable = min(firstmutable, min( |
|
163 | firstmutable = min(firstmutable, min(roots)) | |
164 | # protect from nullrev root |
|
164 | # protect from nullrev root | |
165 | firstmutable = max(0, firstmutable) |
|
165 | firstmutable = max(0, firstmutable) | |
166 | return frozenset(range(firstmutable, len(cl))) |
|
166 | return frozenset(range(firstmutable, len(cl))) |
@@ -970,31 +970,16 b' impl Index {' | |||||
970 | py_roots: PyDict, |
|
970 | py_roots: PyDict, | |
971 | ) -> PyResult<PyObject> { |
|
971 | ) -> PyResult<PyObject> { | |
972 | let index = &*self.index(py).borrow(); |
|
972 | let index = &*self.index(py).borrow(); | |
973 | let opt = self.get_nodetree(py)?.borrow(); |
|
|||
974 | let nt = opt.as_ref().unwrap(); |
|
|||
975 | let roots: Result<HashMap<Phase, Vec<Revision>>, PyErr> = py_roots |
|
973 | let roots: Result<HashMap<Phase, Vec<Revision>>, PyErr> = py_roots | |
976 | .items_list(py) |
|
974 | .items_list(py) | |
977 | .iter(py) |
|
975 | .iter(py) | |
978 | .map(|r| { |
|
976 | .map(|r| { | |
979 | let phase = r.get_item(py, 0)?; |
|
977 | let phase = r.get_item(py, 0)?; | |
980 | let nodes = r.get_item(py, 1)?; |
|
978 | let revs: Vec<_> = | |
981 | // Transform the nodes from Python to revs here since we |
|
979 | rev_pyiter_collect(py, &r.get_item(py, 1)?, index)?; | |
982 | // have access to the nodemap |
|
|||
983 | let revs: Result<_, _> = nodes |
|
|||
984 | .iter(py)? |
|
|||
985 | .map(|node| match node?.extract::<PyBytes>(py) { |
|
|||
986 | Ok(py_bytes) => { |
|
|||
987 | let node = node_from_py_bytes(py, &py_bytes)?; |
|
|||
988 | nt.find_bin(index, node.into()) |
|
|||
989 | .map_err(|e| nodemap_error(py, e))? |
|
|||
990 | .ok_or_else(|| revlog_error(py)) |
|
|||
991 | } |
|
|||
992 | Err(e) => Err(e), |
|
|||
993 | }) |
|
|||
994 | .collect(); |
|
|||
995 | let phase = Phase::try_from(phase.extract::<usize>(py)?) |
|
980 | let phase = Phase::try_from(phase.extract::<usize>(py)?) | |
996 | .map_err(|_| revlog_error(py)); |
|
981 | .map_err(|_| revlog_error(py)); | |
997 |
Ok((phase?, revs |
|
982 | Ok((phase?, revs)) | |
998 | }) |
|
983 | }) | |
999 | .collect(); |
|
984 | .collect(); | |
1000 | let (len, phase_maps) = index |
|
985 | let (len, phase_maps) = index |
@@ -197,7 +197,7 b' debugdelta chain basic output' | |||||
197 | node trie depth: 1 |
|
197 | node trie depth: 1 | |
198 | node trie last rev scanned: -1 (no-rust !) |
|
198 | node trie last rev scanned: -1 (no-rust !) | |
199 | node trie last rev scanned: 3 (rust !) |
|
199 | node trie last rev scanned: 3 (rust !) | |
200 |
node trie lookups: |
|
200 | node trie lookups: 3 (no-rust !) | |
201 | node trie lookups: 2 (rust !) |
|
201 | node trie lookups: 2 (rust !) | |
202 | node trie misses: 1 |
|
202 | node trie misses: 1 | |
203 | node trie splits: 1 |
|
203 | node trie splits: 1 |
@@ -187,7 +187,7 b' Test corrupted p1/p2 fields that could c' | |||||
187 | > ops = [ |
|
187 | > ops = [ | |
188 | > ('reachableroots', |
|
188 | > ('reachableroots', | |
189 | > lambda: cl.index.reachableroots2(0, [1], [0], False)), |
|
189 | > lambda: cl.index.reachableroots2(0, [1], [0], False)), | |
190 |
> ('compute_phases_map_sets', lambda: cl.computephases({1: { |
|
190 | > ('compute_phases_map_sets', lambda: cl.computephases({1: {0}})), | |
191 | > ('index_headrevs', lambda: cl.headrevs()), |
|
191 | > ('index_headrevs', lambda: cl.headrevs()), | |
192 | > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)), |
|
192 | > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)), | |
193 | > ('find_deepest', lambda: cl.ancestor(n0, n1)), |
|
193 | > ('find_deepest', lambda: cl.ancestor(n0, n1)), |
General Comments 0
You need to be logged in to leave comments.
Login now