Skip to content

Commit 0d79ad8

Browse files
committed
The / operator now returns Tree, not TreeEntry
New Tree.name and Tree.filemode
1 parent 2481c02 commit 0d79ad8

File tree

13 files changed

+106
-79
lines changed

13 files changed

+106
-79
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
0.28.3 (UNRELEASED)
22
-------------------------
33

4-
- Support for "/" operator to traverse trees
4+
- Support for ``/`` operator to traverse trees
55
`#903 <https://github.com/libgit2/pygit2/pull/903>`_
66

7-
- New `Index.remove_all()`
7+
- New ``Index.remove_all()``
88
`#920 <https://github.com/libgit2/pygit2/pull/920>`_
99

10-
- New `Repository.lookup_reference_dwim(..)` and `Repository.resolve_refish(..)`
10+
- New ``Repository.lookup_reference_dwim(..)`` and ``Repository.resolve_refish(..)``
1111
`#922 <https://github.com/libgit2/pygit2/pull/922>`_
1212

1313
- Fix spurious exception in config

docs/objects.rst

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,8 @@ New objects are created using an specific API we will see later.
7878

7979
This is the common interface for all Git objects:
8080

81-
.. autoattribute:: pygit2.Object.id
82-
.. autoattribute:: pygit2.Object.type
83-
.. autoattribute:: pygit2.Object.short_id
84-
.. automethod:: pygit2.Object.read_raw
85-
.. automethod:: pygit2.Object.peel
86-
.. automethod:: pygit2.Object.__eq__(Object)
87-
.. automethod:: pygit2.Object.__ne__(Object)
88-
.. automethod:: pygit2.Object.__hash__
81+
.. autoclass:: pygit2.Object
82+
:members: id, type, short_id, read_raw, peel, name, filemode, __eq__, __ne__, __hash__
8983

9084
Blobs
9185
=================

src/commit.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,7 @@ Commit_tree__get__(Commit *commit)
173173
if (err < 0)
174174
return Error_set(err);
175175

176-
py_tree = PyObject_New(Tree, &TreeType);
177-
if (py_tree) {
178-
Py_INCREF(commit->repo);
179-
py_tree->repo = commit->repo;
180-
py_tree->tree = (git_tree*)tree;
181-
}
182-
return (PyObject*)py_tree;
176+
return wrap_object((git_object*)tree, commit->repo, NULL);
183177
}
184178

185179
PyDoc_STRVAR(Commit_tree_id__doc__, "The id of the tree attached to the commit.");
@@ -223,7 +217,7 @@ Commit_parents__get__(Commit *self)
223217
return Error_set_oid(err, parent_oid, GIT_OID_HEXSZ);
224218
}
225219

226-
py_parent = wrap_object((git_object*)parent, py_repo);
220+
py_parent = wrap_object((git_object*)parent, py_repo, NULL);
227221
if (py_parent == NULL) {
228222
Py_DECREF(list);
229223
return NULL;

src/object.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Object_dealloc(Object* self)
4747
{
4848
Py_CLEAR(self->repo);
4949
git_object_free(self->obj);
50+
git_tree_entry_free((git_tree_entry*)self->entry);
5051
Py_TYPE(self)->tp_free(self);
5152
}
5253

@@ -130,6 +131,28 @@ Object__pointer__get__(Object *self)
130131
return PyBytes_FromStringAndSize((char *) &self->obj, sizeof(git_object *));
131132
}
132133

134+
PyDoc_STRVAR(Object_name__doc__,
135+
"Name (will be None if the object was not reached trough a tree)");
136+
PyObject *
137+
Object_name__get__(Object *self)
138+
{
139+
if (self->entry == NULL)
140+
Py_RETURN_NONE;
141+
142+
return to_path(git_tree_entry_name(self->entry));
143+
}
144+
145+
PyDoc_STRVAR(Object_filemode__doc__,
146+
"Filemode (will be None if the object was not reached trough a tree)");
147+
PyObject *
148+
Object_filemode__get__(Object *self)
149+
{
150+
if (self->entry == NULL)
151+
Py_RETURN_NONE;
152+
153+
return PyInt_FromLong(git_tree_entry_filemode(self->entry));
154+
}
155+
133156

134157
PyDoc_STRVAR(Object_read_raw__doc__,
135158
"read_raw()\n"
@@ -177,7 +200,7 @@ Object_peel(Object *self, PyObject *py_type)
177200
if (err < 0)
178201
return Error_set(err);
179202

180-
return wrap_object(peeled, self->repo);
203+
return wrap_object(peeled, self->repo, NULL);
181204
}
182205

