1161 default: |
1161 default: |
1162 return 1; |
1162 return 1; |
1163 } |
1163 } |
1164 } |
1164 } |
1165 |
1165 |
|
1166 static inline void index_get_parents(indexObject *self, int rev, int *ps) |
|
1167 { |
|
1168 if (rev >= self->length - 1) { |
|
1169 PyObject *tuple = PyList_GET_ITEM(self->added, |
|
1170 rev - self->length + 1); |
|
1171 ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5)); |
|
1172 ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6)); |
|
1173 } else { |
|
1174 const char *data = index_deref(self, rev); |
|
1175 ps[0] = getbe32(data + 24); |
|
1176 ps[1] = getbe32(data + 28); |
|
1177 } |
|
1178 } |
|
1179 |
|
1180 typedef uint64_t bitmask; |
|
1181 |
|
1182 /* |
|
1183 * Given a disjoint set of revs, return all candidates for the |
|
1184 * greatest common ancestor. In revset notation, this is the set |
|
1185 * "heads(::a and ::b and ...)" |
|
1186 */ |
|
1187 static PyObject *find_gca_candidates(indexObject *self, const int *revs, |
|
1188 int revcount) |
|
1189 { |
|
1190 const bitmask allseen = (1ull << revcount) - 1; |
|
1191 const bitmask poison = 1ull << revcount; |
|
1192 PyObject *gca = PyList_New(0); |
|
1193 int i, v, interesting, left; |
|
1194 int maxrev = -1; |
|
1195 bitmask *seen; |
|
1196 |
|
1197 for (i = 0; i < revcount; i++) { |
|
1198 if (revs[i] > maxrev) |
|
1199 maxrev = revs[i]; |
|
1200 } |
|
1201 |
|
1202 seen = calloc(sizeof(*seen), maxrev + 1); |
|
1203 if (seen == NULL) |
|
1204 return PyErr_NoMemory(); |
|
1205 |
|
1206 for (i = 0; i < revcount; i++) |
|
1207 seen[revs[i]] = 1ull << i; |
|
1208 |
|
1209 interesting = left = revcount; |
|
1210 |
|
1211 for (v = maxrev; v >= 0 && interesting; v--) { |
|
1212 long sv = seen[v]; |
|
1213 int parents[2]; |
|
1214 |
|
1215 if (!sv) |
|
1216 continue; |
|
1217 |
|
1218 if (sv < poison) { |
|
1219 interesting -= 1; |
|
1220 if (sv == allseen) { |
|
1221 PyObject *obj = PyInt_FromLong(v); |
|
1222 if (obj == NULL) |
|
1223 goto bail; |
|
1224 if (PyList_Append(gca, obj) == -1) { |
|
1225 Py_DECREF(obj); |
|
1226 goto bail; |
|
1227 } |
|
1228 sv |= poison; |
|
1229 for (i = 0; i < revcount; i++) { |
|
1230 if (revs[i] == v) { |
|
1231 if (--left <= 1) |
|
1232 goto done; |
|
1233 break; |
|
1234 } |
|
1235 } |
|
1236 } |
|
1237 } |
|
1238 index_get_parents(self, v, parents); |
|
1239 |
|
1240 for (i = 0; i < 2; i++) { |
|
1241 int p = parents[i]; |
|
1242 if (p == -1) |
|
1243 continue; |
|
1244 const long sp = seen[p]; |
|
1245 if (sv < poison) { |
|
1246 if (sp == 0) { |
|
1247 seen[p] = sv; |
|
1248 interesting++; |
|
1249 } |
|
1250 else if (sp != sv) |
|
1251 seen[p] |= sv; |
|
1252 } else { |
|
1253 if (sp && sp < poison) |
|
1254 interesting--; |
|
1255 seen[p] = sv; |
|
1256 } |
|
1257 } |
|
1258 } |
|
1259 |
|
1260 done: |
|
1261 free(seen); |
|
1262 return gca; |
|
1263 bail: |
|
1264 free(seen); |
|
1265 Py_XDECREF(gca); |
|
1266 return NULL; |
|
1267 } |
|
1268 |
|
1269 /* |
|
1270 * Given a disjoint set of revs, return the subset with the longest |
|
1271 * path to the root. |
|
1272 */ |
|
1273 static PyObject *find_deepest(indexObject *self, PyObject *revs) |
|
1274 { |
|
1275 const Py_ssize_t revcount = PyList_GET_SIZE(revs); |
|
1276 static const Py_ssize_t capacity = 24; |
|
1277 int *depth, *interesting = NULL; |
|
1278 int i, j, v, ninteresting; |
|
1279 PyObject *dict = NULL, *keys; |
|
1280 long *seen = NULL; |
|
1281 int maxrev = -1; |
|
1282 long final; |
|
1283 |
|
1284 if (revcount > capacity) { |
|
1285 PyErr_Format(PyExc_OverflowError, |
|
1286 "bitset size (%ld) > capacity (%ld)", |
|
1287 revcount, capacity); |
|
1288 return NULL; |
|
1289 } |
|
1290 |
|
1291 for (i = 0; i < revcount; i++) { |
|
1292 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i)); |
|
1293 if (n > maxrev) |
|
1294 maxrev = n; |
|
1295 } |
|
1296 |
|
1297 depth = calloc(sizeof(*depth), maxrev + 1); |
|
1298 if (depth == NULL) |
|
1299 return PyErr_NoMemory(); |
|
1300 |
|
1301 seen = calloc(sizeof(*seen), maxrev + 1); |
|
1302 if (seen == NULL) { |
|
1303 PyErr_NoMemory(); |
|
1304 goto bail; |
|
1305 } |
|
1306 |
|
1307 interesting = calloc(sizeof(*interesting), 2 << revcount); |
|
1308 if (interesting == NULL) { |
|
1309 PyErr_NoMemory(); |
|
1310 goto bail; |
|
1311 } |
|
1312 |
|
1313 for (i = 0; i < revcount; i++) { |
|
1314 int n = (int)PyInt_AsLong(PyList_GET_ITEM(revs, i)); |
|
1315 long b = 1l << i; |
|
1316 depth[n] = 1; |
|
1317 seen[n] = b; |
|
1318 interesting[b] = 1; |
|
1319 } |
|
1320 |
|
1321 ninteresting = (int)revcount; |
|
1322 |
|
1323 for (v = maxrev; v >= 0 && ninteresting > 1; v--) { |
|
1324 int dv = depth[v]; |
|
1325 int parents[2]; |
|
1326 long sv; |
|
1327 |
|
1328 if (dv == 0) |
|
1329 continue; |
|
1330 |
|
1331 sv = seen[v]; |
|
1332 index_get_parents(self, v, parents); |
|
1333 |
|
1334 for (i = 0; i < 2; i++) { |
|
1335 int p = parents[i]; |
|
1336 long nsp, sp; |
|
1337 int dp; |
|
1338 |
|
1339 if (p == -1) |
|
1340 continue; |
|
1341 |
|
1342 dp = depth[p]; |
|
1343 nsp = sp = seen[p]; |
|
1344 if (dp <= dv) { |
|
1345 depth[p] = dv + 1; |
|
1346 if (sp != sv) { |
|
1347 interesting[sv] += 1; |
|
1348 nsp = seen[p] = sv; |
|
1349 if (sp) { |
|
1350 interesting[sp] -= 1; |
|
1351 if (interesting[sp] == 0) |
|
1352 ninteresting -= 1; |
|
1353 } |
|
1354 } |
|
1355 } |
|
1356 else if (dv == dp - 1) { |
|
1357 nsp = sp | sv; |
|
1358 if (nsp == sp) |
|
1359 continue; |
|
1360 seen[p] = nsp; |
|
1361 interesting[nsp] += 1; |
|
1362 interesting[sp] -= 1; |
|
1363 if (interesting[sp] == 0) |
|
1364 ninteresting -= 1; |
|
1365 } |
|
1366 } |
|
1367 interesting[sv] -= 1; |
|
1368 if (interesting[sv] == 0) |
|
1369 ninteresting -= 1; |
|
1370 } |
|
1371 |
|
1372 final = 0; |
|
1373 j = ninteresting; |
|
1374 for (i = 0; i < (int)(2 << revcount) && j > 0; i++) { |
|
1375 if (interesting[i] == 0) |
|
1376 continue; |
|
1377 final |= i; |
|
1378 j -= 1; |
|
1379 } |
|
1380 if (final == 0) |
|
1381 return PyList_New(0); |
|
1382 |
|
1383 dict = PyDict_New(); |
|
1384 if (dict == NULL) |
|
1385 goto bail; |
|
1386 |
|
1387 j = ninteresting; |
|
1388 for (i = 0; i < revcount && j > 0; i++) { |
|
1389 PyObject *key; |
|
1390 |
|
1391 if ((final & (1 << i)) == 0) |
|
1392 continue; |
|
1393 |
|
1394 key = PyList_GET_ITEM(revs, i); |
|
1395 Py_INCREF(key); |
|
1396 Py_INCREF(Py_None); |
|
1397 if (PyDict_SetItem(dict, key, Py_None) == -1) { |
|
1398 Py_DECREF(key); |
|
1399 Py_DECREF(Py_None); |
|
1400 goto bail; |
|
1401 } |
|
1402 j -= 1; |
|
1403 } |
|
1404 |
|
1405 keys = PyDict_Keys(dict); |
|
1406 |
|
1407 free(depth); |
|
1408 free(seen); |
|
1409 free(interesting); |
|
1410 Py_DECREF(dict); |
|
1411 |
|
1412 return keys; |
|
1413 bail: |
|
1414 free(depth); |
|
1415 free(seen); |
|
1416 free(interesting); |
|
1417 Py_XDECREF(dict); |
|
1418 |
|
1419 return NULL; |
|
1420 } |
|
1421 |
|
1422 /* |
|
1423 * Given a (possibly overlapping) set of revs, return the greatest |
|
1424 * common ancestors: those with the longest path to the root. |
|
1425 */ |
|
1426 static PyObject *index_ancestors(indexObject *self, PyObject *args) |
|
1427 { |
|
1428 PyObject *ret = NULL, *gca = NULL; |
|
1429 Py_ssize_t argcount, i, len; |
|
1430 bitmask repeat = 0; |
|
1431 int revcount = 0; |
|
1432 int *revs; |
|
1433 |
|
1434 argcount = PySequence_Length(args); |
|
1435 revs = malloc(argcount * sizeof(*revs)); |
|
1436 if (argcount > 0 && revs == NULL) |
|
1437 return PyErr_NoMemory(); |
|
1438 len = index_length(self) - 1; |
|
1439 |
|
1440 for (i = 0; i < argcount; i++) { |
|
1441 static const int capacity = 24; |
|
1442 PyObject *obj = PySequence_GetItem(args, i); |
|
1443 bitmask x; |
|
1444 long val; |
|
1445 |
|
1446 if (!PyInt_Check(obj)) { |
|
1447 PyErr_SetString(PyExc_TypeError, |
|
1448 "arguments must all be ints"); |
|
1449 goto bail; |
|
1450 } |
|
1451 val = PyInt_AsLong(obj); |
|
1452 if (val == -1) { |
|
1453 ret = PyList_New(0); |
|
1454 goto done; |
|
1455 } |
|
1456 if (val < 0 || val >= len) { |
|
1457 PyErr_SetString(PyExc_IndexError, |
|
1458 "index out of range"); |
|
1459 goto bail; |
|
1460 } |
|
1461 /* this cheesy bloom filter lets us avoid some more |
|
1462 * expensive duplicate checks in the common set-is-disjoint |
|
1463 * case */ |
|
1464 x = 1ull << (val & 0x3f); |
|
1465 if (repeat & x) { |
|
1466 int k; |
|
1467 for (k = 0; k < revcount; k++) { |
|
1468 if (val == revs[k]) |
|
1469 goto duplicate; |
|
1470 } |
|
1471 } |
|
1472 else repeat |= x; |
|
1473 if (revcount >= capacity) { |
|
1474 PyErr_Format(PyExc_OverflowError, |
|
1475 "bitset size (%d) > capacity (%d)", |
|
1476 revcount, capacity); |
|
1477 goto bail; |
|
1478 } |
|
1479 revs[revcount++] = (int)val; |
|
1480 duplicate:; |
|
1481 } |
|
1482 |
|
1483 if (revcount == 0) { |
|
1484 ret = PyList_New(0); |
|
1485 goto done; |
|
1486 } |
|
1487 if (revcount == 1) { |
|
1488 PyObject *obj; |
|
1489 ret = PyList_New(1); |
|
1490 if (ret == NULL) |
|
1491 goto bail; |
|
1492 obj = PyInt_FromLong(revs[0]); |
|
1493 if (obj == NULL) |
|
1494 goto bail; |
|
1495 PyList_SET_ITEM(ret, 0, obj); |
|
1496 goto done; |
|
1497 } |
|
1498 |
|
1499 gca = find_gca_candidates(self, revs, revcount); |
|
1500 if (gca == NULL) |
|
1501 goto bail; |
|
1502 |
|
1503 if (PyList_GET_SIZE(gca) <= 1) { |
|
1504 ret = gca; |
|
1505 Py_INCREF(gca); |
|
1506 } |
|
1507 else if (PyList_GET_SIZE(gca) == 1) { |
|
1508 ret = PyList_GET_ITEM(gca, 0); |
|
1509 Py_INCREF(ret); |
|
1510 } |
|
1511 else ret = find_deepest(self, gca); |
|
1512 |
|
1513 done: |
|
1514 free(revs); |
|
1515 Py_XDECREF(gca); |
|
1516 |
|
1517 return ret; |
|
1518 |
|
1519 bail: |
|
1520 free(revs); |
|
1521 Py_XDECREF(gca); |
|
1522 Py_XDECREF(ret); |
|
1523 return NULL; |
|
1524 } |
|
1525 |
1166 /* |
1526 /* |
1167 * Invalidate any trie entries introduced by added revs. |
1527 * Invalidate any trie entries introduced by added revs. |
1168 */ |
1528 */ |
1169 static void nt_invalidate_added(indexObject *self, Py_ssize_t start) |
1529 static void nt_invalidate_added(indexObject *self, Py_ssize_t start) |
1170 { |
1530 { |
1404 (binaryfunc)index_getitem, /* mp_subscript */ |
1764 (binaryfunc)index_getitem, /* mp_subscript */ |
1405 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */ |
1765 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */ |
1406 }; |
1766 }; |
1407 |
1767 |
1408 static PyMethodDef index_methods[] = { |
1768 static PyMethodDef index_methods[] = { |
|
1769 {"ancestors", (PyCFunction)index_ancestors, METH_VARARGS, |
|
1770 "return the gca set of the given revs"}, |
1409 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
1771 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
1410 "clear the index caches"}, |
1772 "clear the index caches"}, |
1411 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
1773 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
1412 "get an index entry"}, |
1774 "get an index entry"}, |
1413 {"headrevs", (PyCFunction)index_headrevs, METH_NOARGS, |
1775 {"headrevs", (PyCFunction)index_headrevs, METH_NOARGS, |