Merge remote-tracking branch 'cholin/features/checkout'
Conflicts: src/pygit2.c
This commit is contained in:
21
src/pygit2.c
21
src/pygit2.c
@@ -407,6 +407,27 @@ moduleinit(PyObject* m)
|
|||||||
PyModule_AddIntConstant(m, "LIBGIT2_VER_REVISION", LIBGIT2_VER_REVISION);
|
PyModule_AddIntConstant(m, "LIBGIT2_VER_REVISION", LIBGIT2_VER_REVISION);
|
||||||
PyModule_AddStringConstant(m, "LIBGIT2_VERSION", LIBGIT2_VERSION);
|
PyModule_AddStringConstant(m, "LIBGIT2_VERSION", LIBGIT2_VERSION);
|
||||||
|
|
||||||
|
/* Different checkout strategies */
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_NONE", GIT_CHECKOUT_NONE);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_SAFE", GIT_CHECKOUT_SAFE);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_SAFE_CREATE",
|
||||||
|
GIT_CHECKOUT_SAFE_CREATE);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_FORCE", GIT_CHECKOUT_FORCE);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_ALLOW_CONFLICTS",
|
||||||
|
GIT_CHECKOUT_ALLOW_CONFLICTS);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_REMOVE_UNTRACKED",
|
||||||
|
GIT_CHECKOUT_REMOVE_UNTRACKED);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_REMOVE_IGNORED",
|
||||||
|
GIT_CHECKOUT_REMOVE_IGNORED);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_UPDATE_ONLY",
|
||||||
|
GIT_CHECKOUT_UPDATE_ONLY);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_DONT_UPDATE_INDEX",
|
||||||
|
GIT_CHECKOUT_DONT_UPDATE_INDEX);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_NO_REFRESH",
|
||||||
|
GIT_CHECKOUT_NO_REFRESH);
|
||||||
|
PyModule_AddIntConstant(m, "GIT_CHECKOUT_DISABLE_PATHSPEC_MATC",
|
||||||
|
GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -184,7 +184,7 @@ PyDoc_STRVAR(Remote_fetch__doc__,
|
|||||||
PyObject *
|
PyObject *
|
||||||
Remote_fetch(Remote *self, PyObject *args)
|
Remote_fetch(Remote *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject* py_stats;
|
PyObject* py_stats = NULL;
|
||||||
const git_transfer_progress *stats;
|
const git_transfer_progress *stats;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ extern PyTypeObject TreeBuilderType;
|
|||||||
extern PyTypeObject ConfigType;
|
extern PyTypeObject ConfigType;
|
||||||
extern PyTypeObject DiffType;
|
extern PyTypeObject DiffType;
|
||||||
extern PyTypeObject RemoteType;
|
extern PyTypeObject RemoteType;
|
||||||
|
extern PyTypeObject ReferenceType;
|
||||||
|
|
||||||
git_otype
|
git_otype
|
||||||
int_to_loose_object_type(int type_id)
|
int_to_loose_object_type(int type_id)
|
||||||
@@ -1066,6 +1067,53 @@ Repository_remotes__get__(Repository *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyDoc_STRVAR(Repository_checkout__doc__,
|
||||||
|
"checkout([strategy:int, reference:Reference])\n"
|
||||||
|
"\n"
|
||||||
|
"Checks out a tree by a given reference and modifies the HEAD pointer\n"
|
||||||
|
"Standard checkout strategy is pygit2.GIT_CHECKOUT_SAFE_CREATE\n"
|
||||||
|
"If no reference is given, checkout will use HEAD instead.");
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
Repository_checkout(Repository *self, PyObject *args, PyObject *kw)
|
||||||
|
{
|
||||||
|
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||||
|
unsigned int strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
|
Reference* ref = NULL;
|
||||||
|
git_object* object;
|
||||||
|
const git_oid* id;
|
||||||
|
int err, head = 0;
|
||||||
|
|
||||||
|
static char *kwlist[] = {"strategy", "reference", "head", NULL};
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kw, "|IO!i", kwlist,
|
||||||
|
&strategy, &ReferenceType, &ref, &head))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (ref != NULL) { // checkout from treeish
|
||||||
|
id = git_reference_target(ref->reference);
|
||||||
|
err = git_object_lookup(&object, self->repo, id, GIT_OBJ_COMMIT);
|
||||||
|
if(err == GIT_OK) {
|
||||||
|
opts.checkout_strategy = strategy;
|
||||||
|
err = git_checkout_tree(self->repo, object, &opts);
|
||||||
|
if (err == GIT_OK) {
|
||||||
|
err = git_repository_set_head(self->repo,
|
||||||
|
git_reference_name(ref->reference));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // checkout from head / index
|
||||||
|
opts.checkout_strategy = strategy;
|
||||||
|
err = (!head) ? git_checkout_index(self->repo, NULL, &opts) :
|
||||||
|
git_checkout_head(self->repo, &opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err < 0)
|
||||||
|
return Error_set(err);
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyMethodDef Repository_methods[] = {
|
PyMethodDef Repository_methods[] = {
|
||||||
METHOD(Repository, create_blob, METH_VARARGS),
|
METHOD(Repository, create_blob, METH_VARARGS),
|
||||||
METHOD(Repository, create_blob_fromfile, METH_VARARGS),
|
METHOD(Repository, create_blob_fromfile, METH_VARARGS),
|
||||||
@@ -1083,6 +1131,7 @@ PyMethodDef Repository_methods[] = {
|
|||||||
METHOD(Repository, status, METH_NOARGS),
|
METHOD(Repository, status, METH_NOARGS),
|
||||||
METHOD(Repository, status_file, METH_O),
|
METHOD(Repository, status_file, METH_O),
|
||||||
METHOD(Repository, create_remote, METH_VARARGS),
|
METHOD(Repository, create_remote, METH_VARARGS),
|
||||||
|
METHOD(Repository, checkout, METH_VARARGS|METH_KEYWORDS),
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Binary file not shown.
@@ -184,6 +184,45 @@ class RepositoryTest_II(utils.RepoTestCase):
|
|||||||
expected = realpath(join(self._temp_dir, 'testrepo'))
|
expected = realpath(join(self._temp_dir, 'testrepo'))
|
||||||
self.assertEqual(directory, expected)
|
self.assertEqual(directory, expected)
|
||||||
|
|
||||||
|
def test_checkout_ref(self):
|
||||||
|
ref_i18n = self.repo.lookup_reference('refs/heads/i18n')
|
||||||
|
|
||||||
|
# checkout i18n with conflicts and default strategy should
|
||||||
|
# not be possible
|
||||||
|
self.assertRaises(pygit2.GitError,
|
||||||
|
lambda: self.repo.checkout(reference=ref_i18n))
|
||||||
|
|
||||||
|
# checkout i18n with GIT_CHECKOUT_FORCE
|
||||||
|
self.assertTrue('new' not in self.repo.head.tree)
|
||||||
|
self.repo.checkout(pygit2.GIT_CHECKOUT_FORCE, ref_i18n)
|
||||||
|
self.assertEqual(self.repo.head.hex, self.repo[ref_i18n.target].hex)
|
||||||
|
self.assertTrue('new' in self.repo.head.tree)
|
||||||
|
self.assertTrue('bye.txt' not in self.repo.status())
|
||||||
|
|
||||||
|
def test_checkout_index(self):
|
||||||
|
# some changes to working dir
|
||||||
|
with open(os.path.join(self.repo.workdir, 'hello.txt'), 'w') as f:
|
||||||
|
f.write('new content')
|
||||||
|
|
||||||
|
# checkout index
|
||||||
|
self.assertTrue('hello.txt' in self.repo.status())
|
||||||
|
self.repo.checkout(pygit2.GIT_CHECKOUT_FORCE)
|
||||||
|
self.assertTrue('hello.txt' not in self.repo.status())
|
||||||
|
|
||||||
|
def test_checkout_head(self):
|
||||||
|
# some changes to the index
|
||||||
|
with open(os.path.join(self.repo.workdir, 'bye.txt'), 'w') as f:
|
||||||
|
f.write('new content')
|
||||||
|
self.repo.index.add('bye.txt')
|
||||||
|
|
||||||
|
# checkout from index should not change anything
|
||||||
|
self.assertTrue('bye.txt' in self.repo.status())
|
||||||
|
self.repo.checkout(pygit2.GIT_CHECKOUT_FORCE)
|
||||||
|
self.assertTrue('bye.txt' in self.repo.status())
|
||||||
|
|
||||||
|
# checkout from head will reset index as well
|
||||||
|
self.repo.checkout(pygit2.GIT_CHECKOUT_FORCE, head=True)
|
||||||
|
self.assertTrue('bye.txt' not in self.repo.status())
|
||||||
|
|
||||||
class NewRepositoryTest(utils.NoRepoTestCase):
|
class NewRepositoryTest(utils.NoRepoTestCase):
|
||||||
def test_new_repo(self):
|
def test_new_repo(self):
|
||||||
|
@@ -44,6 +44,9 @@ log = [
|
|||||||
'acecd5ea2924a4b900e7e149496e1f4b57976e51']
|
'acecd5ea2924a4b900e7e149496e1f4b57976e51']
|
||||||
|
|
||||||
REVLOGS = [
|
REVLOGS = [
|
||||||
|
('Nico von Geyso','checkout: moving from i18n to master'),
|
||||||
|
('Nico von Geyso','commit: added bye.txt and new'),
|
||||||
|
('Nico von Geyso','checkout: moving from master to i18n'),
|
||||||
('J. David Ibañez', 'merge i18n: Merge made by recursive.'),
|
('J. David Ibañez', 'merge i18n: Merge made by recursive.'),
|
||||||
('J. David Ibañez', 'commit: Add .gitignore file'),
|
('J. David Ibañez', 'commit: Add .gitignore file'),
|
||||||
('J. David Ibañez', 'checkout: moving from i18n to master'),
|
('J. David Ibañez', 'checkout: moving from i18n to master'),
|
||||||
|
Reference in New Issue
Block a user