Skip to content

Commit 9e91a39

Browse files
committed
Index: accept a tree for read_tree()
An index may not have an associated repository, so giving it an id in that case is useless. Raise an error in that case and accept a Tree object to make the function useful then.
1 parent f69a57a commit 9e91a39

2 files changed

Lines changed: 37 additions & 9 deletions

File tree

docs/working-copy.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ Custom entries::
2626
>>> entry = pygit2.IndexEntry('README.md', blob_id, blob_filemode)
2727
>>> repo.index.add(entry)
2828

29+
The index fulfills a dual role as the in-memory representation of the
30+
index file and data structure which represents a flat list of a
31+
tree. You can use it independently of the index file, e.g.
32+
33+
>>> index = pygit2.Index()
34+
>>> entry = pygit2.IndexEntry('README.md', blob_id, blob_filemode)
35+
>>> index.add(entry)
36+
2937
The Index type
3038
====================
3139

src/index.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,26 +426,46 @@ Index_remove(Index *self, PyObject *args)
426426
PyDoc_STRVAR(Index_read_tree__doc__,
427427
"read_tree(tree)\n"
428428
"\n"
429-
"Update the index file from the tree identified by the given oid.");
429+
"Update the index file from the specified tree. The tree can be a Tree object or an Oid.\n"
430+
"Using an Oid is only possible if this index is associated with a repository");
430431

431432
PyObject *
432433
Index_read_tree(Index *self, PyObject *value)
433434
{
434435
git_oid oid;
435-
git_tree *tree;
436-
int err;
436+
git_tree *tree = NULL;
437+
int err, need_free = 0;
437438
size_t len;
438439

439440
len = py_oid_to_git_oid(value, &oid);
440-
if (len == 0)
441-
return NULL;
441+
if (len == 0) {
442+
Tree *py_tree;
443+
if (!PyObject_TypeCheck(value, &TreeType)) {
444+
return NULL;
445+
}
442446

443-
err = git_tree_lookup_prefix(&tree, self->repo->repo, &oid, len);
444-
if (err < 0)
445-
return Error_set(err);
447+
PyErr_Clear();
448+
py_tree = (Tree *) value;
449+
tree = py_tree->tree;
450+
}
451+
452+
/*
453+
* if the user passed in an id but we're not associated with a
454+
* repo, we can't do anything
455+
*/
456+
if (tree == NULL && self->repo == NULL) {
457+
PyErr_SetString(PyExc_TypeError, "id given but no associated repository");
458+
return NULL;
459+
} else if (tree == NULL) {
460+
need_free = 1;
461+
err = git_tree_lookup_prefix(&tree, self->repo->repo, &oid, len);
462+
if (err < 0)
463+
return Error_set(err);
464+
}
446465

447466
err = git_index_read_tree(self->index, tree);
448-
git_tree_free(tree);
467+
if (need_free)
468+
git_tree_free(tree);
449469
if (err < 0)
450470
return Error_set(err);
451471

0 commit comments

Comments
 (0)