Skip to content

Commit af38211

Browse files
committed
checkout: move the code to cffi
As part of this, make the strategy part of **kwargs, in preparation for supporting more options.
1 parent d2a62c5 commit af38211

File tree

4 files changed

+64
-83
lines changed

4 files changed

+64
-83
lines changed

pygit2/decl.h

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ typedef ... git_remote;
33
typedef ... git_refspec;
44
typedef ... git_push;
55
typedef ... git_cred;
6+
typedef ... git_object;
67
typedef ... git_tree;
78
typedef ... git_signature;
89
typedef ... git_index;
@@ -309,6 +310,11 @@ typedef enum {
309310
GIT_CLONE_LOCAL_NO_LINKS,
310311
} git_clone_local_t;
311312

313+
int git_checkout_init_options(git_checkout_options *opts, unsigned int version);
314+
int git_checkout_tree(git_repository *repo, const git_object *treeish, const git_checkout_options *opts);
315+
int git_checkout_head(git_repository *repo, const git_checkout_options *opts);
316+
int git_checkout_index(git_repository *repo, git_index *index, const git_checkout_options *opts);
317+
312318
/*
313319
* git_clone
314320
*/

pygit2/repository.py

+56-5
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,52 @@ def create_reference(self, name, target, force=False):
176176

177177
return self.create_reference_symbolic(name, target, force)
178178

179-
180179
#
181180
# Checkout
182181
#
183-
def checkout(self, refname=None, strategy=GIT_CHECKOUT_SAFE_CREATE):
182+
@staticmethod
183+
def _checkout_args_to_options(**kwargs):
184+
# Create the options struct to pass
185+
copts = ffi.new('git_checkout_options *')
186+
check_error(C.git_checkout_init_options(copts, 1))
187+
188+
# pygit2's default is SAFE_CREATE
189+
copts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE
190+
# and go through the arguments to see what the user wanted
191+
for k, v in kwargs.iteritems():
192+
if k == 'strategy':
193+
copts.checkout_strategy = v
194+
195+
return copts
196+
197+
def checkout_head(self, **kwargs):
198+
"""Checkout HEAD
199+
200+
For arguments, see Repository.checkout().
201+
"""
202+
copts = Repository._checkout_args_to_options(**kwargs)
203+
check_error(C.git_checkout_head(self._repo, copts))
204+
205+
def checkout_index(self, **kwargs):
206+
"""Checkout the repository's index
207+
208+
For arguments, see Repository.checkout().
209+
"""
210+
copts = Repository._checkout_args_to_options(**kwargs)
211+
check_error(C.git_checkout_index(self._repo, ffi.NULL, copts))
212+
213+
def checkout_tree(self, treeish, **kwargs):
214+
"""Checkout the given treeish
215+
216+
For arguments, see Repository.checkout().
217+
"""
218+
copts = Repository._checkout_args_to_options(**kwargs)
219+
cptr = ffi.new('git_object **')
220+
ffi.buffer(cptr)[:] = treeish._pointer[:]
221+
222+
check_error(C.git_checkout_tree(self._repo, cptr[0], copts))
223+
224+
def checkout(self, refname=None, **kwargs):
184225
"""
185226
Checkout the given reference using the given strategy, and update
186227
the HEAD.
@@ -193,14 +234,24 @@ def checkout(self, refname=None, strategy=GIT_CHECKOUT_SAFE_CREATE):
193234
194235
If no reference is given, checkout from the index.
195236
237+
Arguments:
238+
239+
:param str refname: The reference to checkout. After checkout,
240+
the current branch will be switched to this one.
241+
242+
:param int strategy: A ``GIT_CHECKOUT_`` value. The default is
243+
``GIT_CHECKOUT_SAFE_CREATE``.
244+
196245
"""
246+
247+
197248
# Case 1: Checkout index
198249
if refname is None:
199-
return self.checkout_index(strategy)
250+
return self.checkout_index(**kwargs)
200251

201252
# Case 2: Checkout head
202253
if refname == 'HEAD':
203-
return self.checkout_head(strategy)
254+
return self.checkout_head(**kwargs)
204255

205256
# Case 3: Reference
206257
if type(refname) is Reference:
@@ -211,7 +262,7 @@ def checkout(self, refname=None, strategy=GIT_CHECKOUT_SAFE_CREATE):
211262

212263
oid = reference.resolve().target
213264
treeish = self[oid]
214-
self.checkout_tree(treeish, strategy)
265+
self.checkout_tree(treeish, **kwargs)
215266
self.head = refname
216267

217268

src/repository.c