183206
Py_hash_t
@@ -243,6 +266,9 @@ PyGetSetDef Object_getseters[] = {
243266
GETTER(Object, short_id),
244267
GETTER(Object, type),
245268
GETTER(Object, _pointer),
269+
// These come from git_tree_entry
270+
GETTER(Object, name),
271+
GETTER(Object, filemode),
246272
{NULL}
247273
};
248274

@@ -297,7 +323,7 @@ PyTypeObject ObjectType = {
297323
};
298324

299325
PyObject *
300-
wrap_object(git_object *c_object, Repository *repo)
326+
wrap_object(git_object *c_object, Repository *repo, const git_tree_entry *entry)
301327
{
302328
Object *py_obj = NULL;
303329

@@ -324,6 +350,7 @@ wrap_object(git_object *c_object, Repository *repo)
324350
py_obj->repo = repo;
325351
Py_INCREF(repo);
326352
}
353+
py_obj->entry = entry;
327354
}
328355
return (PyObject *)py_obj;
329356
}

src/object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ PyObject* Object_get_oid(Object *self);
3737
PyObject* Object_get_hex(Object *self);
3838
PyObject* Object_get_type(Object *self);
3939
PyObject* Object_read_raw(Object *self);
40-
PyObject* wrap_object(git_object *c_object, Repository *repo);
40+
PyObject* wrap_object(git_object *c_object, Repository *repo, const git_tree_entry *entry);
4141

4242
#endif

src/reference.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ Reference_peel(Reference *self, PyObject *args)
407407
if (err < 0)
408408
return Error_set(err);
409409

410-
return wrap_object(obj, self->repo);
410+
return wrap_object(obj, self->repo, NULL);
411411
}
412412

413413
PyObject *

src/repository.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ Repository_git_object_lookup_prefix(Repository *self, PyObject *key)
314314

315315
err = git_object_lookup_prefix(&obj, self->repo, &oid, len, GIT_OBJ_ANY);
316316
if (err == 0)
317-
return wrap_object(obj, self);
317+
return wrap_object(obj, self, NULL);
318318

319319
if (err == GIT_ENOTFOUND)
320320
Py_RETURN_NONE;
@@ -402,7 +402,7 @@ Repository_revparse_single(Repository *self, PyObject *py_spec)
402402
}
403403
Py_DECREF(tspec);
404404

405-
return wrap_object(c_obj, self);
405+
return wrap_object(c_obj, self, NULL);
406406
}
407407

408408
git_odb_object *

src/tag.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Tag_get_object(Tag *self)
6363
if (err < 0)
6464
return Error_set(err);
6565

66-
return wrap_object(obj, self->repo);
66+
return wrap_object(obj, self->repo, NULL);
6767
}
6868

6969

src/tree.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ treeentry_to_object(TreeEntry* self)
214214
int err;
215215

216216
if (self->repo == NULL) {
217-
PyErr_SetString(PyExc_ValueError, "No repository associated with this TreeEntry");
217+
PyErr_SetString(PyExc_ValueError,
218+
"No repository associated with this TreeEntry");
218219
return NULL;
219220
}
220221
py_repo = self->repo;
@@ -225,8 +226,9 @@ treeentry_to_object(TreeEntry* self)
225226
return NULL;
226227
}
227228

228-
return wrap_object(obj, py_repo);
229+
return wrap_object(obj, py_repo, self->entry);
229230
}
231+
230232
PyDoc_STRVAR(TreeEntry_obj__doc__, "Object (subtree/blob)");
231233

232234
PyObject *
@@ -238,7 +240,7 @@ TreeEntry_obj__get__(TreeEntry *self)
238240
if (subtree == NULL)
239241
return NULL;
240242

241-
return wrap_object((git_object*)subtree, self->repo);
243+
return wrap_object((git_object*)subtree, self->repo, self->entry);
242244
} else {
243245
return treeentry_to_object(self);
244246
}
@@ -302,10 +304,10 @@ TreeEntry_getitem(TreeEntry *self, PyObject *value)
302304

303305
if (PyInt_Check(value)) {
304306
/* Case 1: integer */
305-
r = tree_getitem_by_index(subtree, self->repo, value);
307+
r = tree_getentry_by_index(subtree, self->repo, value);
306308
} else {
307309
/* Case 2: byte or text string */
308-
r = tree_getitem_by_path(subtree, self->repo, value);
310+
r = tree_getentry_by_path(subtree, self->repo, value);
309311
}
310312

