532 bail: |
532 bail: |
533 Py_XDECREF(obj); |
533 Py_XDECREF(obj); |
534 return NULL; |
534 return NULL; |
535 } |
535 } |
536 |
536 |
|
537 static PyObject *index_headrevs(indexObject *self) |
|
538 { |
|
539 Py_ssize_t i, len, addlen; |
|
540 char *nothead = NULL; |
|
541 PyObject *heads; |
|
542 |
|
543 len = index_length(self) - 1; |
|
544 heads = PyList_New(0); |
|
545 if (heads == NULL) |
|
546 goto bail; |
|
547 if (len == 0) { |
|
548 PyObject *nullid = PyInt_FromLong(-1); |
|
549 if (nullid == NULL || PyList_Append(heads, nullid) == -1) { |
|
550 Py_XDECREF(nullid); |
|
551 goto bail; |
|
552 } |
|
553 goto done; |
|
554 } |
|
555 |
|
556 nothead = calloc(len, 1); |
|
557 if (nothead == NULL) |
|
558 goto bail; |
|
559 |
|
560 for (i = 0; i < self->raw_length; i++) { |
|
561 const char *data = index_deref(self, i); |
|
562 int parent_1 = getbe32(data + 24); |
|
563 int parent_2 = getbe32(data + 28); |
|
564 if (parent_1 >= 0) |
|
565 nothead[parent_1] = 1; |
|
566 if (parent_2 >= 0) |
|
567 nothead[parent_2] = 1; |
|
568 } |
|
569 |
|
570 addlen = self->added ? PyList_GET_SIZE(self->added) : 0; |
|
571 |
|
572 for (i = 0; i < addlen; i++) { |
|
573 PyObject *rev = PyList_GET_ITEM(self->added, i); |
|
574 PyObject *p1 = PyTuple_GET_ITEM(rev, 5); |
|
575 PyObject *p2 = PyTuple_GET_ITEM(rev, 6); |
|
576 long parent_1, parent_2; |
|
577 |
|
578 if (!PyInt_Check(p1) || !PyInt_Check(p2)) { |
|
579 PyErr_SetString(PyExc_TypeError, |
|
580 "revlog parents are invalid"); |
|
581 goto bail; |
|
582 } |
|
583 parent_1 = PyInt_AS_LONG(p1); |
|
584 parent_2 = PyInt_AS_LONG(p2); |
|
585 if (parent_1 >= 0) |
|
586 nothead[parent_1] = 1; |
|
587 if (parent_2 >= 0) |
|
588 nothead[parent_2] = 1; |
|
589 } |
|
590 |
|
591 for (i = 0; i < len; i++) { |
|
592 PyObject *head; |
|
593 |
|
594 if (nothead[i]) |
|
595 continue; |
|
596 head = PyInt_FromLong(i); |
|
597 if (head == NULL || PyList_Append(heads, head) == -1) { |
|
598 Py_XDECREF(head); |
|
599 goto bail; |
|
600 } |
|
601 } |
|
602 |
|
603 done: |
|
604 free(nothead); |
|
605 return heads; |
|
606 bail: |
|
607 Py_XDECREF(heads); |
|
608 free(nothead); |
|
609 return NULL; |
|
610 } |
|
611 |
537 static inline int nt_level(const char *node, Py_ssize_t level) |
612 static inline int nt_level(const char *node, Py_ssize_t level) |
538 { |
613 { |
539 int v = node[level>>1]; |
614 int v = node[level>>1]; |
540 if (!(level & 1)) |
615 if (!(level & 1)) |
541 v >>= 4; |
616 v >>= 4; |
1142 static PyMethodDef index_methods[] = { |
1217 static PyMethodDef index_methods[] = { |
1143 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
1218 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
1144 "clear the index caches"}, |
1219 "clear the index caches"}, |
1145 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
1220 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
1146 "get an index entry"}, |
1221 "get an index entry"}, |
|
1222 {"headrevs", (PyCFunction)index_headrevs, METH_NOARGS, |
|
1223 "get head revisions"}, |
1147 {"insert", (PyCFunction)index_insert, METH_VARARGS, |
1224 {"insert", (PyCFunction)index_insert, METH_VARARGS, |
1148 "insert an index entry"}, |
1225 "insert an index entry"}, |
1149 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS, |
1226 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS, |
1150 "match a potentially ambiguous node ID"}, |
1227 "match a potentially ambiguous node ID"}, |
1151 {"stats", (PyCFunction)index_stats, METH_NOARGS, |
1228 {"stats", (PyCFunction)index_stats, METH_NOARGS, |