-76
Original file line numberDiff line numberDiff line change
@@ -1288,79 +1288,6 @@ Repository__pointer__get__(Repository *self)
12881288
return PyBytes_FromStringAndSize((char *) &self->repo, sizeof(git_repository *));
12891289
}
12901290

1291-
PyDoc_STRVAR(Repository_checkout_head__doc__,
1292-
"checkout_head(strategy)\n"
1293-
"\n"
1294-
"Checkout the head using the given strategy.");
1295-
1296-
PyObject *
1297-
Repository_checkout_head(Repository *self, PyObject *args)
1298-
{
1299-
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
1300-
unsigned int strategy;
1301-
int err;
1302-
1303-
if (!PyArg_ParseTuple(args, "I", &strategy))
1304-
return NULL;
1305-
1306-
opts.checkout_strategy = strategy;
1307-
err = git_checkout_head(self->repo, &opts);
1308-
if (err < 0)
1309-
return Error_set(err);
1310-
1311-
Py_RETURN_NONE;
1312-
}
1313-
1314-
1315-
PyDoc_STRVAR(Repository_checkout_index__doc__,
1316-
"checkout_index(strategy)\n"
1317-
"\n"
1318-
"Checkout the index using the given strategy.");
1319-
1320-
PyObject *
1321-
Repository_checkout_index(Repository *self, PyObject *args)
1322-
{
1323-
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
1324-
unsigned int strategy;
1325-
int err;
1326-
1327-
if (!PyArg_ParseTuple(args, "I", &strategy))
1328-
return NULL;
1329-
1330-
opts.checkout_strategy = strategy;
1331-
err = git_checkout_index(self->repo, NULL, &opts);
1332-
if (err < 0)
1333-
return Error_set(err);
1334-
1335-
Py_RETURN_NONE;
1336-
}
1337-
1338-
1339-
PyDoc_STRVAR(Repository_checkout_tree__doc__,
1340-
"checkout_tree(treeish, strategy)\n"
1341-
"\n"
1342-
"Checkout the given tree, commit or tag, using the given strategy.");
1343-
1344-
PyObject *
1345-
Repository_checkout_tree(Repository *self, PyObject *args)
1346-
{
1347-
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
1348-
unsigned int strategy;
1349-
Object *py_object;
1350-
int err;
1351-
1352-
if (!PyArg_ParseTuple(args, "O!I", &ObjectType, &py_object, &strategy))
1353-
return NULL;
1354-
1355-
opts.checkout_strategy = strategy;
1356-
err = git_checkout_tree(self->repo, py_object->obj, &opts);
1357-
if (err < 0)
1358-
return Error_set(err);
1359-
1360-
Py_RETURN_NONE;
1361-
}
1362-
1363-
13641291
PyDoc_STRVAR(Repository_notes__doc__, "");
13651292

13661293
PyObject *
@@ -1570,9 +1497,6 @@ PyMethodDef Repository_methods[] = {
15701497
METHOD(Repository, revparse_single, METH_O),
15711498
METHOD(Repository, status, METH_NOARGS),
15721499
METHOD(Repository, status_file, METH_O),
1573-
METHOD(Repository, checkout_head, METH_VARARGS),
1574-
METHOD(Repository, checkout_index, METH_VARARGS),
1575-
METHOD(Repository, checkout_tree, METH_VARARGS),
15761500
METHOD(Repository, notes, METH_VARARGS),
15771501
METHOD(Repository, create_note, METH_VARARGS),
15781502
METHOD(Repository, lookup_note, METH_VARARGS),

test/test_repository.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def test_checkout_ref(self):
213213
head = self.repo.head
214214
head = self.repo[head.target]
215215
self.assertTrue('new' not in head.tree)
216-
self.repo.checkout(ref_i18n, pygit2.GIT_CHECKOUT_FORCE)
216+
self.repo.checkout(ref_i18n, strategy=pygit2.GIT_CHECKOUT_FORCE)
217217

218218
head = self.repo.head
219219
head = self.repo[head.target]
@@ -243,7 +243,7 @@ def test_checkout_head(self):
243243
self.assertTrue('bye.txt' in self.repo.status())
244244

245245
# checkout from head will reset index as well
246-
self.repo.checkout('HEAD', pygit2.GIT_CHECKOUT_FORCE)
246+
self.repo.checkout('HEAD', strategy=pygit2.GIT_CHECKOUT_FORCE)
247247
self.assertTrue('bye.txt' not in self.repo.status())
248248

249249
def test_merge_base(self):

0 commit comments

Comments
 (0)