changeset 40562 | e5ad3ef90aa1 |
parent 40561 | 5c14bf0c5be3 |
child 40598 | fa33196088c4 |
40561:5c14bf0c5be3 | 40562:e5ad3ef90aa1 |
---|---|
42 * Zero is empty |
42 * Zero is empty |
43 */ |
43 */ |
44 typedef struct { |
44 typedef struct { |
45 indexObject *index; |
45 indexObject *index; |
46 nodetreenode *nodes; |
46 nodetreenode *nodes; |
47 unsigned length; /* # nodes in use */ |
47 unsigned length; /* # nodes in use */ |
48 unsigned capacity; /* # nodes allocated */ |
48 unsigned capacity; /* # nodes allocated */ |
49 int depth; /* maximum depth of tree */ |
49 int depth; /* maximum depth of tree */ |
50 int splits; /* # splits performed */ |
50 int splits; /* # splits performed */ |
51 } nodetree; |
51 } nodetree; |
52 |
52 |
53 typedef struct { |
53 typedef struct { |
54 PyObject_HEAD /* ; */ |
54 PyObject_HEAD /* ; */ |
55 nodetree nt; |
55 nodetree nt; |
56 } nodetreeObject; |
56 } nodetreeObject; |
57 |
57 |
58 /* |
58 /* |
59 * This class has two behaviors. |
59 * This class has two behaviors. |
60 * |
60 * |
67 * With string keys, we lazily perform a reverse mapping from node to |
67 * With string keys, we lazily perform a reverse mapping from node to |
68 * rev, using a base-16 trie. |
68 * rev, using a base-16 trie. |
69 */ |
69 */ |
70 struct indexObjectStruct { |
70 struct indexObjectStruct { |
71 PyObject_HEAD |
71 PyObject_HEAD |
72 /* Type-specific fields go here. */ |
72 /* Type-specific fields go here. */ |
73 PyObject *data; /* raw bytes of index */ |
73 PyObject *data; /* raw bytes of index */ |
74 Py_buffer buf; /* buffer of data */ |
74 Py_buffer buf; /* buffer of data */ |
75 PyObject **cache; /* cached tuples */ |
75 PyObject **cache; /* cached tuples */ |
76 const char **offsets; /* populated on demand */ |
76 const char **offsets; /* populated on demand */ |
77 Py_ssize_t raw_length; /* original number of elements */ |
77 Py_ssize_t raw_length; /* original number of elements */ |
78 Py_ssize_t length; /* current number of elements */ |
78 Py_ssize_t length; /* current number of elements */ |
79 PyObject *added; /* populated on demand */ |
79 PyObject *added; /* populated on demand */ |
80 PyObject *headrevs; /* cache, invalidated on changes */ |
80 PyObject *headrevs; /* cache, invalidated on changes */ |
81 PyObject *filteredrevs;/* filtered revs set */ |
81 PyObject *filteredrevs; /* filtered revs set */ |
82 nodetree nt; /* base-16 trie */ |
82 nodetree nt; /* base-16 trie */ |
83 int ntinitialized; /* 0 or 1 */ |
83 int ntinitialized; /* 0 or 1 */ |
84 int ntrev; /* last rev scanned */ |
84 int ntrev; /* last rev scanned */ |
85 int ntlookups; /* # lookups */ |
85 int ntlookups; /* # lookups */ |
86 int ntmisses; /* # lookups that miss the cache */ |
86 int ntmisses; /* # lookups that miss the cache */ |
87 int inlined; |
87 int inlined; |
88 }; |
88 }; |
89 |
89 |
90 static Py_ssize_t index_length(const indexObject *self) |
90 static Py_ssize_t index_length(const indexObject *self) |
91 { |
91 { |
124 Py_INCREF(dict); |
124 Py_INCREF(dict); |
125 |
125 |
126 errclass = PyDict_GetItemString(dict, "RevlogError"); |
126 errclass = PyDict_GetItemString(dict, "RevlogError"); |
127 if (errclass == NULL) { |
127 if (errclass == NULL) { |
128 PyErr_SetString(PyExc_SystemError, |
128 PyErr_SetString(PyExc_SystemError, |
129 "could not find RevlogError"); |
129 "could not find RevlogError"); |
130 goto cleanup; |
130 goto cleanup; |
131 } |
131 } |
132 |
132 |
133 /* value of exception is ignored by callers */ |
133 /* value of exception is ignored by callers */ |
134 PyErr_SetString(errclass, "RevlogError"); |
134 PyErr_SetString(errclass, "RevlogError"); |
144 static const char *index_deref(indexObject *self, Py_ssize_t pos) |
144 static const char *index_deref(indexObject *self, Py_ssize_t pos) |
145 { |
145 { |
146 if (self->inlined && pos > 0) { |
146 if (self->inlined && pos > 0) { |
147 if (self->offsets == NULL) { |
147 if (self->offsets == NULL) { |
148 self->offsets = PyMem_Malloc(self->raw_length * |
148 self->offsets = PyMem_Malloc(self->raw_length * |
149 sizeof(*self->offsets)); |
149 sizeof(*self->offsets)); |
150 if (self->offsets == NULL) |
150 if (self->offsets == NULL) |
151 return (const char *)PyErr_NoMemory(); |
151 return (const char *)PyErr_NoMemory(); |
152 inline_scan(self, self->offsets); |
152 inline_scan(self, self->offsets); |
153 } |
153 } |
154 return self->offsets[pos]; |
154 return self->offsets[pos]; |
155 } |
155 } |
156 |
156 |
157 return (const char *)(self->buf.buf) + pos * v1_hdrsize; |
157 return (const char *)(self->buf.buf) + pos * v1_hdrsize; |
158 } |
158 } |
159 |
159 |
160 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, |
160 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps, |
161 int *ps, int maxrev) |
161 int maxrev) |
162 { |
162 { |
163 if (rev >= self->length) { |
163 if (rev >= self->length) { |
164 PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length); |
164 PyObject *tuple = |
165 PyList_GET_ITEM(self->added, rev - self->length); |
|
165 ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5)); |
166 ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5)); |
166 ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6)); |
167 ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6)); |
167 } else { |
168 } else { |
168 const char *data = index_deref(self, rev); |
169 const char *data = index_deref(self, rev); |
169 ps[0] = getbe32(data + 24); |
170 ps[0] = getbe32(data + 24); |
175 PyErr_SetString(PyExc_ValueError, "parent out of range"); |
176 PyErr_SetString(PyExc_ValueError, "parent out of range"); |
176 return -1; |
177 return -1; |
177 } |
178 } |
178 return 0; |
179 return 0; |
179 } |
180 } |
180 |
|
181 |
181 |
182 /* |
182 /* |
183 * RevlogNG format (all in big endian, data may be inlined): |
183 * RevlogNG format (all in big endian, data may be inlined): |
184 * 6 bytes: offset |
184 * 6 bytes: offset |
185 * 2 bytes: flags |
185 * 2 bytes: flags |
246 link_rev = getbe32(data + 20); |
246 link_rev = getbe32(data + 20); |
247 parent_1 = getbe32(data + 24); |
247 parent_1 = getbe32(data + 24); |
248 parent_2 = getbe32(data + 28); |
248 parent_2 = getbe32(data + 28); |
249 c_node_id = data + 32; |
249 c_node_id = data + 32; |
250 |
250 |
251 entry = Py_BuildValue(tuple_format, offset_flags, comp_len, |
251 entry = Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, |
252 uncomp_len, base_rev, link_rev, |
252 base_rev, link_rev, parent_1, parent_2, c_node_id, |
253 parent_1, parent_2, c_node_id, 20); |
253 20); |
254 |
254 |
255 if (entry) { |
255 if (entry) { |
256 PyObject_GC_UnTrack(entry); |
256 PyObject_GC_UnTrack(entry); |
257 Py_INCREF(entry); |
257 Py_INCREF(entry); |
258 } |
258 } |
352 PyObject *t = NULL; |
352 PyObject *t = NULL; |
353 |
353 |
354 if (obj == NULL) |
354 if (obj == NULL) |
355 return NULL; |
355 return NULL; |
356 |
356 |
357 #define istat(__n, __d) \ |
357 #define istat(__n, __d) \ |
358 do { \ |
358 do { \ |
359 s = PyBytes_FromString(__d); \ |
359 s = PyBytes_FromString(__d); \ |
360 t = PyInt_FromSsize_t(self->__n); \ |
360 t = PyInt_FromSsize_t(self->__n); \ |
361 if (!s || !t) \ |
361 if (!s || !t) \ |
362 goto bail; \ |
362 goto bail; \ |
363 if (PyDict_SetItem(obj, s, t) == -1) \ |
363 if (PyDict_SetItem(obj, s, t) == -1) \ |
364 goto bail; \ |
364 goto bail; \ |
365 Py_CLEAR(s); \ |
365 Py_CLEAR(s); \ |
366 Py_CLEAR(t); \ |
366 Py_CLEAR(t); \ |
367 } while (0) |
367 } while (0) |
368 |
368 |
369 if (self->added) { |
369 if (self->added) { |
370 Py_ssize_t len = PyList_GET_SIZE(self->added); |
370 Py_ssize_t len = PyList_GET_SIZE(self->added); |
371 s = PyBytes_FromString("index entries added"); |
371 s = PyBytes_FromString("index entries added"); |
505 Py_ssize_t l; |
505 Py_ssize_t l; |
506 int r; |
506 int r; |
507 int parents[2]; |
507 int parents[2]; |
508 |
508 |
509 /* Internal data structure: |
509 /* Internal data structure: |
510 * tovisit: array of length len+1 (all revs + nullrev), filled upto lentovisit |
510 * tovisit: array of length len+1 (all revs + nullrev), filled upto |
511 * lentovisit |
|
511 * |
512 * |
512 * revstates: array of length len+1 (all revs + nullrev) */ |
513 * revstates: array of length len+1 (all revs + nullrev) */ |
513 int *tovisit = NULL; |
514 int *tovisit = NULL; |
514 long lentovisit = 0; |
515 long lentovisit = 0; |
515 enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 }; |
516 enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 }; |
516 char *revstates = NULL; |
517 char *revstates = NULL; |
517 |
518 |
518 /* Get arguments */ |
519 /* Get arguments */ |
519 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads, |
520 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads, |
520 &PyList_Type, &roots, |
521 &PyList_Type, &roots, &PyBool_Type, |
521 &PyBool_Type, &includepatharg)) |
522 &includepatharg)) |
522 goto bail; |
523 goto bail; |
523 |
524 |
524 if (includepatharg == Py_True) |
525 if (includepatharg == Py_True) |
525 includepath = 1; |
526 includepath = 1; |
526 |
527 |
593 continue; |
594 continue; |
594 r = index_get_parents(self, revnum, parents, (int)len - 1); |
595 r = index_get_parents(self, revnum, parents, (int)len - 1); |
595 if (r < 0) |
596 if (r < 0) |
596 goto bail; |
597 goto bail; |
597 for (i = 0; i < 2; i++) { |
598 for (i = 0; i < 2; i++) { |
598 if (!(revstates[parents[i] + 1] & RS_SEEN) |
599 if (!(revstates[parents[i] + 1] & RS_SEEN) && |
599 && parents[i] >= minroot) { |
600 parents[i] >= minroot) { |
600 tovisit[lentovisit++] = parents[i]; |
601 tovisit[lentovisit++] = parents[i]; |
601 revstates[parents[i] + 1] |= RS_SEEN; |
602 revstates[parents[i] + 1] |= RS_SEEN; |
602 } |
603 } |
603 } |
604 } |
604 } |
605 } |
616 /* Corrupted index file, error is set from |
617 /* Corrupted index file, error is set from |
617 * index_get_parents */ |
618 * index_get_parents */ |
618 if (r < 0) |
619 if (r < 0) |
619 goto bail; |
620 goto bail; |
620 if (((revstates[parents[0] + 1] | |
621 if (((revstates[parents[0] + 1] | |
621 revstates[parents[1] + 1]) & RS_REACHABLE) |
622 revstates[parents[1] + 1]) & |
622 && !(revstates[i + 1] & RS_REACHABLE)) { |
623 RS_REACHABLE) && |
624 !(revstates[i + 1] & RS_REACHABLE)) { |
|
623 revstates[i + 1] |= RS_REACHABLE; |
625 revstates[i + 1] |= RS_REACHABLE; |
624 val = PyInt_FromSsize_t(i); |
626 val = PyInt_FromSsize_t(i); |
625 if (val == NULL) |
627 if (val == NULL) |
626 goto bail; |
628 goto bail; |
627 r = PyList_Append(reachable, val); |
629 r = PyList_Append(reachable, val); |
664 if (roots == NULL || !PyList_Check(roots)) { |
666 if (roots == NULL || !PyList_Check(roots)) { |
665 PyErr_SetString(PyExc_TypeError, "roots must be a list"); |
667 PyErr_SetString(PyExc_TypeError, "roots must be a list"); |
666 goto done; |
668 goto done; |
667 } |
669 } |
668 |
670 |
669 phases = calloc(len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */ |
671 phases = calloc( |
672 len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */ |
|
670 if (phases == NULL) { |
673 if (phases == NULL) { |
671 PyErr_NoMemory(); |
674 PyErr_NoMemory(); |
672 goto done; |
675 goto done; |
673 } |
676 } |
674 /* Put the phase information of all the roots in phases */ |
677 /* Put the phase information of all the roots in phases */ |
675 numphase = PyList_GET_SIZE(roots)+1; |
678 numphase = PyList_GET_SIZE(roots) + 1; |
676 minrevallphases = len + 1; |
679 minrevallphases = len + 1; |
677 phasessetlist = PyList_New(numphase); |
680 phasessetlist = PyList_New(numphase); |
678 if (phasessetlist == NULL) |
681 if (phasessetlist == NULL) |
679 goto done; |
682 goto done; |
680 |
683 |
681 PyList_SET_ITEM(phasessetlist, 0, Py_None); |
684 PyList_SET_ITEM(phasessetlist, 0, Py_None); |
682 Py_INCREF(Py_None); |
685 Py_INCREF(Py_None); |
683 |
686 |
684 for (i = 0; i < numphase-1; i++) { |
687 for (i = 0; i < numphase - 1; i++) { |
685 phaseroots = PyList_GET_ITEM(roots, i); |
688 phaseroots = PyList_GET_ITEM(roots, i); |
686 phaseset = PySet_New(NULL); |
689 phaseset = PySet_New(NULL); |
687 if (phaseset == NULL) |
690 if (phaseset == NULL) |
688 goto release; |
691 goto release; |
689 PyList_SET_ITEM(phasessetlist, i+1, phaseset); |
692 PyList_SET_ITEM(phasessetlist, i + 1, phaseset); |
690 if (!PyList_Check(phaseroots)) { |
693 if (!PyList_Check(phaseroots)) { |
691 PyErr_SetString(PyExc_TypeError, |
694 PyErr_SetString(PyExc_TypeError, |
692 "roots item must be a list"); |
695 "roots item must be a list"); |
693 goto release; |
696 goto release; |
694 } |
697 } |
695 minrevphase = add_roots_get_min(self, phaseroots, i+1, phases); |
698 minrevphase = |
699 add_roots_get_min(self, phaseroots, i + 1, phases); |
|
696 if (minrevphase == -2) /* Error from add_roots_get_min */ |
700 if (minrevphase == -2) /* Error from add_roots_get_min */ |
697 goto release; |
701 goto release; |
698 minrevallphases = MIN(minrevallphases, minrevphase); |
702 minrevallphases = MIN(minrevallphases, minrevphase); |
699 } |
703 } |
700 /* Propagate the phase information from the roots to the revs */ |
704 /* Propagate the phase information from the roots to the revs */ |
701 if (minrevallphases != -1) { |
705 if (minrevallphases != -1) { |
702 int parents[2]; |
706 int parents[2]; |
703 for (i = minrevallphases; i < len; i++) { |
707 for (i = minrevallphases; i < len; i++) { |
704 if (index_get_parents(self, i, parents, |
708 if (index_get_parents(self, i, parents, (int)len - 1) < |
705 (int)len - 1) < 0) |
709 0) |
706 goto release; |
710 goto release; |
707 set_phase_from_parents(phases, parents[0], parents[1], i); |
711 set_phase_from_parents(phases, parents[0], parents[1], |
712 i); |
|
708 } |
713 } |
709 } |
714 } |
710 /* Transform phase list to a python list */ |
715 /* Transform phase list to a python list */ |
711 phasessize = PyInt_FromSsize_t(len); |
716 phasessize = PyInt_FromSsize_t(len); |
712 if (phasessize == NULL) |
717 if (phasessize == NULL) |
713 goto release; |
718 goto release; |
714 for (i = 0; i < len; i++) { |
719 for (i = 0; i < len; i++) { |
715 phase = phases[i]; |
720 phase = phases[i]; |
716 /* We only store the sets of phase for non public phase, the public phase |
721 /* We only store the sets of phase for non public phase, the |
717 * is computed as a difference */ |
722 * public phase is computed as a difference */ |
718 if (phase != 0) { |
723 if (phase != 0) { |
719 phaseset = PyList_GET_ITEM(phasessetlist, phase); |
724 phaseset = PyList_GET_ITEM(phasessetlist, phase); |
720 rev = PyInt_FromSsize_t(i); |
725 rev = PyInt_FromSsize_t(i); |
721 if (rev == NULL) |
726 if (rev == NULL) |
722 goto release; |
727 goto release; |
754 Py_INCREF(filteredrevs); |
759 Py_INCREF(filteredrevs); |
755 |
760 |
756 if (filteredrevs != Py_None) { |
761 if (filteredrevs != Py_None) { |
757 filter = PyObject_GetAttrString(filteredrevs, "__contains__"); |
762 filter = PyObject_GetAttrString(filteredrevs, "__contains__"); |
758 if (!filter) { |
763 if (!filter) { |
759 PyErr_SetString(PyExc_TypeError, |
764 PyErr_SetString( |
760 "filteredrevs has no attribute __contains__"); |
765 PyExc_TypeError, |
766 "filteredrevs has no attribute __contains__"); |
|
761 goto bail; |
767 goto bail; |
762 } |
768 } |
763 } |
769 } |
764 |
770 |
765 len = index_length(self); |
771 len = index_length(self); |
783 |
789 |
784 for (i = len - 1; i >= 0; i--) { |
790 for (i = len - 1; i >= 0; i--) { |
785 int isfiltered; |
791 int isfiltered; |
786 int parents[2]; |
792 int parents[2]; |
787 |
793 |
788 /* If nothead[i] == 1, it means we've seen an unfiltered child of this |
794 /* If nothead[i] == 1, it means we've seen an unfiltered child |
789 * node already, and therefore this node is not filtered. So we can skip |
795 * of this node already, and therefore this node is not |
790 * the expensive check_filter step. |
796 * filtered. So we can skip the expensive check_filter step. |
791 */ |
797 */ |
792 if (nothead[i] != 1) { |
798 if (nothead[i] != 1) { |
793 isfiltered = check_filter(filter, i); |
799 isfiltered = check_filter(filter, i); |
794 if (isfiltered == -1) { |
800 if (isfiltered == -1) { |
795 PyErr_SetString(PyExc_TypeError, |
801 PyErr_SetString(PyExc_TypeError, |
796 "unable to check filter"); |
802 "unable to check filter"); |
797 goto bail; |
803 goto bail; |
798 } |
804 } |
799 |
805 |
800 if (isfiltered) { |
806 if (isfiltered) { |
801 nothead[i] = 1; |
807 nothead[i] = 1; |
843 static inline int index_baserev(indexObject *self, int rev) |
849 static inline int index_baserev(indexObject *self, int rev) |
844 { |
850 { |
845 const char *data; |
851 const char *data; |
846 |
852 |
847 if (rev >= self->length) { |
853 if (rev >= self->length) { |
848 PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length); |
854 PyObject *tuple = |
855 PyList_GET_ITEM(self->added, rev - self->length); |
|
849 return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3)); |
856 return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3)); |
850 } |
857 } else { |
851 else { |
|
852 data = index_deref(self, rev); |
858 data = index_deref(self, rev); |
853 if (data == NULL) { |
859 if (data == NULL) { |
854 return -2; |
860 return -2; |
855 } |
861 } |
856 |
862 |
874 if (PyInt_Check(stoparg)) { |
880 if (PyInt_Check(stoparg)) { |
875 stoprev = (int)PyInt_AsLong(stoparg); |
881 stoprev = (int)PyInt_AsLong(stoparg); |
876 if (stoprev == -1 && PyErr_Occurred()) { |
882 if (stoprev == -1 && PyErr_Occurred()) { |
877 return NULL; |
883 return NULL; |
878 } |
884 } |
879 } |
885 } else if (stoparg == Py_None) { |
880 else if (stoparg == Py_None) { |
|
881 stoprev = -2; |
886 stoprev = -2; |
882 } |
887 } else { |
883 else { |
|
884 PyErr_SetString(PyExc_ValueError, |
888 PyErr_SetString(PyExc_ValueError, |
885 "stoprev must be integer or None"); |
889 "stoprev must be integer or None"); |
886 return NULL; |
890 return NULL; |
887 } |
891 } |
888 |
892 |
889 if (rev < 0 || rev >= length) { |
893 if (rev < 0 || rev >= length) { |
890 PyErr_SetString(PyExc_ValueError, "revlog index out of range"); |
894 PyErr_SetString(PyExc_ValueError, "revlog index out of range"); |
918 } |
922 } |
919 Py_DECREF(value); |
923 Py_DECREF(value); |
920 |
924 |
921 if (generaldelta) { |
925 if (generaldelta) { |
922 iterrev = baserev; |
926 iterrev = baserev; |
923 } |
927 } else { |
924 else { |
|
925 iterrev--; |
928 iterrev--; |
926 } |
929 } |
927 |
930 |
928 if (iterrev < 0) { |
931 if (iterrev < 0) { |
929 break; |
932 break; |
930 } |
933 } |
931 |
934 |
932 if (iterrev >= length) { |
935 if (iterrev >= length) { |
933 PyErr_SetString(PyExc_IndexError, "revision outside index"); |
936 PyErr_SetString(PyExc_IndexError, |
937 "revision outside index"); |
|
934 return NULL; |
938 return NULL; |
935 } |
939 } |
936 |
940 |
937 baserev = index_baserev(self, iterrev); |
941 baserev = index_baserev(self, iterrev); |
938 |
942 |
944 } |
948 } |
945 } |
949 } |
946 |
950 |
947 if (iterrev == stoprev) { |
951 if (iterrev == stoprev) { |
948 stopped = 1; |
952 stopped = 1; |
949 } |
953 } else { |
950 else { |
|
951 PyObject *value = PyInt_FromLong(iterrev); |
954 PyObject *value = PyInt_FromLong(iterrev); |
952 if (value == NULL) { |
955 if (value == NULL) { |
953 goto bail; |
956 goto bail; |
954 } |
957 } |
955 if (PyList_Append(chain, value)) { |
958 if (PyList_Append(chain, value)) { |
974 return NULL; |
977 return NULL; |
975 } |
978 } |
976 |
979 |
977 static inline int nt_level(const char *node, Py_ssize_t level) |
980 static inline int nt_level(const char *node, Py_ssize_t level) |
978 { |
981 { |
979 int v = node[level>>1]; |
982 int v = node[level >> 1]; |
980 if (!(level & 1)) |
983 if (!(level & 1)) |
981 v >>= 4; |
984 v >>= 4; |
982 return v & 0xf; |
985 return v & 0xf; |
983 } |
986 } |
984 |
987 |
988 * -4: match is ambiguous (multiple candidates) |
991 * -4: match is ambiguous (multiple candidates) |
989 * -2: not found |
992 * -2: not found |
990 * rest: valid rev |
993 * rest: valid rev |
991 */ |
994 */ |
992 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen, |
995 static int nt_find(nodetree *self, const char *node, Py_ssize_t nodelen, |
993 int hex) |
996 int hex) |
994 { |
997 { |
995 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level; |
998 int (*getnybble)(const char *, Py_ssize_t) = hex ? hexdigit : nt_level; |
996 int level, maxlevel, off; |
999 int level, maxlevel, off; |
997 |
1000 |
998 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0) |
1001 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0) |
1034 if (self->length == self->capacity) { |
1037 if (self->length == self->capacity) { |
1035 unsigned newcapacity; |
1038 unsigned newcapacity; |
1036 nodetreenode *newnodes; |
1039 nodetreenode *newnodes; |
1037 newcapacity = self->capacity * 2; |
1040 newcapacity = self->capacity * 2; |
1038 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) { |
1041 if (newcapacity >= INT_MAX / sizeof(nodetreenode)) { |
1039 PyErr_SetString(PyExc_MemoryError, "overflow in nt_new"); |
1042 PyErr_SetString(PyExc_MemoryError, |
1043 "overflow in nt_new"); |
|
1040 return -1; |
1044 return -1; |
1041 } |
1045 } |
1042 newnodes = realloc(self->nodes, newcapacity * sizeof(nodetreenode)); |
1046 newnodes = |
1047 realloc(self->nodes, newcapacity * sizeof(nodetreenode)); |
|
1043 if (newnodes == NULL) { |
1048 if (newnodes == NULL) { |
1044 PyErr_SetString(PyExc_MemoryError, "out of memory"); |
1049 PyErr_SetString(PyExc_MemoryError, "out of memory"); |
1045 return -1; |
1050 return -1; |
1046 } |
1051 } |
1047 self->capacity = newcapacity; |
1052 self->capacity = newcapacity; |
1068 if (v == 0) { |
1073 if (v == 0) { |
1069 n->children[k] = -rev - 2; |
1074 n->children[k] = -rev - 2; |
1070 return 0; |
1075 return 0; |
1071 } |
1076 } |
1072 if (v < 0) { |
1077 if (v < 0) { |
1073 const char *oldnode = index_node_existing(self->index, -(v + 2)); |
1078 const char *oldnode = |
1079 index_node_existing(self->index, -(v + 2)); |
|
1074 int noff; |
1080 int noff; |
1075 |
1081 |
1076 if (oldnode == NULL) |
1082 if (oldnode == NULL) |
1077 return -1; |
1083 return -1; |
1078 if (!memcmp(oldnode, node, 20)) { |
1084 if (!memcmp(oldnode, node, 20)) { |
1117 Py_RETURN_NONE; |
1123 Py_RETURN_NONE; |
1118 } |
1124 } |
1119 |
1125 |
1120 static int nt_delete_node(nodetree *self, const char *node) |
1126 static int nt_delete_node(nodetree *self, const char *node) |
1121 { |
1127 { |
1122 /* rev==-2 happens to get encoded as 0, which is interpreted as not set */ |
1128 /* rev==-2 happens to get encoded as 0, which is interpreted as not set |
1129 */ |
|
1123 return nt_insert(self, node, -2); |
1130 return nt_insert(self, node, -2); |
1124 } |
1131 } |
1125 |
1132 |
1126 static int nt_init(nodetree *self, indexObject *index, unsigned capacity) |
1133 static int nt_init(nodetree *self, indexObject *index, unsigned capacity) |
1127 { |
1134 { |
1154 PyObject *index; |
1161 PyObject *index; |
1155 unsigned capacity; |
1162 unsigned capacity; |
1156 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity)) |
1163 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity)) |
1157 return -1; |
1164 return -1; |
1158 Py_INCREF(index); |
1165 Py_INCREF(index); |
1159 return nt_init(&self->nt, (indexObject*)index, capacity); |
1166 return nt_init(&self->nt, (indexObject *)index, capacity); |
1160 } |
1167 } |
1161 |
1168 |
1162 static int nt_partialmatch(nodetree *self, const char *node, |
1169 static int nt_partialmatch(nodetree *self, const char *node, Py_ssize_t nodelen) |
1163 Py_ssize_t nodelen) |
|
1164 { |
1170 { |
1165 return nt_find(self, node, nodelen, 1); |
1171 return nt_find(self, node, nodelen, 1); |
1166 } |
1172 } |
1167 |
1173 |
1168 /* |
1174 /* |
1244 nt_dealloc(&self->nt); |
1250 nt_dealloc(&self->nt); |
1245 PyObject_Del(self); |
1251 PyObject_Del(self); |
1246 } |
1252 } |
1247 |
1253 |
1248 static PyMethodDef ntobj_methods[] = { |
1254 static PyMethodDef ntobj_methods[] = { |
1249 {"insert", (PyCFunction)ntobj_insert, METH_VARARGS, |
1255 {"insert", (PyCFunction)ntobj_insert, METH_VARARGS, |
1250 "insert an index entry"}, |
1256 "insert an index entry"}, |
1251 {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS, |
1257 {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS, |
1252 "find length of shortest hex nodeid of a binary ID"}, |
1258 "find length of shortest hex nodeid of a binary ID"}, |
1253 {NULL} /* Sentinel */ |
1259 {NULL} /* Sentinel */ |
1254 }; |
1260 }; |
1255 |
1261 |
1256 static PyTypeObject nodetreeType = { |
1262 static PyTypeObject nodetreeType = { |
1257 PyVarObject_HEAD_INIT(NULL, 0) /* header */ |
1263 PyVarObject_HEAD_INIT(NULL, 0) /* header */ |
1258 "parsers.nodetree", /* tp_name */ |
1264 "parsers.nodetree", /* tp_name */ |
1259 sizeof(nodetreeObject) , /* tp_basicsize */ |
1265 sizeof(nodetreeObject), /* tp_basicsize */ |
1260 0, /* tp_itemsize */ |
1266 0, /* tp_itemsize */ |
1261 (destructor)ntobj_dealloc, /* tp_dealloc */ |
1267 (destructor)ntobj_dealloc, /* tp_dealloc */ |
1262 0, /* tp_print */ |
1268 0, /* tp_print */ |
1263 0, /* tp_getattr */ |
1269 0, /* tp_getattr */ |
1264 0, /* tp_setattr */ |
1270 0, /* tp_setattr */ |
1265 0, /* tp_compare */ |
1271 0, /* tp_compare */ |
1266 0, /* tp_repr */ |
1272 0, /* tp_repr */ |
1267 0, /* tp_as_number */ |
1273 0, /* tp_as_number */ |
1268 0, /* tp_as_sequence */ |
1274 0, /* tp_as_sequence */ |
1269 0, /* tp_as_mapping */ |
1275 0, /* tp_as_mapping */ |
1270 0, /* tp_hash */ |
1276 0, /* tp_hash */ |
1271 0, /* tp_call */ |
1277 0, /* tp_call */ |
1272 0, /* tp_str */ |
1278 0, /* tp_str */ |
1273 0, /* tp_getattro */ |
1279 0, /* tp_getattro */ |
1274 0, /* tp_setattro */ |
1280 0, /* tp_setattro */ |
1275 0, /* tp_as_buffer */ |
1281 0, /* tp_as_buffer */ |
1276 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
1282 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
1277 "nodetree", /* tp_doc */ |
1283 "nodetree", /* tp_doc */ |
1278 0, /* tp_traverse */ |
1284 0, /* tp_traverse */ |
1279 0, /* tp_clear */ |
1285 0, /* tp_clear */ |
1280 0, /* tp_richcompare */ |
1286 0, /* tp_richcompare */ |
1281 0, /* tp_weaklistoffset */ |
1287 0, /* tp_weaklistoffset */ |
1282 0, /* tp_iter */ |
1288 0, /* tp_iter */ |
1283 0, /* tp_iternext */ |
1289 0, /* tp_iternext */ |
1284 ntobj_methods, /* tp_methods */ |
1290 ntobj_methods, /* tp_methods */ |
1285 0, /* tp_members */ |
1291 0, /* tp_members */ |
1286 0, /* tp_getset */ |
1292 0, /* tp_getset */ |
1287 0, /* tp_base */ |
1293 0, /* tp_base */ |
1288 0, /* tp_dict */ |
1294 0, /* tp_dict */ |
1289 0, /* tp_descr_get */ |
1295 0, /* tp_descr_get */ |
1290 0, /* tp_descr_set */ |
1296 0, /* tp_descr_set */ |
1291 0, /* tp_dictoffset */ |
1297 0, /* tp_dictoffset */ |
1292 (initproc)ntobj_init, /* tp_init */ |
1298 (initproc)ntobj_init, /* tp_init */ |
1293 0, /* tp_alloc */ |
1299 0, /* tp_alloc */ |
1294 }; |
1300 }; |
1295 |
1301 |
1296 static int index_init_nt(indexObject *self) |
1302 static int index_init_nt(indexObject *self) |
1297 { |
1303 { |
1298 if (!self->ntinitialized) { |
1304 if (!self->ntinitialized) { |
1317 * |
1323 * |
1318 * -3: error (exception set) |
1324 * -3: error (exception set) |
1319 * -2: not found (no exception set) |
1325 * -2: not found (no exception set) |
1320 * rest: valid rev |
1326 * rest: valid rev |
1321 */ |
1327 */ |
1322 static int index_find_node(indexObject *self, |
1328 static int index_find_node(indexObject *self, const char *node, |
1323 const char *node, Py_ssize_t nodelen) |
1329 Py_ssize_t nodelen) |
1324 { |
1330 { |
1325 int rev; |
1331 int rev; |
1326 |
1332 |
1327 if (index_init_nt(self) == -1) |
1333 if (index_init_nt(self) == -1) |
1328 return -3; |
1334 return -3; |
1392 } |
1398 } |
1393 |
1399 |
1394 /* |
1400 /* |
1395 * Fully populate the radix tree. |
1401 * Fully populate the radix tree. |
1396 */ |
1402 */ |
1397 static int index_populate_nt(indexObject *self) { |
1403 static int index_populate_nt(indexObject *self) |
1404 { |
|
1398 int rev; |
1405 int rev; |
1399 if (self->ntrev > 0) { |
1406 if (self->ntrev > 0) { |
1400 for (rev = self->ntrev - 1; rev >= 0; rev--) { |
1407 for (rev = self->ntrev - 1; rev >= 0; rev--) { |
1401 const char *n = index_node_existing(self, rev); |
1408 const char *n = index_node_existing(self, rev); |
1402 if (n == NULL) |
1409 if (n == NULL) |
1532 * Given a disjoint set of revs, return all candidates for the |
1539 * Given a disjoint set of revs, return all candidates for the |
1533 * greatest common ancestor. In revset notation, this is the set |
1540 * greatest common ancestor. In revset notation, this is the set |
1534 * "heads(::a and ::b and ...)" |
1541 * "heads(::a and ::b and ...)" |
1535 */ |
1542 */ |
1536 static PyObject *find_gca_candidates(indexObject *self, const int *revs, |
1543 static PyObject *find_gca_candidates(indexObject *self, const int *revs, |
1537 int revcount) |
1544 int revcount) |
1538 { |
1545 { |
1539 const bitmask allseen = (1ull << revcount) - 1; |
1546 const bitmask allseen = (1ull << revcount) - 1; |
1540 const bitmask poison = 1ull << revcount; |
1547 const bitmask poison = 1ull << revcount; |
1541 PyObject *gca = PyList_New(0); |
1548 PyObject *gca = PyList_New(0); |
1542 int i, v, interesting; |
1549 int i, v, interesting; |
1597 sp = seen[p]; |
1604 sp = seen[p]; |
1598 if (sv < poison) { |
1605 if (sv < poison) { |
1599 if (sp == 0) { |
1606 if (sp == 0) { |
1600 seen[p] = sv; |
1607 seen[p] = sv; |
1601 interesting++; |
1608 interesting++; |
1602 } |
1609 } else if (sp != sv) |
1603 else if (sp != sv) |
|
1604 seen[p] |= sv; |
1610 seen[p] |= sv; |
1605 } else { |
1611 } else { |
1606 if (sp && sp < poison) |
1612 if (sp && sp < poison) |
1607 interesting--; |
1613 interesting--; |
1608 seen[p] = sv; |
1614 seen[p] = sv; |
1634 int maxrev = -1; |
1640 int maxrev = -1; |
1635 long final; |
1641 long final; |
1636 |
1642 |
1637 if (revcount > capacity) { |
1643 if (revcount > capacity) { |
1638 PyErr_Format(PyExc_OverflowError, |
1644 PyErr_Format(PyExc_OverflowError, |
1639 "bitset size (%ld) > capacity (%ld)", |
1645 "bitset size (%ld) > capacity (%ld)", |
1640 (long)revcount, (long)capacity); |
1646 (long)revcount, (long)capacity); |
1641 return NULL; |
1647 return NULL; |
1642 } |
1648 } |
1643 |
1649 |
1644 for (i = 0; i < revcount; i++) { |
1650 for (i = 0; i < revcount; i++) { |
1645 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i)); |
1651 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i)); |
1709 interesting[sp] -= 1; |
1715 interesting[sp] -= 1; |
1710 if (interesting[sp] == 0) |
1716 if (interesting[sp] == 0) |
1711 ninteresting -= 1; |
1717 ninteresting -= 1; |
1712 } |
1718 } |
1713 } |
1719 } |
1714 } |
1720 } else if (dv == dp - 1) { |
1715 else if (dv == dp - 1) { |
|
1716 long nsp = sp | sv; |
1721 long nsp = sp | sv; |
1717 if (nsp == sp) |
1722 if (nsp == sp) |
1718 continue; |
1723 continue; |
1719 seen[p] = nsp; |
1724 seen[p] = nsp; |
1720 interesting[sp] -= 1; |
1725 interesting[sp] -= 1; |
1798 bitmask x; |
1803 bitmask x; |
1799 long val; |
1804 long val; |
1800 |
1805 |
1801 if (!PyInt_Check(obj)) { |
1806 if (!PyInt_Check(obj)) { |
1802 PyErr_SetString(PyExc_TypeError, |
1807 PyErr_SetString(PyExc_TypeError, |
1803 "arguments must all be ints"); |
1808 "arguments must all be ints"); |
1804 Py_DECREF(obj); |
1809 Py_DECREF(obj); |
1805 goto bail; |
1810 goto bail; |
1806 } |
1811 } |
1807 val = PyInt_AsLong(obj); |
1812 val = PyInt_AsLong(obj); |
1808 Py_DECREF(obj); |
1813 Py_DECREF(obj); |
1809 if (val == -1) { |
1814 if (val == -1) { |
1810 ret = PyList_New(0); |
1815 ret = PyList_New(0); |
1811 goto done; |
1816 goto done; |
1812 } |
1817 } |
1813 if (val < 0 || val >= len) { |
1818 if (val < 0 || val >= len) { |
1814 PyErr_SetString(PyExc_IndexError, |
1819 PyErr_SetString(PyExc_IndexError, "index out of range"); |
1815 "index out of range"); |
|
1816 goto bail; |
1820 goto bail; |
1817 } |
1821 } |
1818 /* this cheesy bloom filter lets us avoid some more |
1822 /* this cheesy bloom filter lets us avoid some more |
1819 * expensive duplicate checks in the common set-is-disjoint |
1823 * expensive duplicate checks in the common set-is-disjoint |
1820 * case */ |
1824 * case */ |
1823 int k; |
1827 int k; |
1824 for (k = 0; k < revcount; k++) { |
1828 for (k = 0; k < revcount; k++) { |
1825 if (val == revs[k]) |
1829 if (val == revs[k]) |
1826 goto duplicate; |
1830 goto duplicate; |
1827 } |
1831 } |
1828 } |
1832 } else |
1829 else repeat |= x; |
1833 repeat |= x; |
1830 if (revcount >= capacity) { |
1834 if (revcount >= capacity) { |
1831 PyErr_Format(PyExc_OverflowError, |
1835 PyErr_Format(PyExc_OverflowError, |
1832 "bitset size (%d) > capacity (%d)", |
1836 "bitset size (%d) > capacity (%d)", |
1833 revcount, capacity); |
1837 revcount, capacity); |
1834 goto bail; |
1838 goto bail; |
1835 } |
1839 } |
1836 revs[revcount++] = (int)val; |
1840 revs[revcount++] = (int)val; |
1837 duplicate:; |
1841 duplicate:; |
1838 } |
1842 } |
1915 Py_ssize_t length = index_length(self) + 1; |
1919 Py_ssize_t length = index_length(self) + 1; |
1916 int ret = 0; |
1920 int ret = 0; |
1917 |
1921 |
1918 /* Argument changed from PySliceObject* to PyObject* in Python 3. */ |
1922 /* Argument changed from PySliceObject* to PyObject* in Python 3. */ |
1919 #ifdef IS_PY3K |
1923 #ifdef IS_PY3K |
1920 if (PySlice_GetIndicesEx(item, length, |
1924 if (PySlice_GetIndicesEx(item, length, &start, &stop, &step, |
1921 &start, &stop, &step, &slicelength) < 0) |
1925 &slicelength) < 0) |
1922 #else |
1926 #else |
1923 if (PySlice_GetIndicesEx((PySliceObject*)item, length, |
1927 if (PySlice_GetIndicesEx((PySliceObject *)item, length, &start, &stop, |
1924 &start, &stop, &step, &slicelength) < 0) |
1928 &step, &slicelength) < 0) |
1925 #endif |
1929 #endif |
1926 return -1; |
1930 return -1; |
1927 |
1931 |
1928 if (slicelength <= 0) |
1932 if (slicelength <= 0) |
1929 return 0; |
1933 return 0; |
1931 if ((step < 0 && start < stop) || (step > 0 && start > stop)) |
1935 if ((step < 0 && start < stop) || (step > 0 && start > stop)) |
1932 stop = start; |
1936 stop = start; |
1933 |
1937 |
1934 if (step < 0) { |
1938 if (step < 0) { |
1935 stop = start + 1; |
1939 stop = start + 1; |
1936 start = stop + step*(slicelength - 1) - 1; |
1940 start = stop + step * (slicelength - 1) - 1; |
1937 step = -step; |
1941 step = -step; |
1938 } |
1942 } |
1939 |
1943 |
1940 if (step != 1) { |
1944 if (step != 1) { |
1941 PyErr_SetString(PyExc_ValueError, |
1945 PyErr_SetString(PyExc_ValueError, |
1942 "revlog index delete requires step size of 1"); |
1946 "revlog index delete requires step size of 1"); |
1943 return -1; |
1947 return -1; |
1944 } |
1948 } |
1945 |
1949 |
1946 if (stop != length - 1) { |
1950 if (stop != length - 1) { |
1947 PyErr_SetString(PyExc_IndexError, |
1951 PyErr_SetString(PyExc_IndexError, |
1948 "revlog index deletion indices are invalid"); |
1952 "revlog index deletion indices are invalid"); |
1949 return -1; |
1953 return -1; |
1950 } |
1954 } |
1951 |
1955 |
1952 if (start < self->length) { |
1956 if (start < self->length) { |
1953 if (self->ntinitialized) { |
1957 if (self->ntinitialized) { |
1982 if (self->ntrev > start) |
1986 if (self->ntrev > start) |
1983 self->ntrev = (int)start; |
1987 self->ntrev = (int)start; |
1984 } |
1988 } |
1985 if (self->added) |
1989 if (self->added) |
1986 ret = PyList_SetSlice(self->added, start - self->length, |
1990 ret = PyList_SetSlice(self->added, start - self->length, |
1987 PyList_GET_SIZE(self->added), NULL); |
1991 PyList_GET_SIZE(self->added), NULL); |
1988 done: |
1992 done: |
1989 Py_CLEAR(self->headrevs); |
1993 Py_CLEAR(self->headrevs); |
1990 return ret; |
1994 return ret; |
1991 } |
1995 } |
1992 |
1996 |
1996 * slice deletion |
2000 * slice deletion |
1997 * string assignment (extend node->rev mapping) |
2001 * string assignment (extend node->rev mapping) |
1998 * string deletion (shrink node->rev mapping) |
2002 * string deletion (shrink node->rev mapping) |
1999 */ |
2003 */ |
2000 static int index_assign_subscript(indexObject *self, PyObject *item, |
2004 static int index_assign_subscript(indexObject *self, PyObject *item, |
2001 PyObject *value) |
2005 PyObject *value) |
2002 { |
2006 { |
2003 char *node; |
2007 char *node; |
2004 long rev; |
2008 long rev; |
2005 |
2009 |
2006 if (PySlice_Check(item) && value == NULL) |
2010 if (PySlice_Check(item) && value == NULL) |
2008 |
2012 |
2009 if (node_check(item, &node) == -1) |
2013 if (node_check(item, &node) == -1) |
2010 return -1; |
2014 return -1; |
2011 |
2015 |
2012 if (value == NULL) |
2016 if (value == NULL) |
2013 return self->ntinitialized ? nt_delete_node(&self->nt, node) : 0; |
2017 return self->ntinitialized ? nt_delete_node(&self->nt, node) |
2018 : 0; |
|
2014 rev = PyInt_AsLong(value); |
2019 rev = PyInt_AsLong(value); |
2015 if (rev > INT_MAX || rev < 0) { |
2020 if (rev > INT_MAX || rev < 0) { |
2016 if (!PyErr_Occurred()) |
2021 if (!PyErr_Occurred()) |
2017 PyErr_SetString(PyExc_ValueError, "rev out of range"); |
2022 PyErr_SetString(PyExc_ValueError, "rev out of range"); |
2018 return -1; |
2023 return -1; |
2058 static int index_init(indexObject *self, PyObject *args) |
2063 static int index_init(indexObject *self, PyObject *args) |
2059 { |
2064 { |
2060 PyObject *data_obj, *inlined_obj; |
2065 PyObject *data_obj, *inlined_obj; |
2061 Py_ssize_t size; |
2066 Py_ssize_t size; |
2062 |
2067 |
2063 /* Initialize before argument-checking to avoid index_dealloc() crash. */ |
2068 /* Initialize before argument-checking to avoid index_dealloc() crash. |
2069 */ |
|
2064 self->raw_length = 0; |
2070 self->raw_length = 0; |
2065 self->added = NULL; |
2071 self->added = NULL; |
2066 self->cache = NULL; |
2072 self->cache = NULL; |
2067 self->data = NULL; |
2073 self->data = NULL; |
2068 memset(&self->buf, 0, sizeof(self->buf)); |
2074 memset(&self->buf, 0, sizeof(self->buf)); |
2074 |
2080 |
2075 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj)) |
2081 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj)) |
2076 return -1; |
2082 return -1; |
2077 if (!PyObject_CheckBuffer(data_obj)) { |
2083 if (!PyObject_CheckBuffer(data_obj)) { |
2078 PyErr_SetString(PyExc_TypeError, |
2084 PyErr_SetString(PyExc_TypeError, |
2079 "data does not support buffer interface"); |
2085 "data does not support buffer interface"); |
2080 return -1; |
2086 return -1; |
2081 } |
2087 } |
2082 |
2088 |
2083 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1) |
2089 if (PyObject_GetBuffer(data_obj, &self->buf, PyBUF_SIMPLE) == -1) |
2084 return -1; |
2090 return -1; |
2158 Py_XDECREF(self->added); |
2164 Py_XDECREF(self->added); |
2159 PyObject_Del(self); |
2165 PyObject_Del(self); |
2160 } |
2166 } |
2161 |
2167 |
2162 static PySequenceMethods index_sequence_methods = { |
2168 static PySequenceMethods index_sequence_methods = { |
2163 (lenfunc)index_length, /* sq_length */ |
2169 (lenfunc)index_length, /* sq_length */ |
2164 0, /* sq_concat */ |
2170 0, /* sq_concat */ |
2165 0, /* sq_repeat */ |
2171 0, /* sq_repeat */ |
2166 (ssizeargfunc)index_get, /* sq_item */ |
2172 (ssizeargfunc)index_get, /* sq_item */ |
2167 0, /* sq_slice */ |
2173 0, /* sq_slice */ |
2168 0, /* sq_ass_item */ |
2174 0, /* sq_ass_item */ |
2169 0, /* sq_ass_slice */ |
2175 0, /* sq_ass_slice */ |
2170 (objobjproc)index_contains, /* sq_contains */ |
2176 (objobjproc)index_contains, /* sq_contains */ |
2171 }; |
2177 }; |
2172 |
2178 |
2173 static PyMappingMethods index_mapping_methods = { |
2179 static PyMappingMethods index_mapping_methods = { |
2174 (lenfunc)index_length, /* mp_length */ |
2180 (lenfunc)index_length, /* mp_length */ |
2175 (binaryfunc)index_getitem, /* mp_subscript */ |
2181 (binaryfunc)index_getitem, /* mp_subscript */ |
2176 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */ |
2182 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */ |
2177 }; |
2183 }; |
2178 |
2184 |
2179 static PyMethodDef index_methods[] = { |
2185 static PyMethodDef index_methods[] = { |
2180 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS, |
2186 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS, |
2181 "return the gca set of the given revs"}, |
2187 "return the gca set of the given revs"}, |
2182 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads, |
2188 {"commonancestorsheads", (PyCFunction)index_commonancestorsheads, |
2183 METH_VARARGS, |
2189 METH_VARARGS, |
2184 "return the heads of the common ancestors of the given revs"}, |
2190 "return the heads of the common ancestors of the given revs"}, |
2185 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
2191 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
2186 "clear the index caches"}, |
2192 "clear the index caches"}, |
2187 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
2193 {"get", (PyCFunction)index_m_get, METH_VARARGS, "get an index entry"}, |
2188 "get an index entry"}, |
2194 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, METH_VARARGS, |
2189 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, |
2195 "compute phases"}, |
2190 METH_VARARGS, "compute phases"}, |
2196 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS, |
2191 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS, |
2197 "reachableroots"}, |
2192 "reachableroots"}, |
2198 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, |
2193 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, |
2199 "get head revisions"}, /* Can do filtering since 3.2 */ |
2194 "get head revisions"}, /* Can do filtering since 3.2 */ |
2200 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS, |
2195 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS, |
2201 "get filtered head revisions"}, /* Can always do filtering */ |
2196 "get filtered head revisions"}, /* Can always do filtering */ |
2202 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS, |
2197 {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS, |
2203 "determine revisions with deltas to reconstruct fulltext"}, |
2198 "determine revisions with deltas to reconstruct fulltext"}, |
2204 {"append", (PyCFunction)index_append, METH_O, "append an index entry"}, |
2199 {"append", (PyCFunction)index_append, METH_O, |
2205 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS, |
2200 "append an index entry"}, |
2206 "match a potentially ambiguous node ID"}, |
2201 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS, |
2207 {"shortest", (PyCFunction)index_shortest, METH_VARARGS, |
2202 "match a potentially ambiguous node ID"}, |
2208 "find length of shortest hex nodeid of a binary ID"}, |
2203 {"shortest", (PyCFunction)index_shortest, METH_VARARGS, |
2209 {"stats", (PyCFunction)index_stats, METH_NOARGS, "stats for the index"}, |
2204 "find length of shortest hex nodeid of a binary ID"}, |
2210 {NULL} /* Sentinel */ |
2205 {"stats", (PyCFunction)index_stats, METH_NOARGS, |
|
2206 "stats for the index"}, |
|
2207 {NULL} /* Sentinel */ |
|
2208 }; |
2211 }; |
2209 |
2212 |
2210 static PyGetSetDef index_getset[] = { |
2213 static PyGetSetDef index_getset[] = { |
2211 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL}, |
2214 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL}, |
2212 {NULL} /* Sentinel */ |
2215 {NULL} /* Sentinel */ |
2213 }; |
2216 }; |
2214 |
2217 |
2215 static PyTypeObject indexType = { |
2218 static PyTypeObject indexType = { |
2216 PyVarObject_HEAD_INIT(NULL, 0) /* header */ |
2219 PyVarObject_HEAD_INIT(NULL, 0) /* header */ |
2217 "parsers.index", /* tp_name */ |
2220 "parsers.index", /* tp_name */ |
2218 sizeof(indexObject), /* tp_basicsize */ |
2221 sizeof(indexObject), /* tp_basicsize */ |
2219 0, /* tp_itemsize */ |
2222 0, /* tp_itemsize */ |
2220 (destructor)index_dealloc, /* tp_dealloc */ |
2223 (destructor)index_dealloc, /* tp_dealloc */ |
2221 0, /* tp_print */ |
2224 0, /* tp_print */ |
2222 0, /* tp_getattr */ |
2225 0, /* tp_getattr */ |
2223 0, /* tp_setattr */ |
2226 0, /* tp_setattr */ |
2224 0, /* tp_compare */ |
2227 0, /* tp_compare */ |
2225 0, /* tp_repr */ |
2228 0, /* tp_repr */ |
2226 0, /* tp_as_number */ |
2229 0, /* tp_as_number */ |
2227 &index_sequence_methods, /* tp_as_sequence */ |
2230 &index_sequence_methods, /* tp_as_sequence */ |
2228 &index_mapping_methods, /* tp_as_mapping */ |
2231 &index_mapping_methods, /* tp_as_mapping */ |
2229 0, /* tp_hash */ |
2232 0, /* tp_hash */ |
2230 0, /* tp_call */ |
2233 0, /* tp_call */ |
2231 0, /* tp_str */ |
2234 0, /* tp_str */ |
2232 0, /* tp_getattro */ |
2235 0, /* tp_getattro */ |
2233 0, /* tp_setattro */ |
2236 0, /* tp_setattro */ |
2234 0, /* tp_as_buffer */ |
2237 0, /* tp_as_buffer */ |
2235 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
2238 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
2236 "revlog index", /* tp_doc */ |
2239 "revlog index", /* tp_doc */ |
2237 0, /* tp_traverse */ |
2240 0, /* tp_traverse */ |
2238 0, /* tp_clear */ |
2241 0, /* tp_clear */ |
2239 0, /* tp_richcompare */ |
2242 0, /* tp_richcompare */ |
2240 0, /* tp_weaklistoffset */ |
2243 0, /* tp_weaklistoffset */ |
2241 0, /* tp_iter */ |
2244 0, /* tp_iter */ |
2242 0, /* tp_iternext */ |
2245 0, /* tp_iternext */ |
2243 index_methods, /* tp_methods */ |
2246 index_methods, /* tp_methods */ |
2244 0, /* tp_members */ |
2247 0, /* tp_members */ |
2245 index_getset, /* tp_getset */ |
2248 index_getset, /* tp_getset */ |
2246 0, /* tp_base */ |
2249 0, /* tp_base */ |
2247 0, /* tp_dict */ |
2250 0, /* tp_dict */ |
2248 0, /* tp_descr_get */ |
2251 0, /* tp_descr_get */ |
2249 0, /* tp_descr_set */ |
2252 0, /* tp_descr_set */ |
2250 0, /* tp_dictoffset */ |
2253 0, /* tp_dictoffset */ |
2251 (initproc)index_init, /* tp_init */ |
2254 (initproc)index_init, /* tp_init */ |
2252 0, /* tp_alloc */ |
2255 0, /* tp_alloc */ |
2253 }; |
2256 }; |
2254 |
2257 |
2255 /* |
2258 /* |
2256 * returns a tuple of the form (index, index, cache) with elements as |
2259 * returns a tuple of the form (index, index, cache) with elements as |
2257 * follows: |
2260 * follows: |
2305 */ |
2308 */ |
2306 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject; |
2309 typedef struct rustlazyancestorsObjectStruct rustlazyancestorsObject; |
2307 |
2310 |
2308 struct rustlazyancestorsObjectStruct { |
2311 struct rustlazyancestorsObjectStruct { |
2309 PyObject_HEAD |
2312 PyObject_HEAD |
2310 /* Type-specific fields go here. */ |
2313 /* Type-specific fields go here. */ |
2311 indexObject *index; /* Ref kept to avoid GC'ing the index */ |
2314 indexObject *index; /* Ref kept to avoid GC'ing the index */ |
2312 void *iter; /* Rust iterator */ |
2315 void *iter; /* Rust iterator */ |
2313 }; |
2316 }; |
2314 |
2317 |
2315 /* FFI exposed from Rust code */ |
2318 /* FFI exposed from Rust code */ |
2316 rustlazyancestorsObject *rustlazyancestors_init( |
2319 rustlazyancestorsObject * |
2317 indexObject *index, |
2320 rustlazyancestors_init(indexObject *index, |
2318 /* to pass index_get_parents() */ |
2321 /* to pass index_get_parents() */ |
2319 int (*)(indexObject *, Py_ssize_t, int*, int), |
2322 int (*)(indexObject *, Py_ssize_t, int *, int), |
2320 /* intrevs vector */ |
2323 /* intrevs vector */ |
2321 Py_ssize_t initrevslen, long *initrevs, |
2324 Py_ssize_t initrevslen, long *initrevs, long stoprev, |
2322 long stoprev, |
2325 int inclusive); |
2323 int inclusive); |
|
2324 void rustlazyancestors_drop(rustlazyancestorsObject *self); |
2326 void rustlazyancestors_drop(rustlazyancestorsObject *self); |
2325 int rustlazyancestors_next(rustlazyancestorsObject *self); |
2327 int rustlazyancestors_next(rustlazyancestorsObject *self); |
2326 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev); |
2328 int rustlazyancestors_contains(rustlazyancestorsObject *self, long rev); |
2327 |
2329 |
2328 /* CPython instance methods */ |
2330 /* CPython instance methods */ |
2329 static int rustla_init(rustlazyancestorsObject *self, |
2331 static int rustla_init(rustlazyancestorsObject *self, PyObject *args) |
2330 PyObject *args) { |
2332 { |
2331 PyObject *initrevsarg = NULL; |
2333 PyObject *initrevsarg = NULL; |
2332 PyObject *inclusivearg = NULL; |
2334 PyObject *inclusivearg = NULL; |
2333 long stoprev = 0; |
2335 long stoprev = 0; |
2334 long *initrevs = NULL; |
2336 long *initrevs = NULL; |
2335 int inclusive = 0; |
2337 int inclusive = 0; |
2336 Py_ssize_t i; |
2338 Py_ssize_t i; |
2337 |
2339 |
2338 indexObject *index; |
2340 indexObject *index; |
2339 if (!PyArg_ParseTuple(args, "O!O!lO!", |
2341 if (!PyArg_ParseTuple(args, "O!O!lO!", &indexType, &index, &PyList_Type, |
2340 &indexType, &index, |
2342 &initrevsarg, &stoprev, &PyBool_Type, |
2341 &PyList_Type, &initrevsarg, |
2343 &inclusivearg)) |
2342 &stoprev, |
2344 return -1; |
2343 &PyBool_Type, &inclusivearg)) |
|
2344 return -1; |
|
2345 |
2345 |
2346 Py_INCREF(index); |
2346 Py_INCREF(index); |
2347 self->index = index; |
2347 self->index = index; |
2348 |
2348 |
2349 if (inclusivearg == Py_True) |
2349 if (inclusivearg == Py_True) |
2350 inclusive = 1; |
2350 inclusive = 1; |
2351 |
2351 |
2352 Py_ssize_t linit = PyList_GET_SIZE(initrevsarg); |
2352 Py_ssize_t linit = PyList_GET_SIZE(initrevsarg); |
2353 |
2353 |
2354 initrevs = (long*)calloc(linit, sizeof(long)); |
2354 initrevs = (long *)calloc(linit, sizeof(long)); |
2355 |
2355 |
2356 if (initrevs == NULL) { |
2356 if (initrevs == NULL) { |
2357 PyErr_NoMemory(); |
2357 PyErr_NoMemory(); |
2358 goto bail; |
2358 goto bail; |
2359 } |
2359 } |
2360 |
2360 |
2361 for (i=0; i<linit; i++) { |
2361 for (i = 0; i < linit; i++) { |
2362 initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i)); |
2362 initrevs[i] = PyInt_AsLong(PyList_GET_ITEM(initrevsarg, i)); |
2363 } |
2363 } |
2364 if (PyErr_Occurred()) |
2364 if (PyErr_Occurred()) |
2365 goto bail; |
2365 goto bail; |
2366 |
2366 |
2367 self->iter = rustlazyancestors_init(index, |
2367 self->iter = rustlazyancestors_init(index, index_get_parents, linit, |
2368 index_get_parents, |
2368 initrevs, stoprev, inclusive); |
2369 linit, initrevs, |
|
2370 stoprev, inclusive); |
|
2371 if (self->iter == NULL) { |
2369 if (self->iter == NULL) { |
2372 /* if this is because of GraphError::ParentOutOfRange |
2370 /* if this is because of GraphError::ParentOutOfRange |
2373 * index_get_parents() has already set the proper ValueError */ |
2371 * index_get_parents() has already set the proper ValueError */ |
2374 goto bail; |
2372 goto bail; |
2375 } |
2373 } |
2389 rustlazyancestors_drop(self->iter); |
2387 rustlazyancestors_drop(self->iter); |
2390 } |
2388 } |
2391 PyObject_Del(self); |
2389 PyObject_Del(self); |
2392 } |
2390 } |
2393 |
2391 |
2394 static PyObject *rustla_next(rustlazyancestorsObject *self) { |
2392 static PyObject *rustla_next(rustlazyancestorsObject *self) |
2393 { |
|
2395 int res = rustlazyancestors_next(self->iter); |
2394 int res = rustlazyancestors_next(self->iter); |
2396 if (res == -1) { |
2395 if (res == -1) { |
2397 /* Setting an explicit exception seems unnecessary |
2396 /* Setting an explicit exception seems unnecessary |
2398 * as examples from Python source code (Objects/rangeobjets.c and |
2397 * as examples from Python source code (Objects/rangeobjets.c |
2399 * Modules/_io/stringio.c) seem to demonstrate. |
2398 * and Modules/_io/stringio.c) seem to demonstrate. |
2400 */ |
2399 */ |
2401 return NULL; |
2400 return NULL; |
2402 } |
2401 } |
2403 return PyInt_FromLong(res); |
2402 return PyInt_FromLong(res); |
2404 } |
2403 } |
2405 |
2404 |
2406 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev) { |
2405 static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev) |
2406 { |
|
2407 if (!(PyInt_Check(rev))) { |
2407 if (!(PyInt_Check(rev))) { |
2408 return 0; |
2408 return 0; |
2409 } |
2409 } |
2410 return rustlazyancestors_contains(self->iter, PyInt_AS_LONG(rev)); |
2410 return rustlazyancestors_contains(self->iter, PyInt_AS_LONG(rev)); |
2411 } |
2411 } |
2412 |
2412 |
2413 static PySequenceMethods rustla_sequence_methods = { |
2413 static PySequenceMethods rustla_sequence_methods = { |
2414 0, /* sq_length */ |
2414 0, /* sq_length */ |
2415 0, /* sq_concat */ |
2415 0, /* sq_concat */ |
2416 0, /* sq_repeat */ |
2416 0, /* sq_repeat */ |
2417 0, /* sq_item */ |
2417 0, /* sq_item */ |
2418 0, /* sq_slice */ |
2418 0, /* sq_slice */ |
2419 0, /* sq_ass_item */ |
2419 0, /* sq_ass_item */ |
2420 0, /* sq_ass_slice */ |
2420 0, /* sq_ass_slice */ |
2421 (objobjproc)rustla_contains, /* sq_contains */ |
2421 (objobjproc)rustla_contains, /* sq_contains */ |
2422 }; |
2422 }; |
2423 |
2423 |
2424 static PyTypeObject rustlazyancestorsType = { |
2424 static PyTypeObject rustlazyancestorsType = { |
2425 PyVarObject_HEAD_INIT(NULL, 0) /* header */ |
2425 PyVarObject_HEAD_INIT(NULL, 0) /* header */ |
2426 "parsers.rustlazyancestors", /* tp_name */ |
2426 "parsers.rustlazyancestors", /* tp_name */ |
2427 sizeof(rustlazyancestorsObject), /* tp_basicsize */ |
2427 sizeof(rustlazyancestorsObject), /* tp_basicsize */ |
2428 0, /* tp_itemsize */ |
2428 0, /* tp_itemsize */ |
2429 (destructor)rustla_dealloc, /* tp_dealloc */ |
2429 (destructor)rustla_dealloc, /* tp_dealloc */ |
2430 0, /* tp_print */ |
2430 0, /* tp_print */ |
2431 0, /* tp_getattr */ |
2431 0, /* tp_getattr */ |
2432 0, /* tp_setattr */ |
2432 0, /* tp_setattr */ |
2433 0, /* tp_compare */ |
2433 0, /* tp_compare */ |
2434 0, /* tp_repr */ |
2434 0, /* tp_repr */ |
2435 0, /* tp_as_number */ |
2435 0, /* tp_as_number */ |
2436 &rustla_sequence_methods, /* tp_as_sequence */ |
2436 &rustla_sequence_methods, /* tp_as_sequence */ |
2437 0, /* tp_as_mapping */ |
2437 0, /* tp_as_mapping */ |
2438 0, /* tp_hash */ |
2438 0, /* tp_hash */ |
2439 0, /* tp_call */ |
2439 0, /* tp_call */ |
2440 0, /* tp_str */ |
2440 0, /* tp_str */ |
2441 0, /* tp_getattro */ |
2441 0, /* tp_getattro */ |
2442 0, /* tp_setattro */ |
2442 0, /* tp_setattro */ |
2443 0, /* tp_as_buffer */ |
2443 0, /* tp_as_buffer */ |
2444 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
2444 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
2445 "Iterator over ancestors, implemented in Rust", /* tp_doc */ |
2445 "Iterator over ancestors, implemented in Rust", /* tp_doc */ |
2446 0, /* tp_traverse */ |
2446 0, /* tp_traverse */ |
2447 0, /* tp_clear */ |
2447 0, /* tp_clear */ |
2448 0, /* tp_richcompare */ |
2448 0, /* tp_richcompare */ |
2449 0, /* tp_weaklistoffset */ |
2449 0, /* tp_weaklistoffset */ |
2450 0, /* tp_iter */ |
2450 0, /* tp_iter */ |
2451 (iternextfunc)rustla_next, /* tp_iternext */ |
2451 (iternextfunc)rustla_next, /* tp_iternext */ |
2452 0, /* tp_methods */ |
2452 0, /* tp_methods */ |
2453 0, /* tp_members */ |
2453 0, /* tp_members */ |
2454 0, /* tp_getset */ |
2454 0, /* tp_getset */ |
2455 0, /* tp_base */ |
2455 0, /* tp_base */ |
2456 0, /* tp_dict */ |
2456 0, /* tp_dict */ |
2457 0, /* tp_descr_get */ |
2457 0, /* tp_descr_get */ |
2458 0, /* tp_descr_set */ |
2458 0, /* tp_descr_set */ |
2459 0, /* tp_dictoffset */ |
2459 0, /* tp_dictoffset */ |
2460 (initproc)rustla_init, /* tp_init */ |
2460 (initproc)rustla_init, /* tp_init */ |
2461 0, /* tp_alloc */ |
2461 0, /* tp_alloc */ |
2462 }; |
2462 }; |
2463 #endif /* WITH_RUST */ |
2463 #endif /* WITH_RUST */ |
2464 |
2464 |
2465 void revlog_module_init(PyObject *mod) |
2465 void revlog_module_init(PyObject *mod) |
2466 { |
2466 { |
2475 return; |
2475 return; |
2476 Py_INCREF(&nodetreeType); |
2476 Py_INCREF(&nodetreeType); |
2477 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType); |
2477 PyModule_AddObject(mod, "nodetree", (PyObject *)&nodetreeType); |
2478 |
2478 |
2479 if (!nullentry) { |
2479 if (!nullentry) { |
2480 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0, |
2480 nullentry = Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, |
2481 -1, -1, -1, -1, nullid, 20); |
2481 0, -1, -1, -1, -1, nullid, 20); |
2482 } |
2482 } |
2483 if (nullentry) |
2483 if (nullentry) |
2484 PyObject_GC_UnTrack(nullentry); |
2484 PyObject_GC_UnTrack(nullentry); |
2485 |
2485 |
2486 #ifdef WITH_RUST |
2486 #ifdef WITH_RUST |
2487 rustlazyancestorsType.tp_new = PyType_GenericNew; |
2487 rustlazyancestorsType.tp_new = PyType_GenericNew; |
2488 if (PyType_Ready(&rustlazyancestorsType) < 0) |
2488 if (PyType_Ready(&rustlazyancestorsType) < 0) |
2489 return; |
2489 return; |
2490 Py_INCREF(&rustlazyancestorsType); |
2490 Py_INCREF(&rustlazyancestorsType); |
2491 PyModule_AddObject(mod, "rustlazyancestors", |
2491 PyModule_AddObject(mod, "rustlazyancestors", |
2492 (PyObject *)&rustlazyancestorsType); |
2492 (PyObject *)&rustlazyancestorsType); |
2493 #endif |
2493 #endif |
2494 |
2494 } |
2495 } |