checkout: move the code to cffi

As part of this, make the strategy part of **kwargs, in preparation for
supporting more options.
This commit is contained in:
Carlos Martín Nieto
2014-07-11 13:47:24 +02:00
parent d2a62c5268
commit af38211d0c
4 changed files with 64 additions and 83 deletions

View File

@@ -3,6 +3,7 @@ typedef ... git_remote;
typedef ... git_refspec; typedef ... git_refspec;
typedef ... git_push; typedef ... git_push;
typedef ... git_cred; typedef ... git_cred;
typedef ... git_object;
typedef ... git_tree; typedef ... git_tree;
typedef ... git_signature; typedef ... git_signature;
typedef ... git_index; typedef ... git_index;
@@ -309,6 +310,11 @@ typedef enum {
GIT_CLONE_LOCAL_NO_LINKS, GIT_CLONE_LOCAL_NO_LINKS,
} git_clone_local_t; } git_clone_local_t;
int git_checkout_init_options(git_checkout_options *opts, unsigned int version);
int git_checkout_tree(git_repository *repo, const git_object *treeish, const git_checkout_options *opts);
int git_checkout_head(git_repository *repo, const git_checkout_options *opts);
int git_checkout_index(git_repository *repo, git_index *index, const git_checkout_options *opts);
/* /*
* git_clone * git_clone
*/ */

View File

@@ -176,11 +176,52 @@ class Repository(_Repository):
return self.create_reference_symbolic(name, target, force) return self.create_reference_symbolic(name, target, force)
# #
# Checkout # Checkout
# #
def checkout(self, refname=None, strategy=GIT_CHECKOUT_SAFE_CREATE): @staticmethod
def _checkout_args_to_options(**kwargs):
# Create the options struct to pass
copts = ffi.new('git_checkout_options *')
check_error(C.git_checkout_init_options(copts, 1))
# pygit2's default is SAFE_CREATE
copts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE
# and go through the arguments to see what the user wanted
for k, v in kwargs.iteritems():
if k == 'strategy':
copts.checkout_strategy = v
return copts
def checkout_head(self, **kwargs):
"""Checkout HEAD
For arguments, see Repository.checkout().
"""
copts = Repository._checkout_args_to_options(**kwargs)
check_error(C.git_checkout_head(self._repo, copts))
def checkout_index(self, **kwargs):
"""Checkout the repository's index
For arguments, see Repository.checkout().
"""
copts = Repository._checkout_args_to_options(**kwargs)
check_error(C.git_checkout_index(self._repo, ffi.NULL, copts))
def checkout_tree(self, treeish, **kwargs):
"""Checkout the given treeish
For arguments, see Repository.checkout().
"""
copts = Repository._checkout_args_to_options(**kwargs)
cptr = ffi.new('git_object **')
ffi.buffer(cptr)[:] = treeish._pointer[:]
check_error(C.git_checkout_tree(self._repo, cptr[0], copts))
def checkout(self, refname=None, **kwargs):
""" """
Checkout the given reference using the given strategy, and update Checkout the given reference using the given strategy, and update
the HEAD. the HEAD.
@@ -193,14 +234,24 @@ class Repository(_Repository):
If no reference is given, checkout from the index. If no reference is given, checkout from the index.
Arguments:
:param str refname: The reference to checkout. After checkout,
the current branch will be switched to this one.
:param int strategy: A ``GIT_CHECKOUT_`` value. The default is
``GIT_CHECKOUT_SAFE_CREATE``.
""" """
# Case 1: Checkout index # Case 1: Checkout index
if refname is None: if refname is None:
return self.checkout_index(strategy) return self.checkout_index(**kwargs)
# Case 2: Checkout head # Case 2: Checkout head
if refname == 'HEAD': if refname == 'HEAD':
return self.checkout_head(strategy) return self.checkout_head(**kwargs)
# Case 3: Reference # Case 3: Reference
if type(refname) is Reference: if type(refname) is Reference:
@@ -211,7 +262,7 @@ class Repository(_Repository):
oid = reference.resolve().target oid = reference.resolve().target
treeish = self[oid] treeish = self[oid]
self.checkout_tree(treeish, strategy) self.checkout_tree(treeish, **kwargs)
self.head = refname self.head = refname

