Adjust to libgit2 development branch

This wraps the previous functionality, though there are some iterator
changes we might still want to bring over.
This commit is contained in:
Carlos Martín Nieto
2013-10-30 08:57:17 +01:00
parent c267891d1f
commit b7e906eee9
12 changed files with 87 additions and 116 deletions

View File

@@ -49,9 +49,8 @@ def init_repository(path, bare=False):
def clone_repository( def clone_repository(
url, path, bare=False, remote_name="origin", url, path, bare=False, ignore_cert_errors=False,
push_url=None, fetch_spec=None, remote_name="origin", checkout_branch=None):
push_spec=None, checkout_branch=None):
""" """
Clones a new Git repository from *url* in the given *path*. Clones a new Git repository from *url* in the given *path*.
@@ -60,15 +59,6 @@ def clone_repository(
**remote_name** is the name given to the "origin" remote. **remote_name** is the name given to the "origin" remote.
The default is "origin". The default is "origin".
**push_url** is a URL to be used for pushing.
None means use the *url* parameter.
**fetch_spec** defines the the default fetch spec.
None results in the same behavior as *GIT_REMOTE_DEFAULT_FETCH*.
**push_spec** is the fetch specification to be used for pushing.
None means use the same spec as for *fetch_spec*.
**checkout_branch** gives the name of the branch to checkout. **checkout_branch** gives the name of the branch to checkout.
None means use the remote's *HEAD*. None means use the remote's *HEAD*.
@@ -83,6 +73,5 @@ def clone_repository(
""" """
_pygit2.clone_repository( _pygit2.clone_repository(
url, path, bare, remote_name, push_url, url, path, bare, ignore_cert_errors, remote_name, checkout_branch)
fetch_spec, push_spec, checkout_branch)
return Repository(path) return Repository(path)

View File

@@ -336,55 +336,44 @@ PyDoc_STRVAR(Config_get_multivar__doc__,
"parameter is expected to be a regular expression to filter the variables\n" "parameter is expected to be a regular expression to filter the variables\n"
"we're interested in."); "we're interested in.");
int
Config_get_multivar_fn_wrapper(const git_config_entry *value, void *data)
{
PyObject *item;
item = to_unicode(value->value, NULL, NULL);
if (item == NULL)
/* FIXME Right now there is no way to forward errors through the
* libgit2 API, open an issue or pull-request to libgit2.
*
* See libgit2/src/config_file.c:443 (config_get_multivar).
* Comment says "early termination by the user is not an error".
* That's wrong.
*/
return -2;
PyList_Append((PyObject *)data, item);
Py_CLEAR(item);
return 0;
}
PyObject * PyObject *
Config_get_multivar(Config *self, PyObject *args) Config_get_multivar(Config *self, PyObject *args)
{ {
int err; int err;
PyObject *list; PyObject *list;
Py_ssize_t size;
const char *name = NULL; const char *name = NULL;
const char *regex = NULL; const char *regex = NULL;
git_config_iterator *iter;
git_config_entry *entry;
if (!PyArg_ParseTuple(args, "s|s", &name, &regex)) if (!PyArg_ParseTuple(args, "s|s", &name, &regex))
return NULL; return NULL;
list = PyList_New(0); list = PyList_New(0);
err = git_config_get_multivar(self->config, name, regex, err = git_config_multivar_iterator_new(&iter, self->config, name, regex);
Config_get_multivar_fn_wrapper, if (err < 0)
(void *)list); return Error_set(err);
if (err < 0) { while ((err = git_config_next(&entry, iter)) == 0) {
/* XXX The return value of git_config_get_multivar is not reliable, PyObject *item;
* see https://github.com/libgit2/libgit2/pull/1712
* Once libgit2 0.20 is released, we will remove this test. */
if (err == GIT_ENOTFOUND && PyList_Size(list) != 0)
return list;
Py_CLEAR(list); item = to_unicode(entry->value, NULL, NULL);
return Error_set(err); if (item == NULL) {
git_config_iterator_free(iter);
return NULL;
}
PyList_Append(list, item);
Py_CLEAR(item);
} }
git_config_iterator_free(iter);
if (err == GIT_ITEROVER)
err = 0;
if (err < 0)
return Error_set(err);
return list; return list;
} }

View File

@@ -43,7 +43,7 @@ extern PyTypeObject HunkType;
PyTypeObject PatchType; PyTypeObject PatchType;
PyObject* PyObject*
wrap_diff(git_diff_list *diff, Repository *repo) wrap_diff(git_diff *diff, Repository *repo)
{ {
Diff *py_diff; Diff *py_diff;
@@ -58,23 +58,24 @@ wrap_diff(git_diff_list *diff, Repository *repo)
} }
PyObject* PyObject*
diff_get_patch_byindex(git_diff_list* list, size_t idx) diff_get_patch_byindex(git_diff* diff, size_t idx)
{ {
const git_diff_delta* delta; const git_diff_delta* delta;
const git_diff_range* range; const git_diff_hunk *hunk;
git_diff_patch* patch = NULL; const git_diff_line *line;
size_t i, j, hunk_amounts, lines_in_hunk, line_len, header_len, additions, deletions; git_patch* patch = NULL;
const char* line, *header; size_t i, j, hunk_amounts, lines_in_hunk, additions, deletions;
char line_origin;
int err; int err;
Hunk *py_hunk = NULL; Hunk *py_hunk = NULL;
Patch *py_patch = NULL; Patch *py_patch = NULL;
PyObject *py_line_origin=NULL, *py_line=NULL; PyObject *py_line_origin=NULL, *py_line=NULL;
err = git_diff_get_patch(&patch, &delta, list, idx); err = git_patch_from_diff(&patch, diff, idx);
if (err < 0) if (err < 0)
return Error_set(err); return Error_set(err);
delta = git_patch_get_delta(patch);
py_patch = PyObject_New(Patch, &PatchType); py_patch = PyObject_New(Patch, &PatchType);
if (py_patch != NULL) { if (py_patch != NULL) {
py_patch->old_file_path = delta->old_file.path; py_patch->old_file_path = delta->old_file.path;
@@ -85,36 +86,34 @@ diff_get_patch_byindex(git_diff_list* list, size_t idx)
py_patch->old_oid = git_oid_allocfmt(&delta->old_file.oid); py_patch->old_oid = git_oid_allocfmt(&delta->old_file.oid);
py_patch->new_oid = git_oid_allocfmt(&delta->new_file.oid); py_patch->new_oid = git_oid_allocfmt(&delta->new_file.oid);
git_diff_patch_line_stats(NULL, &additions, &deletions, patch); git_patch_line_stats(NULL, &additions, &deletions, patch);
py_patch->additions = additions; py_patch->additions = additions;
py_patch->deletions = deletions; py_patch->deletions = deletions;
hunk_amounts = git_diff_patch_num_hunks(patch); hunk_amounts = git_patch_num_hunks(patch);
py_patch->hunks = PyList_New(hunk_amounts); py_patch->hunks = PyList_New(hunk_amounts);
for (i=0; i < hunk_amounts; ++i) { for (i=0; i < hunk_amounts; ++i) {
err = git_diff_patch_get_hunk(&range, &header, &header_len, err = git_patch_get_hunk(&hunk, &lines_in_hunk, patch, i);
&lines_in_hunk, patch, i);
if (err < 0) if (err < 0)
goto cleanup; goto cleanup;
py_hunk = PyObject_New(Hunk, &HunkType); py_hunk = PyObject_New(Hunk, &HunkType);
if (py_hunk != NULL) { if (py_hunk != NULL) {
py_hunk->old_start = range->old_start; py_hunk->old_start = hunk->old_start;
py_hunk->old_lines = range->old_lines; py_hunk->old_lines = hunk->old_lines;
py_hunk->new_start = range->new_start; py_hunk->new_start = hunk->new_start;
py_hunk->new_lines = range->new_lines; py_hunk->new_lines = hunk->new_lines;
py_hunk->lines = PyList_New(lines_in_hunk); py_hunk->lines = PyList_New(lines_in_hunk);
for (j=0; j < lines_in_hunk; ++j) { for (j=0; j < lines_in_hunk; ++j) {
err = git_diff_patch_get_line_in_hunk(&line_origin, err = git_patch_get_line_in_hunk(&line, patch, i, j);
&line, &line_len, NULL, NULL, patch, i, j);
if (err < 0) if (err < 0)
goto cleanup; goto cleanup;
py_line_origin = to_unicode_n(&line_origin, 1, NULL, NULL); py_line_origin = to_unicode_n(&line->origin, 1, NULL, NULL);
py_line = to_unicode_n(line, line_len, NULL, NULL); py_line = to_unicode_n(line->content, line->content_len, NULL, NULL);
PyList_SetItem(py_hunk->lines, j, PyList_SetItem(py_hunk->lines, j,
Py_BuildValue("OO", Py_BuildValue("OO",
py_line_origin, py_line_origin,
@@ -132,7 +131,7 @@ diff_get_patch_byindex(git_diff_list* list, size_t idx)
} }
cleanup: cleanup:
git_diff_patch_free(patch); git_patch_free(patch);
return (err < 0) ? Error_set(err) : (PyObject*) py_patch; return (err < 0) ? Error_set(err) : (PyObject*) py_patch;
} }
@@ -283,8 +282,7 @@ PyDoc_STRVAR(Diff_patch__doc__, "Patch diff string.");
PyObject * PyObject *
Diff_patch__get__(Diff *self) Diff_patch__get__(Diff *self)
{ {
const git_diff_delta* delta; git_patch* patch;
git_diff_patch* patch;
char **strings = NULL; char **strings = NULL;
char *buffer = NULL; char *buffer = NULL;
int err = GIT_ERROR; int err = GIT_ERROR;
@@ -295,16 +293,16 @@ Diff_patch__get__(Diff *self)
MALLOC(strings, num * sizeof(char*), cleanup); MALLOC(strings, num * sizeof(char*), cleanup);
for (i = 0, len = 1; i < num ; ++i) { for (i = 0, len = 1; i < num ; ++i) {
err = git_diff_get_patch(&patch, &delta, self->list, i); err = git_patch_from_diff(&patch, self->list, i);
if (err < 0) if (err < 0)
goto cleanup; goto cleanup;
err = git_diff_patch_to_str(&(strings[i]), patch); err = git_patch_to_str(&(strings[i]), patch);
if (err < 0) if (err < 0)
goto cleanup; goto cleanup;
len += strlen(strings[i]); len += strlen(strings[i]);
git_diff_patch_free(patch); git_patch_free(patch);
} }
CALLOC(buffer, (len + 1), sizeof(char), cleanup); CALLOC(buffer, (len + 1), sizeof(char), cleanup);
@@ -461,7 +459,7 @@ Diff_getitem(Diff *self, PyObject *value)
static void static void
Diff_dealloc(Diff *self) Diff_dealloc(Diff *self)
{ {
git_diff_list_free(self->list); git_diff_free(self->list);
Py_CLEAR(self->repo); Py_CLEAR(self->repo);
PyObject_Del(self); PyObject_Del(self);
} }

View File

@@ -41,6 +41,6 @@
PyObject* Diff_changes(Diff *self); PyObject* Diff_changes(Diff *self);
PyObject* Diff_patch(Diff *self); PyObject* Diff_patch(Diff *self);
PyObject* wrap_diff(git_diff_list *diff, Repository *repo); PyObject* wrap_diff(git_diff *diff, Repository *repo);
#endif #endif

View File

@@ -135,7 +135,7 @@ PyObject *
Index_diff_to_workdir(Index *self, PyObject *args) Index_diff_to_workdir(Index *self, PyObject *args)
{ {
git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff; git_diff *diff;
int err; int err;
if (!PyArg_ParseTuple(args, "|IHH", &opts.flags, &opts.context_lines, if (!PyArg_ParseTuple(args, "|IHH", &opts.flags, &opts.context_lines,
@@ -177,7 +177,7 @@ Index_diff_to_tree(Index *self, PyObject *args)
{ {
Repository *py_repo; Repository *py_repo;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff; git_diff *diff;
int err; int err;
Tree *py_tree = NULL; Tree *py_tree = NULL;

View File

@@ -99,8 +99,7 @@ init_repository(PyObject *self, PyObject *args) {
}; };
PyDoc_STRVAR(clone_repository__doc__, PyDoc_STRVAR(clone_repository__doc__,
"clone_repository(url, path, bare, remote_name, push_url," "clone_repository(url, path, bare, remote_name, checkout_branch)\n"
"fetch_spec, push_spec, checkout_branch)\n"
"\n" "\n"
"Clones a Git repository in the given url to the given path " "Clones a Git repository in the given url to the given path "
"with the specified options.\n" "with the specified options.\n"
@@ -115,14 +114,6 @@ PyDoc_STRVAR(clone_repository__doc__,
" If 'bare' is not 0, then a bare git repository will be created.\n" " If 'bare' is not 0, then a bare git repository will be created.\n"
"remote_name\n" "remote_name\n"
" The name given to the 'origin' remote. The default is 'origin'.\n" " The name given to the 'origin' remote. The default is 'origin'.\n"
"push_url\n"
" URL to be used for pushing.\n"
"fetch_spec\n"
" The fetch specification to be used for fetching. None results in "
"the same behavior as GIT_REMOTE_DEFAULT_FETCH.\n"
"push_spec\n"
" The fetch specification to be used for pushing. None means use the "
"same spec as for 'fetch_spec'\n"
"checkout_branch\n" "checkout_branch\n"
" The name of the branch to checkout. None means use the remote's " " The name of the branch to checkout. None means use the remote's "
"HEAD.\n"); "HEAD.\n");
@@ -133,22 +124,18 @@ clone_repository(PyObject *self, PyObject *args) {
git_repository *repo; git_repository *repo;
const char *url; const char *url;
const char *path; const char *path;
unsigned int bare; unsigned int bare, ignore_cert_errors;
const char *remote_name, *push_url, *fetch_spec; const char *remote_name, *checkout_branch;
const char *push_spec, *checkout_branch;
int err; int err;
git_clone_options opts = GIT_CLONE_OPTIONS_INIT; git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
if (!PyArg_ParseTuple(args, "zzIzzzzz", if (!PyArg_ParseTuple(args, "zzIIzz",
&url, &path, &bare, &remote_name, &push_url, &url, &path, &bare, &ignore_cert_errors, &remote_name, &checkout_branch))
&fetch_spec, &push_spec, &checkout_branch))
return NULL; return NULL;
opts.bare = bare; opts.bare = bare;
opts.ignore_cert_errors = ignore_cert_errors;
opts.remote_name = remote_name; opts.remote_name = remote_name;
opts.pushurl = push_url;
opts.fetch_spec = fetch_spec;
opts.push_spec = push_spec;
opts.checkout_branch = checkout_branch; opts.checkout_branch = checkout_branch;
err = git_clone(&repo, url, path, &opts); err = git_clone(&repo, url, path, &opts);
@@ -392,8 +379,8 @@ moduleinit(PyObject* m)
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_UNTRACKED_DIRS) ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_UNTRACKED_DIRS)
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_UNTRACKED_DIRS) ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_UNTRACKED_DIRS)
ADD_CONSTANT_INT(m, GIT_DIFF_DISABLE_PATHSPEC_MATCH) ADD_CONSTANT_INT(m, GIT_DIFF_DISABLE_PATHSPEC_MATCH)
ADD_CONSTANT_INT(m, GIT_DIFF_DELTAS_ARE_ICASE) ADD_CONSTANT_INT(m, GIT_DIFF_IGNORE_CASE)
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) ADD_CONSTANT_INT(m, GIT_DIFF_SHOW_UNTRACKED_CONTENT)
ADD_CONSTANT_INT(m, GIT_DIFF_SKIP_BINARY_CHECK) ADD_CONSTANT_INT(m, GIT_DIFF_SKIP_BINARY_CHECK)
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE) ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE)
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE_TREES) ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE_TREES)

View File

@@ -309,13 +309,19 @@ PyDoc_STRVAR(Reference_log__doc__,
PyObject * PyObject *
Reference_log(Reference *self) Reference_log(Reference *self)
{ {
int err;
RefLogIter *iter; RefLogIter *iter;
git_repository *repo;
CHECK_REFERENCE(self); CHECK_REFERENCE(self);
repo = git_reference_owner(self->reference);
iter = PyObject_New(RefLogIter, &RefLogIterType); iter = PyObject_New(RefLogIter, &RefLogIterType);
if (iter != NULL) { if (iter != NULL) {
git_reflog_read(&iter->reflog, self->reference); err = git_reflog_read(&iter->reflog, repo, git_reference_name(self->reference));
if (err < 0)
return Error_set(err);
iter->size = git_reflog_entrycount(iter->reflog); iter->size = git_reflog_entrycount(iter->reflog);
iter->i = 0; iter->i = 0;
} }
@@ -341,6 +347,7 @@ Reference_log_append(Reference *self, PyObject *args)
Signature *py_committer; Signature *py_committer;
PyObject *py_message = NULL; PyObject *py_message = NULL;
char *encoding = NULL; char *encoding = NULL;
git_repository *repo;
CHECK_REFERENCE(self); CHECK_REFERENCE(self);
@@ -366,7 +373,8 @@ Reference_log_append(Reference *self, PyObject *args)
} }
/* Go */ /* Go */
err = git_reflog_read(&reflog, self->reference); repo = git_reference_owner(self->reference);
err = git_reflog_read(&reflog, repo, git_reference_name(self->reference));
if (err < 0) { if (err < 0) {
free((void *)message); free((void *)message);
return NULL; return NULL;

View File

@@ -179,7 +179,7 @@ Remote_fetch(Remote *self, PyObject *args)
err = git_remote_connect(self->remote, GIT_DIRECTION_FETCH); err = git_remote_connect(self->remote, GIT_DIRECTION_FETCH);
if (err == GIT_OK) { if (err == GIT_OK) {
err = git_remote_download(self->remote, NULL, NULL); err = git_remote_download(self->remote);
if (err == GIT_OK) { if (err == GIT_OK) {
stats = git_remote_stats(self->remote); stats = git_remote_stats(self->remote);
py_stats = Py_BuildValue("{s:I,s:I,s:n}", py_stats = Py_BuildValue("{s:I,s:I,s:n}",

View File

@@ -208,14 +208,14 @@ Repository_head_is_detached__get__(Repository *self)
} }
PyDoc_STRVAR(Repository_head_is_orphaned__doc__, PyDoc_STRVAR(Repository_head_is_unborn__doc__,
"An orphan branch is one named from HEAD but which doesn't exist in the\n" "An unborn branch is one named from HEAD but which doesn't exist in the\n"
"refs namespace, because it doesn't have any commit to point to."); "refs namespace, because it doesn't have any commit to point to.");
PyObject * PyObject *
Repository_head_is_orphaned__get__(Repository *self) Repository_head_is_unborn__get__(Repository *self)
{ {
if (git_repository_head_orphan(self->repo) > 0) if (git_repository_head_unborn(self->repo) > 0)
Py_RETURN_TRUE; Py_RETURN_TRUE;
Py_RETURN_FALSE; Py_RETURN_FALSE;
@@ -430,9 +430,9 @@ Repository_write(Repository *self, PyObject *args)
if (err < 0) if (err < 0)
return Error_set(err); return Error_set(err);
stream->write(stream, buffer, buflen); git_odb_stream_write(stream, buffer, buflen);
err = stream->finalize_write(&oid, stream); err = git_odb_stream_finalize_write(&oid, stream);
stream->free(stream); git_odb_stream_free(stream);
return git_oid_to_python(&oid); return git_oid_to_python(&oid);
} }
@@ -1480,7 +1480,7 @@ PyGetSetDef Repository_getseters[] = {
GETTER(Repository, path), GETTER(Repository, path),
GETSET(Repository, head), GETSET(Repository, head),
GETTER(Repository, head_is_detached), GETTER(Repository, head_is_detached),
GETTER(Repository, head_is_orphaned), GETTER(Repository, head_is_unborn),
GETTER(Repository, is_empty), GETTER(Repository, is_empty),
GETTER(Repository, is_bare), GETTER(Repository, is_bare),
GETTER(Repository, config), GETTER(Repository, config),

View File

@@ -290,7 +290,7 @@ PyObject *
Tree_diff_to_workdir(Tree *self, PyObject *args) Tree_diff_to_workdir(Tree *self, PyObject *args)
{ {
git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff; git_diff *diff;
Repository *py_repo; Repository *py_repo;
int err; int err;
@@ -328,7 +328,7 @@ PyObject *
Tree_diff_to_index(Tree *self, PyObject *args, PyObject *kwds) Tree_diff_to_index(Tree *self, PyObject *args, PyObject *kwds)
{ {
git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff; git_diff *diff;
Repository *py_repo; Repository *py_repo;
int err; int err;
@@ -373,7 +373,7 @@ PyObject *
Tree_diff_to_tree(Tree *self, PyObject *args, PyObject *kwds) Tree_diff_to_tree(Tree *self, PyObject *args, PyObject *kwds)
{ {
git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff; git_diff *diff;
git_tree *from, *to, *tmp; git_tree *from, *to, *tmp;
Repository *py_repo; Repository *py_repo;
int err, swap = 0; int err, swap = 0;

View File

@@ -95,7 +95,7 @@ typedef struct {
/* git _diff */ /* git _diff */
SIMPLE_TYPE(Diff, git_diff_list, list) SIMPLE_TYPE(Diff, git_diff, list)
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD

View File

@@ -65,7 +65,7 @@ class RepositoryTest(utils.BareRepoTestCase):
head = self.repo.head head = self.repo.head
self.assertEqual(HEAD_SHA, head.target.hex) self.assertEqual(HEAD_SHA, head.target.hex)
self.assertEqual(type(head), Reference) self.assertEqual(type(head), Reference)
self.assertFalse(self.repo.head_is_orphaned) self.assertFalse(self.repo.head_is_unborn)
self.assertFalse(self.repo.head_is_detached) self.assertFalse(self.repo.head_is_detached)
def test_read(self): def test_read(self):
@@ -294,7 +294,7 @@ class EmptyRepositoryTest(utils.EmptyRepoTestCase):
self.assertFalse(self.repo.is_bare) self.assertFalse(self.repo.is_bare)
def test_head(self): def test_head(self):
self.assertTrue(self.repo.head_is_orphaned) self.assertTrue(self.repo.head_is_unborn)
self.assertFalse(self.repo.head_is_detached) self.assertFalse(self.repo.head_is_detached)