Show More
@@ -667,7 +667,7 b' void dirs_module_init(PyObject *mod);' | |||
|
667 | 667 | void manifest_module_init(PyObject *mod); |
|
668 | 668 | void revlog_module_init(PyObject *mod); |
|
669 | 669 | |
|
670 |
static const int version = 1 |
|
|
670 | static const int version = 17; | |
|
671 | 671 | |
|
672 | 672 | static void module_init(PyObject *mod) |
|
673 | 673 | { |
@@ -109,6 +109,9 b' static const Py_ssize_t nullrev = -1;' | |||
|
109 | 109 | |
|
110 | 110 | static Py_ssize_t inline_scan(indexObject *self, const char **offsets); |
|
111 | 111 | |
|
112 | static int index_find_node(indexObject *self, const char *node, | |
|
113 | Py_ssize_t nodelen); | |
|
114 | ||
|
112 | 115 | #if LONG_MAX == 0x7fffffffL |
|
113 | 116 | static const char *const tuple_format = PY23("Kiiiiiis#", "Kiiiiiiy#"); |
|
114 | 117 | #else |
@@ -577,34 +580,6 b' static int check_filter(PyObject *filter' | |||
|
577 | 580 | } |
|
578 | 581 | } |
|
579 | 582 | |
|
580 | static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list, | |
|
581 | Py_ssize_t marker, char *phases) | |
|
582 | { | |
|
583 | PyObject *iter = NULL; | |
|
584 | PyObject *iter_item = NULL; | |
|
585 | Py_ssize_t min_idx = index_length(self) + 2; | |
|
586 | long iter_item_long; | |
|
587 | ||
|
588 | if (PyList_GET_SIZE(list) != 0) { | |
|
589 | iter = PyObject_GetIter(list); | |
|
590 | if (iter == NULL) | |
|
591 | return -2; | |
|
592 | while ((iter_item = PyIter_Next(iter))) { | |
|
593 | if (!pylong_to_long(iter_item, &iter_item_long)) { | |
|
594 | Py_DECREF(iter_item); | |
|
595 | return -2; | |
|
596 | } | |
|
597 | Py_DECREF(iter_item); | |
|
598 | if (iter_item_long < min_idx) | |
|
599 | min_idx = iter_item_long; | |
|
600 | phases[iter_item_long] = (char)marker; | |
|
601 | } | |
|
602 | Py_DECREF(iter); | |
|
603 | } | |
|
604 | ||
|
605 | return min_idx; | |
|
606 | } | |
|
607 | ||
|
608 | 583 | static inline void set_phase_from_parents(char *phases, int parent_1, |
|
609 | 584 | int parent_2, Py_ssize_t i) |
|
610 | 585 | { |
@@ -773,99 +748,165 b' bail:' | |||
|
773 | 748 | return NULL; |
|
774 | 749 | } |
|
775 | 750 | |
|
751 | static int add_roots_get_min(indexObject *self, PyObject *roots, char *phases, | |
|
752 | char phase) | |
|
753 | { | |
|
754 | Py_ssize_t len = index_length(self); | |
|
755 | PyObject *iter; | |
|
756 | PyObject *item; | |
|
757 | PyObject *iterator; | |
|
758 | int rev, minrev = -1; | |
|
759 | char *node; | |
|
760 | ||
|
761 | if (!PySet_Check(roots)) | |
|
762 | return -2; | |
|
763 | iterator = PyObject_GetIter(roots); | |
|
764 | if (iterator == NULL) | |
|
765 | return -2; | |
|
766 | while ((item = PyIter_Next(iterator))) { | |
|
767 | if (node_check(item, &node) == -1) | |
|
768 | goto failed; | |
|
769 | rev = index_find_node(self, node, 20); | |
|
770 | /* null is implicitly public, so negative is invalid */ | |
|
771 | if (rev < 0 || rev >= len) | |
|
772 | goto failed; | |
|
773 | phases[rev] = phase; | |
|
774 | if (minrev == -1 || minrev > rev) | |
|
775 | minrev = rev; | |
|
776 | Py_DECREF(item); | |
|
777 | } | |
|
778 | Py_DECREF(iterator); | |
|
779 | return minrev; | |
|
780 | failed: | |
|
781 | Py_DECREF(iterator); | |
|
782 | Py_DECREF(item); | |
|
783 | return -2; | |
|
784 | } | |
|
785 | ||
|
776 | 786 | static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args) |
|
777 | 787 | { |
|
778 | PyObject *roots = Py_None; | |
|
788 | /* 0: public (untracked), 1: draft, 2: secret, 32: archive, | |
|
789 | 96: internal */ | |
|
790 | static const char trackedphases[] = {1, 2, 32, 96}; | |
|
779 | 791 | PyObject *ret = NULL; |
|
780 |
PyObject * |
|
|
792 | PyObject *roots = Py_None; | |
|
793 | PyObject *idx = NULL; | |
|
794 | PyObject *pyphase = NULL; | |
|
795 | PyObject *pyrev = NULL; | |
|
781 | 796 | PyObject *phaseroots = NULL; |
|
782 |
PyObject *phasese |
|
|
783 |
PyObject *phases |
|
|
784 | PyObject *rev = NULL; | |
|
797 | PyObject *phasessize = NULL; | |
|
798 | PyObject *phasesets[4] = {NULL, NULL, NULL, NULL}; | |
|
785 | 799 | Py_ssize_t len = index_length(self); |
|
786 | Py_ssize_t numphase = 0; | |
|
787 | Py_ssize_t minrevallphases = 0; | |
|
788 | Py_ssize_t minrevphase = 0; | |
|
789 | Py_ssize_t i = 0; | |
|
800 | const char *currentphase; | |
|
790 | 801 | char *phases = NULL; |
|
791 | long phase; | |
|
802 | int minphaserev = -1, rev, i; | |
|
803 | const int numphases = (int)(sizeof(phasesets) / sizeof(phasesets[0])); | |
|
792 | 804 | |
|
793 | 805 | if (!PyArg_ParseTuple(args, "O", &roots)) |
|
794 | goto done; | |
|
795 |
if (roots == NULL || !Py |
|
|
796 |
PyErr_SetString(PyExc_TypeError, "roots must be a |
|
|
797 | goto done; | |
|
806 | return NULL; | |
|
807 | if (roots == NULL || !PyDict_Check(roots)) { | |
|
808 | PyErr_SetString(PyExc_TypeError, "roots must be a dictionary"); | |
|
809 | return NULL; | |
|
798 | 810 | } |
|
799 | 811 | |
|
800 | phases = calloc( | |
|
801 | len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */ | |
|
812 | phases = calloc(len, 1); | |
|
802 | 813 | if (phases == NULL) { |
|
803 | 814 | PyErr_NoMemory(); |
|
804 | goto done; | |
|
815 | return NULL; | |
|
805 | 816 | } |
|
806 | /* Put the phase information of all the roots in phases */ | |
|
807 | numphase = PyList_GET_SIZE(roots) + 1; | |
|
808 | minrevallphases = len + 1; | |
|
809 | phasessetlist = PyList_New(numphase); | |
|
810 | if (phasessetlist == NULL) | |
|
811 | goto done; | |
|
812 | 817 | |
|
813 | PyList_SET_ITEM(phasessetlist, 0, Py_None); | |
|
814 | Py_INCREF(Py_None); | |
|
818 | for (i = 0; i < numphases; ++i) { | |
|
819 | pyphase = PyInt_FromLong(trackedphases[i]); | |
|
820 | if (pyphase == NULL) | |
|
821 | goto release; | |
|
822 | phaseroots = PyDict_GetItem(roots, pyphase); | |
|
823 | Py_DECREF(pyphase); | |
|
824 | if (phaseroots == NULL) | |
|
825 | continue; | |
|
826 | rev = add_roots_get_min(self, phaseroots, phases, trackedphases[i]); | |
|
827 | phaseroots = NULL; | |
|
828 | if (rev == -2) | |
|
829 | goto release; | |
|
830 | if (rev != -1 && (minphaserev == -1 || rev < minphaserev)) | |
|
831 | minphaserev = rev; | |
|
832 | } | |
|
815 | 833 | |
|
816 |
for (i = 0; i < numphase |
|
|
817 | phaseroots = PyList_GET_ITEM(roots, i); | |
|
818 |
phaseset = |
|
|
819 | if (phaseset == NULL) | |
|
820 | goto release; | |
|
821 | PyList_SET_ITEM(phasessetlist, i + 1, phaseset); | |
|
822 | if (!PyList_Check(phaseroots)) { | |
|
823 | PyErr_SetString(PyExc_TypeError, | |
|
824 | "roots item must be a list"); | |
|
834 | for (i = 0; i < numphases; ++i) { | |
|
835 | phasesets[i] = PySet_New(NULL); | |
|
836 | if (phasesets[i] == NULL) | |
|
825 | 837 | goto release; |
|
826 | 838 |
|
|
827 | minrevphase = | |
|
828 | add_roots_get_min(self, phaseroots, i + 1, phases); | |
|
829 | if (minrevphase == -2) /* Error from add_roots_get_min */ | |
|
830 | goto release; | |
|
831 | minrevallphases = MIN(minrevallphases, minrevphase); | |
|
832 | } | |
|
833 | /* Propagate the phase information from the roots to the revs */ | |
|
834 | if (minrevallphases != -1) { | |
|
839 | ||
|
840 | if (minphaserev == -1) | |
|
841 | minphaserev = len; | |
|
842 | for (rev = minphaserev; rev < len; ++rev) { | |
|
835 | 843 | int parents[2]; |
|
836 | for (i = minrevallphases; i < len; i++) { | |
|
837 | if (index_get_parents(self, i, parents, (int)len - 1) < | |
|
838 | 0) | |
|
844 | /* | |
|
845 | * The parent lookup could be skipped for phaseroots, but | |
|
846 | * phase --force would historically not recompute them | |
|
847 | * correctly, leaving descendents with a lower phase around. | |
|
848 | * As such, unconditionally recompute the phase. | |
|
849 | */ | |
|
850 | if (index_get_parents(self, rev, parents, (int)len - 1) < 0) | |
|
839 | 851 |
|
|
840 |
|
|
|
841 | i); | |
|
852 | set_phase_from_parents(phases, parents[0], parents[1], rev); | |
|
853 | switch (phases[rev]) { | |
|
854 | case 0: | |
|
855 | continue; | |
|
856 | case 1: | |
|
857 | pyphase = phasesets[0]; | |
|
858 | break; | |
|
859 | case 2: | |
|
860 | pyphase = phasesets[1]; | |
|
861 | break; | |
|
862 | case 32: | |
|
863 | pyphase = phasesets[2]; | |
|
864 | break; | |
|
865 | case 96: | |
|
866 | pyphase = phasesets[3]; | |
|
867 | break; | |
|
868 | default: | |
|
869 | goto release; | |
|
842 | 870 | } |
|
871 | pyrev = PyInt_FromLong(rev); | |
|
872 | if (pyrev == NULL) | |
|
873 | goto release; | |
|
874 | if (PySet_Add(pyphase, pyrev) == -1) { | |
|
875 | Py_DECREF(pyrev); | |
|
876 | goto release; | |
|
843 | 877 | } |
|
844 | /* Transform phase list to a python list */ | |
|
878 | Py_DECREF(pyrev); | |
|
879 | } | |
|
880 | phaseroots = _dict_new_presized(numphases); | |
|
881 | if (phaseroots == NULL) | |
|
882 | goto release; | |
|
883 | for (int i = 0; i < numphases; ++i) { | |
|
884 | pyphase = PyInt_FromLong(trackedphases[i]); | |
|
885 | if (pyphase == NULL) | |
|
886 | goto release; | |
|
887 | if (PyDict_SetItem(phaseroots, pyphase, phasesets[i]) == -1) { | |
|
888 | Py_DECREF(pyphase); | |
|
889 | goto release; | |
|
890 | } | |
|
891 | Py_DECREF(phasesets[i]); | |
|
892 | phasesets[i] = NULL; | |
|
893 | } | |
|
845 | 894 | phasessize = PyInt_FromSsize_t(len); |
|
846 | 895 | if (phasessize == NULL) |
|
847 | 896 | goto release; |
|
848 | for (i = 0; i < len; i++) { | |
|
849 | phase = phases[i]; | |
|
850 | /* We only store the sets of phase for non public phase, the | |
|
851 | * public phase is computed as a difference */ | |
|
852 | if (phase != 0) { | |
|
853 | phaseset = PyList_GET_ITEM(phasessetlist, phase); | |
|
854 | rev = PyInt_FromSsize_t(i); | |
|
855 | if (rev == NULL) | |
|
856 | goto release; | |
|
857 | PySet_Add(phaseset, rev); | |
|
858 | Py_XDECREF(rev); | |
|
859 | } | |
|
860 | } | |
|
861 | ret = PyTuple_Pack(2, phasessize, phasessetlist); | |
|
897 | ||
|
898 | ret = PyTuple_Pack(2, phasessize, phaseroots); | |
|
899 | Py_DECREF(phasessize); | |
|
900 | Py_DECREF(phaseroots); | |
|
901 | return ret; | |
|
862 | 902 | |
|
863 | 903 | release: |
|
864 | Py_XDECREF(phasessize); | |
|
865 |
Py_XDECREF(phases |
|
|
866 | done: | |
|
904 | for (i = 0; i < numphases; ++i) | |
|
905 | Py_XDECREF(phasesets[i]); | |
|
906 | Py_XDECREF(phaseroots); | |
|
907 | ||
|
867 | 908 | free(phases); |
|
868 |
return |
|
|
909 | return NULL; | |
|
869 | 910 | } |
|
870 | 911 | |
|
871 | 912 | static PyObject *index_headrevs(indexObject *self, PyObject *args) |
@@ -170,7 +170,7 b' def _readroots(repo, phasedefaults=None)' | |||
|
170 | 170 | """ |
|
171 | 171 | repo = repo.unfiltered() |
|
172 | 172 | dirty = False |
|
173 |
roots = |
|
|
173 | roots = {i: set() for i in allphases} | |
|
174 | 174 | try: |
|
175 | 175 | f, pending = txnutil.trypending(repo.root, repo.svfs, b'phaseroots') |
|
176 | 176 | try: |
@@ -333,7 +333,11 b' class phasecache(object):' | |||
|
333 | 333 | if len(cl) >= self._loadedrevslen: |
|
334 | 334 | self.invalidate() |
|
335 | 335 | self.loadphaserevs(repo) |
|
336 |
return any( |
|
|
336 | return any( | |
|
337 | revs | |
|
338 | for phase, revs in pycompat.iteritems(self.phaseroots) | |
|
339 | if phase != public | |
|
340 | ) | |
|
337 | 341 | |
|
338 | 342 | def nonpublicphaseroots(self, repo): |
|
339 | 343 | """returns the roots of all non-public phases |
@@ -346,7 +350,13 b' class phasecache(object):' | |||
|
346 | 350 | if len(cl) >= self._loadedrevslen: |
|
347 | 351 | self.invalidate() |
|
348 | 352 | self.loadphaserevs(repo) |
|
349 | return set().union(*[roots for roots in self.phaseroots[1:] if roots]) | |
|
353 | return set().union( | |
|
354 | *[ | |
|
355 | revs | |
|
356 | for phase, revs in pycompat.iteritems(self.phaseroots) | |
|
357 | if phase != public | |
|
358 | ] | |
|
359 | ) | |
|
350 | 360 | |
|
351 | 361 | def getrevset(self, repo, phases, subset=None): |
|
352 | 362 | """return a smartset for the given phases""" |
@@ -405,7 +415,7 b' class phasecache(object):' | |||
|
405 | 415 | # Shallow copy meant to ensure isolation in |
|
406 | 416 | # advance/retractboundary(), nothing more. |
|
407 | 417 | ph = self.__class__(None, None, _load=False) |
|
408 |
ph.phaseroots = self.phaseroots |
|
|
418 | ph.phaseroots = self.phaseroots.copy() | |
|
409 | 419 | ph.dirty = self.dirty |
|
410 | 420 | ph.opener = self.opener |
|
411 | 421 | ph._loadedrevslen = self._loadedrevslen |
@@ -425,21 +435,12 b' class phasecache(object):' | |||
|
425 | 435 | |
|
426 | 436 | def _getphaserevsnative(self, repo): |
|
427 | 437 | repo = repo.unfiltered() |
|
428 | nativeroots = [] | |
|
429 | for phase in trackedphases: | |
|
430 | nativeroots.append( | |
|
431 | pycompat.maplist(repo.changelog.rev, self.phaseroots[phase]) | |
|
432 | ) | |
|
433 | revslen, phasesets = repo.changelog.computephases(nativeroots) | |
|
434 | phasesets2 = [set() for phase in range(max(allphases) + 1)] | |
|
435 | for phase, phaseset in zip(allphases, phasesets): | |
|
436 | phasesets2[phase] = phaseset | |
|
437 | return revslen, phasesets2 | |
|
438 | return repo.changelog.computephases(self.phaseroots) | |
|
438 | 439 | |
|
439 | 440 | def _computephaserevspure(self, repo): |
|
440 | 441 | repo = repo.unfiltered() |
|
441 | 442 | cl = repo.changelog |
|
442 |
self._phasesets = |
|
|
443 | self._phasesets = {phase: set() for phase in allphases} | |
|
443 | 444 | lowerroots = set() |
|
444 | 445 | for phase in reversed(trackedphases): |
|
445 | 446 | roots = pycompat.maplist(cl.rev, self.phaseroots[phase]) |
@@ -493,7 +494,7 b' class phasecache(object):' | |||
|
493 | 494 | f.close() |
|
494 | 495 | |
|
495 | 496 | def _write(self, fp): |
|
496 |
for phase, roots in |
|
|
497 | for phase, roots in pycompat.iteritems(self.phaseroots): | |
|
497 | 498 | for h in sorted(roots): |
|
498 | 499 | fp.write(b'%i %s\n' % (phase, hex(h))) |
|
499 | 500 | self.dirty = False |
@@ -575,7 +576,11 b' class phasecache(object):' | |||
|
575 | 576 | return changes |
|
576 | 577 | |
|
577 | 578 | def retractboundary(self, repo, tr, targetphase, nodes): |
|
578 | oldroots = self.phaseroots[: targetphase + 1] | |
|
579 | oldroots = { | |
|
580 | phase: revs | |
|
581 | for phase, revs in pycompat.iteritems(self.phaseroots) | |
|
582 | if phase <= targetphase | |
|
583 | } | |
|
579 | 584 | if tr is None: |
|
580 | 585 | phasetracking = None |
|
581 | 586 | else: |
@@ -594,7 +599,7 b' class phasecache(object):' | |||
|
594 | 599 | # find the phase of the affected revision |
|
595 | 600 | for phase in pycompat.xrange(targetphase, -1, -1): |
|
596 | 601 | if phase: |
|
597 |
roots = oldroots[ |
|
|
602 | roots = oldroots.get(phase, []) | |
|
598 | 603 | revs = set(repo.revs(b'%ln::%ld', roots, affected)) |
|
599 | 604 | affected -= revs |
|
600 | 605 | else: # public phase |
@@ -648,7 +653,7 b' class phasecache(object):' | |||
|
648 | 653 | """ |
|
649 | 654 | filtered = False |
|
650 | 655 | has_node = repo.changelog.index.has_node # to filter unknown nodes |
|
651 |
for phase, nodes in |
|
|
656 | for phase, nodes in pycompat.iteritems(self.phaseroots): | |
|
652 | 657 | missing = sorted(node for node in nodes if not has_node(node)) |
|
653 | 658 | if missing: |
|
654 | 659 | for mnode in missing: |
@@ -80,7 +80,7 b' def _importfrom(pkgname, modname):' | |||
|
80 | 80 | ('cext', 'bdiff'): 3, |
|
81 | 81 | ('cext', 'mpatch'): 1, |
|
82 | 82 | ('cext', 'osutil'): 4, |
|
83 |
('cext', 'parsers'): 1 |
|
|
83 | ('cext', 'parsers'): 17, | |
|
84 | 84 | } |
|
85 | 85 | |
|
86 | 86 | # map import request to other package or module |
@@ -185,7 +185,7 b' Test corrupted p1/p2 fields that could c' | |||
|
185 | 185 | > ops = [ |
|
186 | 186 | > ('reachableroots', |
|
187 | 187 | > lambda: cl.index.reachableroots2(0, [1], [0], False)), |
|
188 |
> ('compute_phases_map_sets', lambda: cl.computephases( |
|
|
188 | > ('compute_phases_map_sets', lambda: cl.computephases({1: {cl.node(0)}})), | |
|
189 | 189 | > ('index_headrevs', lambda: cl.headrevs()), |
|
190 | 190 | > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)), |
|
191 | 191 | > ('find_deepest', lambda: cl.ancestor(n0, n1)), |
General Comments 0
You need to be logged in to leave comments.
Login now