Skip to content

Commit

Permalink
Adjust to libgit2 development branch
Browse files Browse the repository at this point in the history
This wraps the previous functionality, though there are some iterator
changes we might still want to bring over.
  • Loading branch information
carlosmn committed Nov 20, 2013
1 parent c267891 commit b7e906e
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 116 deletions.
17 changes: 3 additions & 14 deletions pygit2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ def init_repository(path, bare=False):


def clone_repository(
url, path, bare=False, remote_name="origin",
push_url=None, fetch_spec=None,
push_spec=None, checkout_branch=None):
url, path, bare=False, ignore_cert_errors=False,
remote_name="origin", checkout_branch=None):
"""
Clones a new Git repository from *url* in the given *path*.
Expand All @@ -60,15 +59,6 @@ def clone_repository(
**remote_name** is the name given to the "origin" remote.
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.
None means use the remote's *HEAD*.
Expand All @@ -83,6 +73,5 @@ def clone_repository(
"""

_pygit2.clone_repository(
url, path, bare, remote_name, push_url,
fetch_spec, push_spec, checkout_branch)
url, path, bare, ignore_cert_errors, remote_name, checkout_branch)
return Repository(path)
55 changes: 22 additions & 33 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,55 +336,44 @@ PyDoc_STRVAR(Config_get_multivar__doc__,
"parameter is expected to be a regular expression to filter the variables\n"
"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 *
Config_get_multivar(Config *self, PyObject *args)
{
int err;
PyObject *list;
Py_ssize_t size;
const char *name = NULL;
const char *regex = NULL;
git_config_iterator *iter;
git_config_entry *entry;

if (!PyArg_ParseTuple(args, "s|s", &name, &regex))
return NULL;

list = PyList_New(0);
err = git_config_get_multivar(self->config, name, regex,
Config_get_multivar_fn_wrapper,
(void *)list);
err = git_config_multivar_iterator_new(&iter, self->config, name, regex);
if (err < 0)
return Error_set(err);

if (err < 0) {
/* XXX The return value of git_config_get_multivar is not reliable,
* 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;
while ((err = git_config_next(&entry, iter)) == 0) {
PyObject *item;

Py_CLEAR(list);
return Error_set(err);
item = to_unicode(entry->value, NULL, NULL);
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;
}

Expand Down
54 changes: 26 additions & 28 deletions src/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ extern PyTypeObject HunkType;
PyTypeObject PatchType;

PyObject*
wrap_diff(git_diff_list *diff, Repository *repo)
wrap_diff(git_diff *diff, Repository *repo)
{
Diff *py_diff;

Expand All @@ -58,23 +58,24 @@ wrap_diff(git_diff_list *diff, Repository *repo)
}

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_range* range;
git_diff_patch* patch = NULL;
size_t i, j, hunk_amounts, lines_in_hunk, line_len, header_len, additions, deletions;
const char* line, *header;
char line_origin;
const git_diff_hunk *hunk;
const git_diff_line *line;
git_patch* patch = NULL;
size_t i, j, hunk_amounts, lines_in_hunk, additions, deletions;
int err;
Hunk *py_hunk = NULL;
Patch *py_patch = NULL;
PyObject *py_line_origin=NULL, *py_line=NULL;

err = git_diff_get_patch(&patch, &delta, list, idx);
if (err < 0)
err = git_patch_from_diff(&patch, diff, idx);
if (err < 0)
return Error_set(err);

delta = git_patch_get_delta(patch);

py_patch = PyObject_New(Patch, &PatchType);
if (py_patch != NULL) {
py_patch->old_file_path = delta->old_file.path;
Expand All @@ -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->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->deletions = deletions;

hunk_amounts = git_diff_patch_num_hunks(patch);
hunk_amounts = git_patch_num_hunks(patch);
py_patch->hunks = PyList_New(hunk_amounts);
for (i=0; i < hunk_amounts; ++i) {
err = git_diff_patch_get_hunk(&range, &header, &header_len,
&lines_in_hunk, patch, i);
err = git_patch_get_hunk(&hunk, &lines_in_hunk, patch, i);

if (err < 0)
goto cleanup;

py_hunk = PyObject_New(Hunk, &HunkType);
if (py_hunk != NULL) {
py_hunk->old_start = range->old_start;
py_hunk->old_lines = range->old_lines;
py_hunk->new_start = range->new_start;
py_hunk->new_lines = range->new_lines;
py_hunk->old_start = hunk->old_start;
py_hunk->old_lines = hunk->old_lines;
py_hunk->new_start = hunk->new_start;
py_hunk->new_lines = hunk->new_lines;

py_hunk->lines = PyList_New(lines_in_hunk);
for (j=0; j < lines_in_hunk; ++j) {
err = git_diff_patch_get_line_in_hunk(&line_origin,
&line, &line_len, NULL, NULL, patch, i, j);
err = git_patch_get_line_in_hunk(&line, patch, i, j);

if (err < 0)
goto cleanup;

py_line_origin = to_unicode_n(&line_origin, 1, NULL, NULL);
py_line = to_unicode_n(line, line_len, NULL, NULL);
py_line_origin = to_unicode_n(&line->origin, 1, NULL, NULL);
py_line = to_unicode_n(line->content, line->content_len, NULL, NULL);
PyList_SetItem(py_hunk->lines, j,
Py_BuildValue("OO",
py_line_origin,
Expand All @@ -132,7 +131,7 @@ diff_get_patch_byindex(git_diff_list* list, size_t idx)
}

cleanup:
git_diff_patch_free(patch);
git_patch_free(patch);

return (err < 0) ? Error_set(err) : (PyObject*) py_patch;
}
Expand Down Expand Up @@ -283,8 +282,7 @@ PyDoc_STRVAR(Diff_patch__doc__, "Patch diff string.");
PyObject *
Diff_patch__get__(Diff *self)
{
const git_diff_delta* delta;
git_diff_patch* patch;
git_patch* patch;
char **strings = NULL;
char *buffer = NULL;
int err = GIT_ERROR;
Expand All @@ -295,16 +293,16 @@ Diff_patch__get__(Diff *self)
MALLOC(strings, num * sizeof(char*), cleanup);

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)
goto cleanup;

err = git_diff_patch_to_str(&(strings[i]), patch);
err = git_patch_to_str(&(strings[i]), patch);
if (err < 0)
goto cleanup;

len += strlen(strings[i]);
git_diff_patch_free(patch);
git_patch_free(patch);
}

CALLOC(buffer, (len + 1), sizeof(char), cleanup);
Expand Down Expand Up @@ -461,7 +459,7 @@ Diff_getitem(Diff *self, PyObject *value)
static void
Diff_dealloc(Diff *self)
{
git_diff_list_free(self->list);
git_diff_free(self->list);
Py_CLEAR(self->repo);
PyObject_Del(self);
}
Expand Down
2 changes: 1 addition & 1 deletion src/diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@
PyObject* Diff_changes(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
4 changes: 2 additions & 2 deletions src/index.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ PyObject *
Index_diff_to_workdir(Index *self, PyObject *args)
{
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff;
git_diff *diff;
int err;

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

Tree *py_tree = NULL;
Expand Down
29 changes: 8 additions & 21 deletions src/pygit2.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ init_repository(PyObject *self, PyObject *args) {
};

PyDoc_STRVAR(clone_repository__doc__,
"clone_repository(url, path, bare, remote_name, push_url,"
"fetch_spec, push_spec, checkout_branch)\n"
"clone_repository(url, path, bare, remote_name, checkout_branch)\n"
"\n"
"Clones a Git repository in the given url to the given path "
"with the specified options.\n"
Expand All @@ -115,14 +114,6 @@ PyDoc_STRVAR(clone_repository__doc__,
" If 'bare' is not 0, then a bare git repository will be created.\n"
"remote_name\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"
" The name of the branch to checkout. None means use the remote's "
"HEAD.\n");
Expand All @@ -133,22 +124,18 @@ clone_repository(PyObject *self, PyObject *args) {
git_repository *repo;
const char *url;
const char *path;
unsigned int bare;
const char *remote_name, *push_url, *fetch_spec;
const char *push_spec, *checkout_branch;
unsigned int bare, ignore_cert_errors;
const char *remote_name, *checkout_branch;
int err;
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;

if (!PyArg_ParseTuple(args, "zzIzzzzz",
&url, &path, &bare, &remote_name, &push_url,
&fetch_spec, &push_spec, &checkout_branch))
if (!PyArg_ParseTuple(args, "zzIIzz",
&url, &path, &bare, &ignore_cert_errors, &remote_name, &checkout_branch))
return NULL;

opts.bare = bare;
opts.ignore_cert_errors = ignore_cert_errors;
opts.remote_name = remote_name;
opts.pushurl = push_url;
opts.fetch_spec = fetch_spec;
opts.push_spec = push_spec;
opts.checkout_branch = checkout_branch;

err = git_clone(&repo, url, path, &opts);
Expand Down Expand Up @@ -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_DISABLE_PATHSPEC_MATCH)
ADD_CONSTANT_INT(m, GIT_DIFF_DELTAS_ARE_ICASE)
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_UNTRACKED_CONTENT)
ADD_CONSTANT_INT(m, GIT_DIFF_IGNORE_CASE)
ADD_CONSTANT_INT(m, GIT_DIFF_SHOW_UNTRACKED_CONTENT)
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_TREES)
Expand Down
12 changes: 10 additions & 2 deletions src/reference.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,19 @@ PyDoc_STRVAR(Reference_log__doc__,
PyObject *
Reference_log(Reference *self)
{
int err;
RefLogIter *iter;
git_repository *repo;

CHECK_REFERENCE(self);

repo = git_reference_owner(self->reference);
iter = PyObject_New(RefLogIter, &RefLogIterType);
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->i = 0;
}
Expand All @@ -341,6 +347,7 @@ Reference_log_append(Reference *self, PyObject *args)
Signature *py_committer;
PyObject *py_message = NULL;
char *encoding = NULL;
git_repository *repo;

CHECK_REFERENCE(self);

Expand All @@ -366,7 +373,8 @@ Reference_log_append(Reference *self, PyObject *args)
}

/* 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) {
free((void *)message);
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion src/remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Remote_fetch(Remote *self, PyObject *args)

err = git_remote_connect(self->remote, GIT_DIRECTION_FETCH);
if (err == GIT_OK) {
err = git_remote_download(self->remote, NULL, NULL);
err = git_remote_download(self->remote);
if (err == GIT_OK) {
stats = git_remote_stats(self->remote);
py_stats = Py_BuildValue("{s:I,s:I,s:n}",
Expand Down
Loading

2 comments on commit b7e906e

@alexband
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @carlosmn is git_diff_list depreciated in libgit2, we here has a kind of fork of pygi2 with some modification. The fork hasn't sync with the main repo for a while, and now there are some conflicts with git_diff_list, I found your commit to adjust to libgit2, is there any explanation or documentation about the git_diff_list thing, either in libgit2 or pygit2. Thanks in advance.

@alexband
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems that it's just rename libgit2/libgit2@3ff1d12

so I can just rename it , cool

Please sign in to comment.