repository: add listall_reference_objects() method
This allows for efficient reading of many references and their targets, without incurring the overhead of lookup_reference() (which stats for a loose ref and then reads packed-refs) which can be expensive on NFS with thousands of refs.
This commit is contained in:
		| @@ -4,6 +4,7 @@ References | |||||||
|  |  | ||||||
| .. contents:: | .. contents:: | ||||||
|  |  | ||||||
|  | .. automethod:: pygit2.Repository.listall_reference_objects | ||||||
| .. automethod:: pygit2.Repository.listall_references | .. automethod:: pygit2.Repository.listall_references | ||||||
| .. automethod:: pygit2.Repository.lookup_reference | .. automethod:: pygit2.Repository.lookup_reference | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1123,6 +1123,56 @@ out: | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | PyDoc_STRVAR(Repository_listall_reference_objects__doc__, | ||||||
|  |   "listall_reference_objects() -> [Reference, ...]\n" | ||||||
|  |   "\n" | ||||||
|  |   "Return a list with all the reference objects in the repository."); | ||||||
|  |  | ||||||
|  | PyObject * | ||||||
|  | Repository_listall_reference_objects(Repository *self, PyObject *args) | ||||||
|  | { | ||||||
|  |     git_reference_iterator *iter; | ||||||
|  |     git_reference *ref = NULL; | ||||||
|  |     int err; | ||||||
|  |     PyObject *list; | ||||||
|  |  | ||||||
|  |     list = PyList_New(0); | ||||||
|  |     if (list == NULL) | ||||||
|  |         return NULL; | ||||||
|  |  | ||||||
|  |     if ((err = git_reference_iterator_new(&iter, self->repo)) < 0) | ||||||
|  |         return Error_set(err); | ||||||
|  |  | ||||||
|  |     while ((err = git_reference_next(&ref, iter)) == 0) { | ||||||
|  |         PyObject *py_ref = wrap_reference(ref, self); | ||||||
|  |         if (py_ref == NULL) | ||||||
|  |             goto error; | ||||||
|  |  | ||||||
|  |         err = PyList_Append(list, py_ref); | ||||||
|  |         Py_DECREF(py_ref); | ||||||
|  |  | ||||||
|  |         if (err < 0) | ||||||
|  |             goto error; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     git_reference_iterator_free(iter); | ||||||
|  |     if (err == GIT_ITEROVER) | ||||||
|  |         err = 0; | ||||||
|  |  | ||||||
|  |     if (err < 0) { | ||||||
|  |         Py_CLEAR(list); | ||||||
|  |         return Error_set(err); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return list; | ||||||
|  |  | ||||||
|  | error: | ||||||
|  |     git_reference_iterator_free(iter); | ||||||
|  |     Py_CLEAR(list); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| PyDoc_STRVAR(Repository_listall_branches__doc__, | PyDoc_STRVAR(Repository_listall_branches__doc__, | ||||||
|   "listall_branches([flag]) -> [str, ...]\n" |   "listall_branches([flag]) -> [str, ...]\n" | ||||||
|   "\n" |   "\n" | ||||||
| @@ -1643,6 +1693,7 @@ PyMethodDef Repository_methods[] = { | |||||||
|     METHOD(Repository, create_reference_direct, METH_VARARGS), |     METHOD(Repository, create_reference_direct, METH_VARARGS), | ||||||
|     METHOD(Repository, create_reference_symbolic, METH_VARARGS), |     METHOD(Repository, create_reference_symbolic, METH_VARARGS), | ||||||
|     METHOD(Repository, listall_references, METH_NOARGS), |     METHOD(Repository, listall_references, METH_NOARGS), | ||||||
|  |     METHOD(Repository, listall_reference_objects, METH_NOARGS), | ||||||
|     METHOD(Repository, listall_submodules, METH_NOARGS), |     METHOD(Repository, listall_submodules, METH_NOARGS), | ||||||
|     METHOD(Repository, lookup_reference, METH_O), |     METHOD(Repository, lookup_reference, METH_O), | ||||||
|     METHOD(Repository, revparse_single, METH_O), |     METHOD(Repository, revparse_single, METH_O), | ||||||
|   | |||||||
| @@ -58,6 +58,8 @@ PyObject* Repository_create_commit(Repository *self, PyObject *args); | |||||||
| PyObject* Repository_create_tag(Repository *self, PyObject *args); | PyObject* Repository_create_tag(Repository *self, PyObject *args); | ||||||
| PyObject* Repository_create_branch(Repository *self, PyObject *args); | PyObject* Repository_create_branch(Repository *self, PyObject *args); | ||||||
| PyObject* Repository_listall_references(Repository *self, PyObject *args); | PyObject* Repository_listall_references(Repository *self, PyObject *args); | ||||||
|  | PyObject* Repository_listall_reference_objects(Repository *self, | ||||||
|  |                                                PyObject *args); | ||||||
| PyObject* Repository_listall_branches(Repository *self, PyObject *args); | PyObject* Repository_listall_branches(Repository *self, PyObject *args); | ||||||
| PyObject* Repository_lookup_reference(Repository *self, PyObject *py_name); | PyObject* Repository_lookup_reference(Repository *self, PyObject *py_name); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,6 +42,17 @@ LAST_COMMIT = '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98' | |||||||
|  |  | ||||||
| class ReferencesTest(utils.RepoTestCase): | class ReferencesTest(utils.RepoTestCase): | ||||||
|  |  | ||||||
|  |     def test_list_all_reference_objects(self): | ||||||
|  |         repo = self.repo | ||||||
|  |  | ||||||
|  |         refs = [(ref.name, ref.target.hex) | ||||||
|  |                 for ref in repo.listall_reference_objects()] | ||||||
|  |         self.assertEqual(sorted(refs), | ||||||
|  |                          [('refs/heads/i18n', | ||||||
|  |                            '5470a671a80ac3789f1a6a8cefbcf43ce7af0563'), | ||||||
|  |                           ('refs/heads/master', | ||||||
|  |                            '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98')]) | ||||||
|  |  | ||||||
|     def test_list_all_references(self): |     def test_list_all_references(self): | ||||||
|         repo = self.repo |         repo = self.repo | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Brodie Rao
					Brodie Rao