1106 phases[i] = phases[parent_1]; |
1106 phases[i] = phases[parent_1]; |
1107 if (parent_2 >= 0 && phases[parent_2] > phases[i]) |
1107 if (parent_2 >= 0 && phases[parent_2] > phases[i]) |
1108 phases[i] = phases[parent_2]; |
1108 phases[i] = phases[parent_2]; |
1109 } |
1109 } |
1110 |
1110 |
1111 static PyObject *reachableroots(indexObject *self, PyObject *args) |
1111 static PyObject *reachableroots2(indexObject *self, PyObject *args) |
1112 { |
1112 { |
1113 |
1113 |
1114 /* Input */ |
1114 /* Input */ |
1115 long minroot; |
1115 long minroot; |
1116 PyObject *includepatharg = NULL; |
1116 PyObject *includepatharg = NULL; |
1117 int includepath = 0; |
1117 int includepath = 0; |
1118 /* heads is a list */ |
1118 /* heads and roots are lists */ |
1119 PyObject *heads = NULL; |
1119 PyObject *heads = NULL; |
1120 /* roots is a set */ |
|
1121 PyObject *roots = NULL; |
1120 PyObject *roots = NULL; |
1122 PyObject *reachable = NULL; |
1121 PyObject *reachable = NULL; |
1123 |
1122 |
1124 PyObject *val; |
1123 PyObject *val; |
1125 Py_ssize_t len = index_length(self) - 1; |
1124 Py_ssize_t len = index_length(self) - 1; |
1134 /* Internal data structure: |
1133 /* Internal data structure: |
1135 * tovisit: array of length len+1 (all revs + nullrev), filled upto lentovisit |
1134 * tovisit: array of length len+1 (all revs + nullrev), filled upto lentovisit |
1136 * revstates: array of length len+1 (all revs + nullrev) */ |
1135 * revstates: array of length len+1 (all revs + nullrev) */ |
1137 int *tovisit = NULL; |
1136 int *tovisit = NULL; |
1138 long lentovisit = 0; |
1137 long lentovisit = 0; |
1139 enum { RS_SEEN = 1 }; |
1138 enum { RS_SEEN = 1, RS_ROOT = 2 }; |
1140 char *revstates = NULL; |
1139 char *revstates = NULL; |
1141 |
1140 |
1142 /* Get arguments */ |
1141 /* Get arguments */ |
1143 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads, |
1142 if (!PyArg_ParseTuple(args, "lO!O!O!", &minroot, &PyList_Type, &heads, |
1144 &PySet_Type, &roots, &PyBool_Type, &includepatharg)) |
1143 &PyList_Type, &roots, |
|
1144 &PyBool_Type, &includepatharg)) |
1145 goto bail; |
1145 goto bail; |
1146 |
1146 |
1147 if (includepatharg == Py_True) |
1147 if (includepatharg == Py_True) |
1148 includepath = 1; |
1148 includepath = 1; |
1149 |
1149 |
1165 if (revstates == NULL) { |
1165 if (revstates == NULL) { |
1166 PyErr_NoMemory(); |
1166 PyErr_NoMemory(); |
1167 goto bail; |
1167 goto bail; |
1168 } |
1168 } |
1169 |
1169 |
|
1170 l = PyList_GET_SIZE(roots); |
|
1171 for (i = 0; i < l; i++) { |
|
1172 revnum = PyInt_AsLong(PyList_GET_ITEM(roots, i)); |
|
1173 if (revnum == -1 && PyErr_Occurred()) |
|
1174 goto bail; |
|
1175 /* If root is out of range, e.g. wdir(), it must be unreachable |
|
1176 * from heads. So we can just ignore it. */ |
|
1177 if (revnum + 1 < 0 || revnum + 1 >= len + 1) |
|
1178 continue; |
|
1179 revstates[revnum + 1] |= RS_ROOT; |
|
1180 } |
|
1181 |
1170 /* Populate tovisit with all the heads */ |
1182 /* Populate tovisit with all the heads */ |
1171 l = PyList_GET_SIZE(heads); |
1183 l = PyList_GET_SIZE(heads); |
1172 for (i = 0; i < l; i++) { |
1184 for (i = 0; i < l; i++) { |
1173 revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i)); |
1185 revnum = PyInt_AsLong(PyList_GET_ITEM(heads, i)); |
1174 if (revnum == -1 && PyErr_Occurred()) |
1186 if (revnum == -1 && PyErr_Occurred()) |
1186 /* Visit the tovisit list and find the reachable roots */ |
1198 /* Visit the tovisit list and find the reachable roots */ |
1187 k = 0; |
1199 k = 0; |
1188 while (k < lentovisit) { |
1200 while (k < lentovisit) { |
1189 /* Add the node to reachable if it is a root*/ |
1201 /* Add the node to reachable if it is a root*/ |
1190 revnum = tovisit[k++]; |
1202 revnum = tovisit[k++]; |
1191 val = PyInt_FromLong(revnum); |
1203 if (revstates[revnum + 1] & RS_ROOT) { |
1192 if (val == NULL) |
1204 val = PyInt_FromLong(revnum); |
1193 goto bail; |
1205 if (val == NULL) |
1194 if (PySet_Contains(roots, val) == 1) { |
1206 goto bail; |
1195 PySet_Add(reachable, val); |
1207 PySet_Add(reachable, val); |
1196 if (includepath == 0) { |
1208 Py_DECREF(val); |
1197 Py_DECREF(val); |
1209 if (includepath == 0) |
1198 continue; |
1210 continue; |
1199 } |
1211 } |
1200 } |
|
1201 Py_DECREF(val); |
|
1202 |
1212 |
1203 /* Add its parents to the list of nodes to visit */ |
1213 /* Add its parents to the list of nodes to visit */ |
1204 if (revnum == -1) |
1214 if (revnum == -1) |
1205 continue; |
1215 continue; |
1206 r = index_get_parents(self, revnum, parents, (int)len - 1); |
1216 r = index_get_parents(self, revnum, parents, (int)len - 1); |
2432 "clear the index caches"}, |
2442 "clear the index caches"}, |
2433 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
2443 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
2434 "get an index entry"}, |
2444 "get an index entry"}, |
2435 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, |
2445 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets, |
2436 METH_VARARGS, "compute phases"}, |
2446 METH_VARARGS, "compute phases"}, |
2437 {"reachableroots", (PyCFunction)reachableroots, METH_VARARGS, |
2447 {"reachableroots2", (PyCFunction)reachableroots2, METH_VARARGS, |
2438 "reachableroots"}, |
2448 "reachableroots"}, |
2439 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, |
2449 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, |
2440 "get head revisions"}, /* Can do filtering since 3.2 */ |
2450 "get head revisions"}, /* Can do filtering since 3.2 */ |
2441 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS, |
2451 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS, |
2442 "get filtered head revisions"}, /* Can always do filtering */ |
2452 "get filtered head revisions"}, /* Can always do filtering */ |