909 } else { |
909 } else { |
910 return 0; |
910 return 0; |
911 } |
911 } |
912 } |
912 } |
913 |
913 |
|
914 static Py_ssize_t add_roots_get_min(indexObject *self, PyObject *list, |
|
915 int marker, char *phases) |
|
916 { |
|
917 PyObject *iter = NULL; |
|
918 PyObject *iter_item = NULL; |
|
919 Py_ssize_t min_idx = index_length(self) + 1; |
|
920 long iter_item_long; |
|
921 |
|
922 if (PyList_GET_SIZE(list) != 0) { |
|
923 iter = PyObject_GetIter(list); |
|
924 if (iter == NULL) |
|
925 return -2; |
|
926 while ((iter_item = PyIter_Next(iter))) |
|
927 { |
|
928 iter_item_long = PyInt_AS_LONG(iter_item); |
|
929 Py_DECREF(iter_item); |
|
930 if (iter_item_long < min_idx) |
|
931 min_idx = iter_item_long; |
|
932 phases[iter_item_long] = marker; |
|
933 } |
|
934 Py_DECREF(iter); |
|
935 } |
|
936 |
|
937 return min_idx; |
|
938 } |
|
939 |
|
940 static inline void set_phase_from_parents(char *phases, int parent_1, |
|
941 int parent_2, int i) |
|
942 { |
|
943 if (parent_1 >= 0 && phases[parent_1] > phases[i]) |
|
944 phases[i] = phases[parent_1]; |
|
945 if (parent_2 >= 0 && phases[parent_2] > phases[i]) |
|
946 phases[i] = phases[parent_2]; |
|
947 } |
|
948 |
|
949 static PyObject *compute_phases(indexObject *self, PyObject *args) |
|
950 { |
|
951 PyObject *roots = Py_None; |
|
952 PyObject *phaseslist = NULL; |
|
953 PyObject *phaseroots = NULL; |
|
954 PyObject *rev = NULL; |
|
955 PyObject *p1 = NULL; |
|
956 PyObject *p2 = NULL; |
|
957 Py_ssize_t addlen = self->added ? PyList_GET_SIZE(self->added) : 0; |
|
958 Py_ssize_t len = index_length(self) - 1; |
|
959 Py_ssize_t numphase = 0; |
|
960 Py_ssize_t minrevallphases = 0; |
|
961 Py_ssize_t minrevphase = 0; |
|
962 Py_ssize_t i = 0; |
|
963 long parent_1, parent_2; |
|
964 char *phases = NULL; |
|
965 const char *data; |
|
966 |
|
967 if (!PyArg_ParseTuple(args, "O", &roots)) |
|
968 goto release_none; |
|
969 if (roots == NULL || !PyList_Check(roots)) |
|
970 goto release_none; |
|
971 |
|
972 phases = calloc(len, 1); /* phase per rev: {0: public, 1: draft, 2: secret} */ |
|
973 if (phases == NULL) |
|
974 goto release_none; |
|
975 /* Put the phase information of all the roots in phases */ |
|
976 numphase = PyList_GET_SIZE(roots)+1; |
|
977 minrevallphases = len + 1; |
|
978 for (i = 0; i < numphase-1; i++) { |
|
979 phaseroots = PyList_GET_ITEM(roots, i); |
|
980 if (!PyList_Check(phaseroots)) |
|
981 goto release_phases; |
|
982 minrevphase = add_roots_get_min(self, phaseroots, i+1, phases); |
|
983 if (minrevphase == -2) /* Error from add_roots_get_min */ |
|
984 goto release_phases; |
|
985 minrevallphases = MIN(minrevallphases, minrevphase); |
|
986 } |
|
987 /* Propagate the phase information from the roots to the revs */ |
|
988 if (minrevallphases != -1) { |
|
989 for (i = minrevallphases; i < self->raw_length; i++) { |
|
990 data = index_deref(self, i); |
|
991 set_phase_from_parents(phases, getbe32(data+24), getbe32(data+28), i); |
|
992 } |
|
993 for (i = 0; i < addlen; i++) { |
|
994 rev = PyList_GET_ITEM(self->added, i); |
|
995 p1 = PyTuple_GET_ITEM(rev, 5); |
|
996 p2 = PyTuple_GET_ITEM(rev, 6); |
|
997 if (!PyInt_Check(p1) || !PyInt_Check(p2)) { |
|
998 PyErr_SetString(PyExc_TypeError, "revlog parents are invalid"); |
|
999 goto release_phases; |
|
1000 } |
|
1001 parent_1 = PyInt_AS_LONG(p1); |
|
1002 parent_2 = PyInt_AS_LONG(p2); |
|
1003 set_phase_from_parents(phases, parent_1, parent_2, i+self->raw_length); |
|
1004 } |
|
1005 } |
|
1006 /* Transform phase list to a python list */ |
|
1007 phaseslist = PyList_New(len); |
|
1008 if (phaseslist == NULL) |
|
1009 goto release_phases; |
|
1010 for (i = 0; i < len; i++) |
|
1011 PyList_SET_ITEM(phaseslist, i, PyInt_FromLong(phases[i])); |
|
1012 |
|
1013 release_phases: |
|
1014 free(phases); |
|
1015 release_none: |
|
1016 return phaseslist; |
|
1017 } |
|
1018 |
914 static PyObject *index_headrevs(indexObject *self, PyObject *args) |
1019 static PyObject *index_headrevs(indexObject *self, PyObject *args) |
915 { |
1020 { |
916 Py_ssize_t i, len, addlen; |
1021 Py_ssize_t i, len, addlen; |
917 char *nothead = NULL; |
1022 char *nothead = NULL; |
918 PyObject *heads = NULL; |
1023 PyObject *heads = NULL; |
2041 "return the heads of the common ancestors of the given revs"}, |
2146 "return the heads of the common ancestors of the given revs"}, |
2042 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
2147 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
2043 "clear the index caches"}, |
2148 "clear the index caches"}, |
2044 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
2149 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
2045 "get an index entry"}, |
2150 "get an index entry"}, |
|
2151 {"computephases", (PyCFunction)compute_phases, METH_VARARGS, |
|
2152 "compute phases"}, |
2046 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, |
2153 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, |
2047 "get head revisions"}, /* Can do filtering since 3.2 */ |
2154 "get head revisions"}, /* Can do filtering since 3.2 */ |
2048 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS, |
2155 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS, |
2049 "get filtered head revisions"}, /* Can always do filtering */ |
2156 "get filtered head revisions"}, /* Can always do filtering */ |
2050 {"insert", (PyCFunction)index_insert, METH_VARARGS, |
2157 {"insert", (PyCFunction)index_insert, METH_VARARGS, |