View File

@@ -1288,79 +1288,6 @@ Repository__pointer__get__(Repository *self)
return PyBytes_FromStringAndSize((char *) &self->repo, sizeof(git_repository *)); return PyBytes_FromStringAndSize((char *) &self->repo, sizeof(git_repository *));
} }
PyDoc_STRVAR(Repository_checkout_head__doc__,
"checkout_head(strategy)\n"
"\n"
"Checkout the head using the given strategy.");
PyObject *
Repository_checkout_head(Repository *self, PyObject *args)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
unsigned int strategy;
int err;
if (!PyArg_ParseTuple(args, "I", &strategy))
return NULL;
opts.checkout_strategy = strategy;
err = git_checkout_head(self->repo, &opts);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Repository_checkout_index__doc__,
"checkout_index(strategy)\n"
"\n"
"Checkout the index using the given strategy.");
PyObject *
Repository_checkout_index(Repository *self, PyObject *args)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
unsigned int strategy;
int err;
if (!PyArg_ParseTuple(args, "I", &strategy))
return NULL;
opts.checkout_strategy = strategy;
err = git_checkout_index(self->repo, NULL, &opts);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Repository_checkout_tree__doc__,
"checkout_tree(treeish, strategy)\n"
"\n"
"Checkout the given tree, commit or tag, using the given strategy.");
PyObject *
Repository_checkout_tree(Repository *self, PyObject *args)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
unsigned int strategy;
Object *py_object;
int err;
if (!PyArg_ParseTuple(args, "O!I", &ObjectType, &py_object, &strategy))
return NULL;
opts.checkout_strategy = strategy;
err = git_checkout_tree(self->repo, py_object->obj, &opts);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
PyDoc_STRVAR(Repository_notes__doc__, ""); PyDoc_STRVAR(Repository_notes__doc__, "");
PyObject * PyObject *
@@ -1570,9 +1497,6 @@ PyMethodDef Repository_methods[] = {
METHOD(Repository, revparse_single, METH_O), METHOD(Repository, revparse_single, METH_O),
METHOD(Repository, status, METH_NOARGS), METHOD(Repository, status, METH_NOARGS),
METHOD(Repository, status_file, METH_O), METHOD(Repository, status_file, METH_O),
METHOD(Repository, checkout_head, METH_VARARGS),
METHOD(Repository, checkout_index, METH_VARARGS),
METHOD(Repository, checkout_tree, METH_VARARGS),
METHOD(Repository, notes, METH_VARARGS), METHOD(Repository, notes, METH_VARARGS),
METHOD(Repository, create_note, METH_VARARGS), METHOD(Repository, create_note, METH_VARARGS),
METHOD(Repository, lookup_note, METH_VARARGS), METHOD(Repository, lookup_note, METH_VARARGS),

View File

@@ -213,7 +213,7 @@ class RepositoryTest_II(utils.RepoTestCase):
head = self.repo.head head = self.repo.head
head = self.repo[head.target] head = self.repo[head.target]
self.assertTrue('new' not in head.tree) self.assertTrue('new' not in head.tree)
self.repo.checkout(ref_i18n, pygit2.GIT_CHECKOUT_FORCE) self.repo.checkout(ref_i18n, strategy=pygit2.GIT_CHECKOUT_FORCE)
head = self.repo.head head = self.repo.head
head = self.repo[head.target] head = self.repo[head.target]
@@ -243,7 +243,7 @@ class RepositoryTest_II(utils.RepoTestCase):
self.assertTrue('bye.txt' in self.repo.status()) self.assertTrue('bye.txt' in self.repo.status())
# checkout from head will reset index as well # checkout from head will reset index as well
self.repo.checkout('HEAD', pygit2.GIT_CHECKOUT_FORCE) self.repo.checkout('HEAD', strategy=pygit2.GIT_CHECKOUT_FORCE)
self.assertTrue('bye.txt' not in self.repo.status()) self.assertTrue('bye.txt' not in self.repo.status())
def test_merge_base(self): def test_merge_base(self):