311313
git_tree_free(subtree);
@@ -533,7 +535,7 @@ Tree_iter(Tree *self)
533535
}
534536

535537
TreeEntry *
536-
tree_getitem_by_index(const git_tree *tree, Repository *repo, PyObject *py_index)
538+
tree_getentry_by_index(const git_tree *tree, Repository *repo, PyObject *py_index)
537539
{
538540
int index;
539541
const git_tree_entry *entry_src;
@@ -558,7 +560,7 @@ tree_getitem_by_index(const git_tree *tree, Repository *repo, PyObject *py_index
558560
}
559561

560562
TreeEntry *
561-
tree_getitem_by_path(const git_tree *tree, Repository *repo, PyObject *py_path)
563+
tree_getentry_by_path(const git_tree *tree, Repository *repo, PyObject *py_path)
562564
{
563565
char *path;
564566
git_tree_entry *entry;
@@ -586,14 +588,23 @@ tree_getitem_by_path(const git_tree *tree, Repository *repo, PyObject *py_path)
586588
}
587589

588590
TreeEntry *
589-
Tree_getitem(Tree *self, PyObject *value)
591+
Tree_getentry(Tree *self, PyObject *value)
590592
{
591593
/* Case 1: integer */
592594
if (PyInt_Check(value))
593-
return tree_getitem_by_index(self->tree, self->repo, value);
595+
return tree_getentry_by_index(self->tree, self->repo, value);
594596

595597
/* Case 2: byte or text string */
596-
return tree_getitem_by_path(self->tree, self->repo, value);
598+
return tree_getentry_by_path(self->tree, self->repo, value);
599+
}
600+
601+
PyObject *
602+
Tree_getobj(Tree *self, PyObject *value)
603+
{
604+
TreeEntry* entry = tree_getentry_by_path(self->tree, self->repo, value);
605+
if (entry == NULL)
606+
return NULL;
607+
return treeentry_to_object(entry);
597608
}
598609

599610

@@ -782,7 +793,7 @@ PySequenceMethods Tree_as_sequence = {
782793

783794
PyMappingMethods Tree_as_mapping = {
784795
(lenfunc)Tree_len, /* mp_length */
785-
(binaryfunc)Tree_getitem, /* mp_subscript */
796+
(binaryfunc)Tree_getentry, /* mp_subscript */
786797
0, /* mp_ass_subscript */
787798
};
788799

@@ -801,7 +812,7 @@ PyNumberMethods Tree_as_number = {
801812
0, /* nb_subtract */
802813
0, /* nb_multiply */
803814
#if PY_MAJOR_VERSION < 3
804-
(binaryfunc)Tree_getitem, /* Py2: nb_divide */
815+
(binaryfunc)Tree_getobj, /* Py2: nb_divide */
805816
#endif
806817
0, /* nb_remainder */
807818
0, /* nb_divmod */
@@ -837,7 +848,7 @@ PyNumberMethods Tree_as_number = {
837848
0, /* nb_inplace_xor */
838849
0, /* nb_inplace_or */
839850
0, /* nb_floor_divide */
840-
(binaryfunc)Tree_getitem, /* nb_true_divide */
851+
(binaryfunc)Tree_getobj, /* nb_true_divide */
841852
0, /* nb_inplace_floor_divide */
842853
0, /* nb_inplace_true_divide */
843854
0, /* nb_index */

src/tree.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ PyObject* TreeEntry_get_oid(TreeEntry *self);
4040
PyObject* TreeEntry_get_hex(TreeEntry *self);
4141
PyObject* TreeEntry_get_obj(TreeEntry *self);
4242

43-
TreeEntry* tree_getitem_by_index(const git_tree *tree, Repository *repo, PyObject *py_index);
44-
TreeEntry* tree_getitem_by_path(const git_tree *tree, Repository *repo, PyObject *py_path);
43+
TreeEntry* tree_getentry_by_index(const git_tree *tree, Repository *repo,
44+
PyObject *py_index);
45+
TreeEntry* tree_getentry_by_path(const git_tree *tree, Repository *repo,
46+
PyObject *py_path);
4547
PyObject* Tree_diff_tree(Tree *self, PyObject *args);
4648

4749

48-
4950
#endif

0 commit comments

Comments
 (0)