1 /*
2 * Copyright 2010-2021 The pygit2 contributors
3 *
4 * This file is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
7 *
8 * In addition to the permissions in the GNU General Public License,
9 * the authors give you unlimited permission to link the compiled
10 * version of this file into combinations with other programs,
11 * and to distribute those combinations without any restriction
12 * coming from the use of this file. (The General Public License
13 * restrictions do apply in other respects; for example, they cover
14 * modification of the file, and distribution when not linked into
15 * a combined executable.)
16 *
17 * This file is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; see the file COPYING. If not, write to
24 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA.
26 */
27
28 #define PY_SSIZE_T_CLEAN
29 #include <Python.h>
30 #include "error.h"
31 #include "object.h"
32 #include "oid.h"
33 #include "tree.h"
34 #include "utils.h"
35 #include "walker.h"
36
37 extern PyTypeObject CommitType;
38
39 void
Walker_dealloc(Walker * self)40 Walker_dealloc(Walker *self)
41 {
42 Py_CLEAR(self->repo);
43 git_revwalk_free(self->walk);
44 PyObject_Del(self);
45 }
46
47
48 PyDoc_STRVAR(Walker_hide__doc__,
49 "hide(oid)\n"
50 "\n"
51 "Mark a commit (and its ancestors) uninteresting for the output.");
52
53 PyObject *
Walker_hide(Walker * self,PyObject * py_hex)54 Walker_hide(Walker *self, PyObject *py_hex)
55 {
56 int err;
57 git_oid oid;
58
59 err = py_oid_to_git_oid_expand(self->repo->repo, py_hex, &oid);
60 if (err < 0)
61 return NULL;
62
63 err = git_revwalk_hide(self->walk, &oid);
64 if (err < 0)
65 return Error_set(err);
66
67 Py_RETURN_NONE;
68 }
69
70
71 PyDoc_STRVAR(Walker_push__doc__,
72 "push(oid)\n"
73 "\n"
74 "Mark a commit to start traversal from.");
75
76 PyObject *
Walker_push(Walker * self,PyObject * py_hex)77 Walker_push(Walker *self, PyObject *py_hex)
78 {
79 int err;
80 git_oid oid;
81
82 err = py_oid_to_git_oid_expand(self->repo->repo, py_hex, &oid);
83 if (err < 0)
84 return NULL;
85
86 err = git_revwalk_push(self->walk, &oid);
87 if (err < 0)
88 return Error_set(err);
89
90 Py_RETURN_NONE;
91 }
92
93
94 PyDoc_STRVAR(Walker_sort__doc__,
95 "sort(mode)\n"
96 "\n"
97 "Change the sorting mode (this resets the walker).");
98
99 PyObject *
Walker_sort(Walker * self,PyObject * py_sort_mode)100 Walker_sort(Walker *self, PyObject *py_sort_mode)
101 {
102 long sort_mode;
103
104 sort_mode = PyLong_AsLong(py_sort_mode);
105 if (sort_mode == -1 && PyErr_Occurred())
106 return NULL;
107
108 git_revwalk_sorting(self->walk, (unsigned int)sort_mode);
109
110 Py_RETURN_NONE;
111 }
112
113
114 PyDoc_STRVAR(Walker_reset__doc__,
115 "reset()\n"
116 "\n"
117 "Reset the walking machinery for reuse.");
118
119 PyObject *
Walker_reset(Walker * self)120 Walker_reset(Walker *self)
121 {
122 git_revwalk_reset(self->walk);
123 Py_RETURN_NONE;
124 }
125
126 PyDoc_STRVAR(Walker_simplify_first_parent__doc__,
127 "simplify_first_parent()\n"
128 "\n"
129 "Simplify the history by first-parent.");
130
131 PyObject *
Walker_simplify_first_parent(Walker * self)132 Walker_simplify_first_parent(Walker *self)
133 {
134 git_revwalk_simplify_first_parent(self->walk);
135 Py_RETURN_NONE;
136 }
137
138 PyObject *
Walker_iter(Walker * self)139 Walker_iter(Walker *self)
140 {
141 Py_INCREF(self);
142 return (PyObject*)self;
143 }
144
145 PyObject *
Walker_iternext(Walker * self)146 Walker_iternext(Walker *self)
147 {
148 int err;
149 git_commit *commit;
150 git_oid oid;
151
152 err = git_revwalk_next(&oid, self->walk);
153 if (err < 0)
154 return Error_set(err);
155
156 err = git_commit_lookup(&commit, self->repo->repo, &oid);
157 if (err < 0)
158 return Error_set(err);
159
160 return wrap_object((git_object*)commit, self->repo, NULL);
161 }
162
163 PyMethodDef Walker_methods[] = {
164 METHOD(Walker, hide, METH_O),
165 METHOD(Walker, push, METH_O),
166 METHOD(Walker, reset, METH_NOARGS),
167 METHOD(Walker, simplify_first_parent, METH_NOARGS),
168 METHOD(Walker, sort, METH_O),
169 {NULL}
170 };
171
172
173 PyDoc_STRVAR(Walker__doc__, "Revision walker.");
174
175 PyTypeObject WalkerType = {
176 PyVarObject_HEAD_INIT(NULL, 0)
177 "_pygit2.Walker", /* tp_name */
178 sizeof(Walker), /* tp_basicsize */
179 0, /* tp_itemsize */
180 (destructor)Walker_dealloc, /* tp_dealloc */
181 0, /* tp_print */
182 0, /* tp_getattr */
183 0, /* tp_setattr */
184 0, /* tp_compare */
185 0, /* tp_repr */
186 0, /* tp_as_number */
187 0, /* tp_as_sequence */
188 0, /* tp_as_mapping */
189 0, /* tp_hash */
190 0, /* tp_call */
191 0, /* tp_str */
192 0, /* tp_getattro */
193 0, /* tp_setattro */
194 0, /* tp_as_buffer */
195 Py_TPFLAGS_DEFAULT, /* tp_flags */
196 Walker__doc__, /* tp_doc */
197 0, /* tp_traverse */
198 0, /* tp_clear */
199 0, /* tp_richcompare */
200 0, /* tp_weaklistoffset */
201 (getiterfunc)Walker_iter, /* tp_iter */
202 (iternextfunc)Walker_iternext, /* tp_iternext */
203 Walker_methods, /* tp_methods */
204 0, /* tp_members */
205 0, /* tp_getset */
206 0, /* tp_base */
207 0, /* tp_dict */
208 0, /* tp_descr_get */
209 0, /* tp_descr_set */
210 0, /* tp_dictoffset */
211 0, /* tp_init */
212 0, /* tp_alloc */
213 0, /* tp_new */
214 };
215