Merge remote-tracking branch 'carlos/development'

This commit is contained in:
J. David Ibáñez 2014-06-21 10:14:00 +02:00
commit 88a28f7ed8
33 changed files with 371 additions and 544 deletions

@ -50,8 +50,8 @@ Attributes:
.. autoattribute:: pygit2.Patch.old_file_path
.. autoattribute:: pygit2.Patch.new_file_path
.. autoattribute:: pygit2.Patch.old_oid
.. autoattribute:: pygit2.Patch.new_oid
.. autoattribute:: pygit2.Patch.old_id
.. autoattribute:: pygit2.Patch.new_id
.. autoattribute:: pygit2.Patch.status
.. autoattribute:: pygit2.Patch.similarity
.. autoattribute:: pygit2.Patch.hunks

@ -22,8 +22,8 @@ merge with the default ones defined in GIT_MERGE_OPTS_INIT libgit2 constant.
Example::
>>> branch_head_hex = '5ebeeebb320790caf276b9fc8b24546d63316533'
>>> branch_oid = self.repo.get(branch_head_hex).id
>>> merge_result = self.repo.merge(branch_oid)
>>> branch_id = self.repo.get(branch_head_hex).id
>>> merge_result = self.repo.merge(branch_id)
The MergeResult object
======================
@ -33,5 +33,5 @@ Represents the result of a merge and contains these fields:
- is_uptodate: bool, if there wasn't any merge because the repo was already
up to date
- is_fastforward: bool, whether the merge was fastforward or not
- fastforward_oid: Oid, in the case it was a fastforward, this is the
forwarded Oid.
- fastforward_id: Oid, in the case it was a fastforward, this is the
forwarded id.

@ -14,14 +14,14 @@ type.
Object lookup
=================
In the previous chapter we learnt about Object IDs. With an oid we can ask the
In the previous chapter we learnt about Object IDs. With an Oid we can ask the
repository to get the associated object. To do that the ``Repository`` class
implementes a subset of the mapping interface.
.. automethod:: pygit2.Repository.get
Return the Git object for the given *oid*, returns the *default* value if
there's no object in the repository with that oid. The oid can be an Oid
Return the Git object for the given *id*, returns the *default* value if
there's no object in the repository with that id. The id can be an Oid
object, or an hexadecimal string.
Example::
@ -32,16 +32,16 @@ implementes a subset of the mapping interface.
>>> obj
<_pygit2.Commit object at 0x7ff27a6b60f0>
.. method:: Repository.__getitem__(oid)
.. method:: Repository.__getitem__(id)
Return the Git object for the given oid, raise ``KeyError`` if there's no
object in the repository with that oid. The oid can be an Oid object, or
Return the Git object for the given id, raise ``KeyError`` if there's no
object in the repository with that id. The id can be an Oid object, or
an hexadecimal string.
.. method:: Repository.__contains__(oid)
.. method:: Repository.__contains__(id)
Returns True if there is an object in the Repository with that oid, False
if there is not. The oid can be an Oid object, or an hexadecimal string.
Returns True if there is an object in the Repository with that id, False
if there is not. The id can be an Oid object, or an hexadecimal string.
The Object base type
@ -125,15 +125,15 @@ them to the Git object database:
Example:
>>> oid = repo.create_blob('foo bar') # Creates blob from bytes string
>>> blob = repo[oid]
>>> id = repo.create_blob('foo bar') # Creates blob from bytes string
>>> blob = repo[id]
>>> blob.data
'foo bar'
.. automethod:: pygit2.Repository.create_blob_fromworkdir
.. automethod:: pygit2.Repository.create_blob_fromdisk
There are also some functions to calculate the oid for a byte string without
There are also some functions to calculate the id for a byte string without
creating the blob object:
.. autofunction:: pygit2.hash

@ -109,8 +109,8 @@ Example::
>>> for entry in head.log():
... print(entry.message)
.. autoattribute:: pygit2.RefLogEntry.oid_new
.. autoattribute:: pygit2.RefLogEntry.oid_old
.. autoattribute:: pygit2.RefLogEntry.id_new
.. autoattribute:: pygit2.RefLogEntry.id_old
.. autoattribute:: pygit2.RefLogEntry.message
.. autoattribute:: pygit2.RefLogEntry.committer
@ -126,6 +126,6 @@ The Note type
--------------------
.. autoattribute:: pygit2.Note.annotated_id
.. autoattribute:: pygit2.Note.oid
.. autoattribute:: pygit2.Note.id
.. autoattribute:: pygit2.Note.message
.. automethod:: pygit2.Note.remove

@ -8,8 +8,8 @@ Index read::
>>> index = repo.index
>>> index.read()
>>> oid = index['path/to/file'].id # from path to object id
>>> blob = repo[oid] # from object id to object
>>> id = index['path/to/file'].id # from path to object id
>>> blob = repo[id] # from object id to object
Iterate over all entries of the index::
@ -51,7 +51,7 @@ The Index type
The IndexEntry type
--------------------
.. autoattribute:: pygit2.IndexEntry.oid
.. autoattribute:: pygit2.IndexEntry.id
.. autoattribute:: pygit2.IndexEntry.hex
.. autoattribute:: pygit2.IndexEntry.path
.. autoattribute:: pygit2.IndexEntry.mode

@ -189,7 +189,7 @@ def clone_into(repo, remote, branch=None):
and calling this function.
"""
err = C.git_clone_into(repo._repo, remote._remote, ffi.NULL, to_str(branch))
err = C.git_clone_into(repo._repo, remote._remote, ffi.NULL, to_str(branch), ffi.NULL)
if remote._stored_exception:
raise remote._stored_exception

@ -223,6 +223,19 @@ class Config(object):
err = C.git_config_add_file_ondisk(self._config, to_str(path), level, force)
check_error(err)
def snapshot(self):
"""Create a snapshot from this Config object
This means that looking up multiple values will use the same version
of the configuration files
"""
ccfg = ffi.new('git_config **')
err = C.git_config_snapshot(cfg, self._config)
check_error(err)
return Config.from_c(self._repo, ccfg[0])
#
# Methods to parse a string according to the git-config rules
#
@ -248,10 +261,13 @@ class Config(object):
@staticmethod
def _from_found_config(fn):
buf = ffi.new('char []', C.GIT_PATH_MAX)
err = fn(buf, C.GIT_PATH_MAX)
buf = ffi.new('git_buf *', (ffi.NULL, 0))
err = fn(buf)
check_error(err, True)
return Config(ffi.string(buf).decode())
cpath = ffi.string(buf.ptr).decode()
C.git_buf_free(buf)
return Config(cpath)
@staticmethod
def get_system_config():

@ -5,6 +5,7 @@ typedef ... git_push;
typedef ... git_cred;
typedef ... git_diff_file;
typedef ... git_tree;
typedef ... git_signature;
#define GIT_OID_RAWSZ ...
#define GIT_PATH_MAX ...
@ -13,6 +14,12 @@ typedef struct git_oid {
unsigned char id[20];
} git_oid;
typedef struct {
char *ptr;
size_t asize, size;
} git_buf;
void git_buf_free(git_buf *buffer);
typedef struct git_strarray {
char **strings;
size_t count;
@ -79,15 +86,26 @@ typedef enum {
...
} git_credtype_t;
typedef struct git_remote_callbacks {
typedef int (*git_transport_message_cb)(const char *str, int len, void *data);
typedef int (*git_cred_acquire_cb)(
git_cred **cred,
const char *url,
const char *username_from_url,
unsigned int allowed_types,
void *payload);
typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload);
struct git_remote_callbacks {
unsigned int version;
int (*progress)(const char *str, int len, void *data);
git_transport_message_cb sideband_progress;
int (*completion)(git_remote_completion_type type, void *data);
int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data);
int (*transfer_progress)(const git_transfer_progress *stats, void *data);
git_cred_acquire_cb credentials;
git_transfer_progress_cb transfer_progress;
int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
void *payload;
} git_remote_callbacks ;
};
typedef struct git_remote_callbacks git_remote_callbacks;
int git_remote_list(git_strarray *out, git_repository *repo);
int git_remote_load(git_remote **out, git_repository *repo, const char *name);
@ -98,16 +116,16 @@ int git_remote_create(
const char *url);
const char * git_remote_name(const git_remote *remote);
typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, void *payload);
int git_remote_rename(git_remote *remote,
const char *new_name,
git_remote_rename_problem_cb callback,
void *payload);
int git_remote_rename(
git_strarray *problems,
git_remote *remote,
const char *new_name);
const char * git_remote_url(const git_remote *remote);
int git_remote_set_url(git_remote *remote, const char* url);
const char * git_remote_pushurl(const git_remote *remote);
int git_remote_set_pushurl(git_remote *remote, const char* url);
int git_remote_fetch(git_remote *remote);
int git_remote_fetch(git_remote *remote, const git_signature *signature, const char *reflog_message);
const git_transfer_progress * git_remote_stats(git_remote *remote);
int git_remote_add_push(git_remote *remote, const char *refspec);
int git_remote_add_fetch(git_remote *remote, const char *refspec);
@ -133,7 +151,10 @@ int git_push_status_foreach(
int (*cb)(const char *ref, const char *msg, void *data),
void *data);
int git_push_update_tips(git_push *push);
int git_push_update_tips(
git_push *push,
const git_signature *signature,
const char *reflog_message);
void git_push_free(git_push *push);
const char * git_refspec_src(const git_refspec *refspec);
@ -145,8 +166,8 @@ git_direction git_refspec_direction(const git_refspec *spec);
int git_refspec_src_matches(const git_refspec *refspec, const char *refname);
int git_refspec_dst_matches(const git_refspec *refspec, const char *refname);
int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name);
int git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name);
int git_refspec_transform(git_buf *buf, const git_refspec *spec, const char *name);
int git_refspec_rtransform(git_buf *buf, const git_refspec *spec, const char *name);
int git_cred_userpass_plaintext_new(
git_cred **out,
@ -179,7 +200,7 @@ typedef void (*git_checkout_progress_cb)(
size_t total_steps,
void *payload);
typedef struct git_checkout_opts {
typedef struct git_checkout_options {
unsigned int version;
unsigned int checkout_strategy;
@ -202,10 +223,17 @@ typedef struct git_checkout_opts {
const char *target_directory;
const char *ancestor_label;
const char *our_label;
const char *their_label;
} git_checkout_opts;
} git_checkout_options;
typedef enum {
GIT_CLONE_LOCAL_AUTO,
GIT_CLONE_LOCAL,
GIT_CLONE_NO_LOCAL,
GIT_CLONE_LOCAL_NO_LINKS,
} git_clone_local_t;
/*
* git_clone
@ -214,13 +242,15 @@ typedef struct git_checkout_opts {
typedef struct git_clone_options {
unsigned int version;
git_checkout_opts checkout_opts;
git_checkout_options checkout_opts;
git_remote_callbacks remote_callbacks;
int bare;
int ignore_cert_errors;
git_clone_local_t local;
const char *remote_name;
const char* checkout_branch;
git_signature *signature;
} git_clone_options;
int git_clone(git_repository **out,
@ -231,8 +261,9 @@ int git_clone(git_repository **out,
int git_clone_into(
git_repository *repo,
git_remote *remote,
const git_checkout_opts *co_opts,
const char *branch);
const git_checkout_options *co_opts,
const char *branch,
const git_signature *signature);
/*
* git_config
@ -257,6 +288,7 @@ typedef struct {
} git_config_entry;
int git_repository_config(git_config **out, git_repository *repo);
int git_repository_config_snapshot(git_config **out, git_repository *repo);
void git_config_free(git_config *cfg);
int git_config_get_string(const char **out, const git_config *cfg, const char *name);
@ -290,11 +322,11 @@ int git_config_set_multivar(
const char *value);
int git_config_new(git_config **out);
int git_config_snapshot(git_config **out, git_config *config);
int git_config_open_ondisk(git_config **out, const char *path);
int git_config_find_system(char *out, size_t length);
int git_config_find_global(char *out, size_t length);
int git_config_find_xdg(char *out, size_t length);
int git_config_find_system(git_buf *out);
int git_config_find_global(git_buf *out);
int git_config_find_xdg(git_buf *out);
/*
* git_repository_init

@ -73,38 +73,24 @@ class Refspec(object):
Returns whether the given string matches the destination of this refspec"""
return bool(C.git_refspec_dst_matches(self._refspec, to_str(ref)))
def _transform(self, ref, fn):
buf = ffi.new('git_buf *', (ffi.NULL, 0))
err = fn(buf, self._refspec, to_str(ref))
check_error(err)
try:
return ffi.string(buf.ptr).decode()
finally:
C.git_buf_free(buf)
def transform(self, ref):
"""transform(str) -> str
Transform a reference name according to this refspec from the lhs to the rhs."""
alen = len(ref)
err = C.GIT_EBUFS
ptr = None
ref_str = to_str(ref)
while err == C.GIT_EBUFS:
alen *= 2
ptr = ffi.new('char []', alen)
err = C.git_refspec_transform(ptr, alen, self._refspec, ref_str)
check_error(err)
return ffi.string(ptr).decode()
return self._transform(ref, C.git_refspec_transform)
def rtransform(self, ref):
"""transform(str) -> str
Transform a reference name according to this refspec from the lhs to the rhs"""
alen = len(ref)
err = C.GIT_EBUFS
ptr = None
ref_str = to_str(ref)
while err == C.GIT_EBUFS:
alen *= 2
ptr = ffi.new('char []', alen)
err = C.git_refspec_rtransform(ptr, alen, self._refspec, ref_str)
check_error(err)
return ffi.string(ptr).decode()
return self._transform(ref, C.git_refspec_rtransform)

@ -69,7 +69,7 @@ class TransferProgress(object):
class Remote(object):
def progress(self, string):
def sideband_progress(self, string):
"""Progress output callback
Override this function with your own progress reporting function
@ -122,7 +122,7 @@ class Remote(object):
# Build the callback structure
callbacks = ffi.new('git_remote_callbacks *')
callbacks.version = 1
callbacks.progress = self._progress_cb
callbacks.sideband_progress = self._sideband_progress_cb
callbacks.transfer_progress = self._transfer_progress_cb
callbacks.update_tips = self._update_tips_cb
callbacks.credentials = self._credentials_cb
@ -142,14 +142,25 @@ class Remote(object):
return maybe_string(C.git_remote_name(self._remote))
@name.setter
def name(self, value):
if not value:
def rename(self, new_name):
"""Rename this remote
Returns a list of fetch refspecs which were not in the standard format
and thus could not be remapped
"""
if not new_name:
raise ValueError("New remote name must be a non-empty string")
err = C.git_remote_rename(self._remote, to_str(value), ffi.NULL, ffi.NULL)
problems = ffi.new('git_strarray *')
err = C.git_remote_rename(problems, self._remote, to_str(new_name))
check_error(err)
ret = strarray_to_strings(problems)
C.git_strarray_free(problems)
return ret
@property
def url(self):
"""Url of the remote"""
@ -179,14 +190,19 @@ class Remote(object):
err = C.git_remote_save(self._remote)
check_error(err)
def fetch(self):
"""fetch() -> TransferProgress
def fetch(self, signature=None, message=None):
"""fetch(signature, message) -> TransferProgress
Perform a fetch against this remote.
"""
if signature:
ptr = signature._pointer[:]
else:
ptr = ffi.NULL
self._stored_exception = None
err = C.git_remote_fetch(self._remote)
err = C.git_remote_fetch(self._remote, ptr, to_str(message))
if self._stored_exception:
raise self._stored_exception
@ -261,10 +277,15 @@ class Remote(object):
self._bad_message = ffi.string(msg).decode()
return 0
def push(self, spec):
"""push(refspec)
def push(self, spec, signature=None, message=None):
"""push(refspec, signature, message)
Push the given refspec to the remote. Raises ``GitError`` on error"""
Push the given refspec to the remote. Raises ``GitError`` on error
:param str spec: push refspec to use
:param Signature signature: signature to use when updating the tips
:param str message: message to use when updating the tips
"""
cpush = ffi.new('git_push **')
err = C.git_push_new(cpush, self._remote)
@ -288,7 +309,12 @@ class Remote(object):
if hasattr(self, '_bad_message'):
raise GitError(self._bad_message)
err = C.git_push_update_tips(push)
if signature:
ptr = signature._pointer[:]
else:
ptr = ffi.NULL
err = C.git_push_update_tips(push, ptr, to_str(message))
check_error(err)
finally:
@ -297,7 +323,7 @@ class Remote(object):
# These functions exist to be called by the git_remote as
# callbacks. They proxy the call to whatever the user set
@ffi.callback('int (*transfer_progress)(const git_transfer_progress *stats, void *data)')
@ffi.callback('git_transfer_progress_cb')
def _transfer_progress_cb(stats_ptr, data):
self = ffi.from_handle(data)
@ -312,8 +338,8 @@ class Remote(object):
return 0
@ffi.callback('int (*progress)(const char *str, int len, void *data)')
def _progress_cb(string, length, data):
@ffi.callback('git_transport_message_cb')
def _sideband_progress_cb(string, length, data):
self = ffi.from_handle(data)
if not hasattr(self, 'progress') or not self.progress:

@ -128,6 +128,19 @@ class Repository(_Repository):
return Config.from_c(self, cconfig[0])
@property
def config_snapshot(self):
"""A snapshot for this repositiory's configuration
This allows reads over multiple values to use the same version
of the configuration files"""
cconfig = ffi.new('git_config **')
err = C.git_repository_config_snapshot(cconfig, self._repo)
check_error(err)
return Config.from_c(self, cconfig[0])
#
# References
#

@ -69,14 +69,20 @@ wrap_blame_hunk(const git_blame_hunk *hunk, Blame *blame)
py_hunk->lines_in_hunk = hunk->lines_in_hunk;
py_hunk->final_commit_id = git_oid_allocfmt(&hunk->final_commit_id);
py_hunk->final_start_line_number = hunk->final_start_line_number;
py_hunk->final_signature = hunk->final_signature != NULL ?
git_signature_dup(hunk->final_signature) : NULL;
py_hunk->final_signature = NULL;
if (hunk->final_signature)
git_signature_dup(&py_hunk->final_signature, hunk->final_signature);
py_hunk->orig_commit_id = git_oid_allocfmt(&hunk->orig_commit_id);
py_hunk->orig_path = hunk->orig_path != NULL ?
strdup(hunk->orig_path) : NULL;
py_hunk->orig_start_line_number = hunk->orig_start_line_number;
py_hunk->orig_signature = hunk->orig_signature != NULL ?
git_signature_dup(hunk->orig_signature) : NULL;
py_hunk->orig_signature = NULL;
if (hunk->orig_signature)
git_signature_dup(&py_hunk->orig_signature, hunk->orig_signature);
py_hunk->boundary = hunk->boundary;
}

@ -101,7 +101,7 @@ Branch_rename(Branch *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s|i", &c_name, &force))
return NULL;
err = git_branch_move(&c_out, self->reference, c_name, force);
err = git_branch_move(&c_out, self->reference, c_name, force, NULL, NULL);
if (err == GIT_OK)
return wrap_branch(c_out, self->repo);
else
@ -135,34 +135,19 @@ PyObject *
Branch_remote_name__get__(Branch *self)
{
int err;
git_buf name = {NULL};
const char *branch_name;
char *c_name = NULL;
PyObject *py_name;
CHECK_REFERENCE(self);
branch_name = git_reference_name(self->reference);
/* Get the length of the remote name */
err = git_branch_remote_name(NULL, 0, self->repo->repo, branch_name);
err = git_branch_remote_name(&name, self->repo->repo, branch_name);
if (err < GIT_OK)
return Error_set(err);
/* Get the actual remote name */
c_name = calloc(err, sizeof(char));
if (c_name == NULL)
return PyErr_NoMemory();
err = git_branch_remote_name(c_name,
err * sizeof(char),
self->repo->repo,
branch_name);
if (err < GIT_OK) {
free(c_name);
return Error_set(err);
}
py_name = to_unicode_n(c_name, err - 1, NULL, NULL);
free(c_name);
py_name = to_unicode(name.ptr, NULL, NULL);
git_buf_free(&name);
return py_name;
}
@ -227,34 +212,20 @@ PyObject *
Branch_upstream_name__get__(Branch *self)
{
int err;
git_buf name = {NULL};
const char *branch_name;
char *c_name = NULL;
PyObject *py_name;
CHECK_REFERENCE(self);
branch_name = git_reference_name(self->reference);
/* Get the length of the upstream name */
err = git_branch_upstream_name(NULL, 0, self->repo->repo, branch_name);
err = git_branch_upstream_name(&name, self->repo->repo, branch_name);
if (err < GIT_OK)
return Error_set(err);
/* Get the actual upstream name */
c_name = calloc(err, sizeof(char));
if (c_name == NULL)
return PyErr_NoMemory();
err = git_branch_upstream_name(c_name,
err * sizeof(char),
self->repo->repo,
branch_name);
if (err < GIT_OK) {
free(c_name);
return Error_set(err);
}
py_name = to_unicode_n(c_name, err - 1, NULL, NULL);
free(c_name);
py_name = to_unicode(name.ptr, NULL, NULL);
git_buf_free(&name);
return py_name;
}

@ -80,8 +80,8 @@ wrap_patch(git_patch *patch)
py_patch->status = git_diff_status_char(delta->status);
py_patch->similarity = delta->similarity;
py_patch->flags = delta->flags;
py_patch->old_oid = git_oid_allocfmt(&delta->old_file.oid);
py_patch->new_oid = git_oid_allocfmt(&delta->new_file.oid);
py_patch->old_id = git_oid_allocfmt(&delta->old_file.id);
py_patch->new_id = git_oid_allocfmt(&delta->new_file.id);
git_patch_line_stats(NULL, &additions, &deletions, patch);
py_patch->additions = additions;
@ -149,8 +149,8 @@ static void
Patch_dealloc(Patch *self)
{
Py_CLEAR(self->hunks);
free(self->old_oid);
free(self->new_oid);
free(self->old_id);
free(self->new_id);
/* We do not have to free old_file_path and new_file_path, they will
* be freed by git_diff_list_free in Diff_dealloc */
PyObject_Del(self);
@ -159,8 +159,8 @@ Patch_dealloc(Patch *self)
PyMemberDef Patch_members[] = {
MEMBER(Patch, old_file_path, T_STRING, "old file path"),
MEMBER(Patch, new_file_path, T_STRING, "new file path"),
MEMBER(Patch, old_oid, T_STRING, "old oid"),
MEMBER(Patch, new_oid, T_STRING, "new oid"),
MEMBER(Patch, old_id, T_STRING, "old oid"),
MEMBER(Patch, new_id, T_STRING, "new oid"),
MEMBER(Patch, status, T_CHAR, "status"),
MEMBER(Patch, similarity, T_INT, "similarity"),
MEMBER(Patch, hunks, T_OBJECT, "hunks"),
@ -292,8 +292,7 @@ PyObject *
Diff_patch__get__(Diff *self)
{
git_patch* patch;
char **strings = NULL;
char *buffer = NULL;
git_buf buf = {NULL};
int err = GIT_ERROR;
size_t i, len, num;
PyObject *py_patch = NULL;
@ -301,32 +300,25 @@ Diff_patch__get__(Diff *self)
num = git_diff_num_deltas(self->list);
if (num == 0)
Py_RETURN_NONE;
MALLOC(strings, num * sizeof(char*), cleanup);
for (i = 0, len = 1; i < num ; ++i) {
err = git_patch_from_diff(&patch, self->list, i);
if (err < 0)
goto cleanup;
err = git_patch_to_str(&(strings[i]), patch);
/* This appends to the current buf, so we can simply keep passing it */
err = git_patch_to_buf(&buf, patch);
if (err < 0)
goto cleanup;
len += strlen(strings[i]);
git_patch_free(patch);
}
CALLOC(buffer, (len + 1), sizeof(char), cleanup);
for (i = 0; i < num; ++i) {
strcat(buffer, strings[i]);
free(strings[i]);
}
free(strings);
py_patch = to_unicode(buffer, NULL, NULL);
free(buffer);
py_patch = to_unicode(buf.ptr, NULL, NULL);
git_buf_free(&buf);
cleanup:
git_buf_free(&buf);
return (err < 0) ? Error_set(err) : py_patch;
}

@ -649,7 +649,7 @@ IndexEntry_init(IndexEntry *self, PyObject *args, PyObject *kwds)
return -1;
if (id)
git_oid_cpy(&self->entry.oid, &id->oid);
git_oid_cpy(&self->entry.id, &id->oid);
if (mode)
self->entry.mode = mode;
@ -710,18 +710,18 @@ IndexEntry_path__set__(IndexEntry *self, PyObject *py_path)
return 0;
}
PyDoc_STRVAR(IndexEntry_oid__doc__, "Object id.");
PyDoc_STRVAR(IndexEntry_id__doc__, "Object id.");
PyObject *
IndexEntry_oid__get__(IndexEntry *self)
IndexEntry_id__get__(IndexEntry *self)
{
return git_oid_to_python(&self->entry.oid);
return git_oid_to_python(&self->entry.id);
}
int
IndexEntry_oid__set__(IndexEntry *self, PyObject *py_id)
IndexEntry_id__set__(IndexEntry *self, PyObject *py_id)
{
if (!py_oid_to_git_oid(py_id, &self->entry.oid))
if (!py_oid_to_git_oid(py_id, &self->entry.id))
return -1;
return 0;
@ -732,13 +732,13 @@ PyDoc_STRVAR(IndexEntry_hex__doc__, "Hex id.");
PyObject *
IndexEntry_hex__get__(IndexEntry *self)
{
return git_oid_to_py_str(&self->entry.oid);
return git_oid_to_py_str(&self->entry.id);
}
PyGetSetDef IndexEntry_getseters[] = {
GETSET(IndexEntry, mode),
GETSET(IndexEntry, path),
GETSET(IndexEntry, oid),
GETSET(IndexEntry, id),
GETTER(IndexEntry, hex),
{NULL},
};

@ -1,145 +0,0 @@
/*
* Copyright 2010-2014 The pygit2 contributors
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2,
* as published by the Free Software Foundation.
*
* In addition to the permissions in the GNU General Public License,
* the authors give you unlimited permission to link the compiled
* version of this file into combinations with other programs,
* and to distribute those combinations without any restriction
* coming from the use of this file. (The General Public License
* restrictions do apply in other respects; for example, they cover
* modification of the file, and distribution when not linked into
* a combined executable.)
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "utils.h"
#include "types.h"
#include "oid.h"
#include "repository.h"
#include "mergeresult.h"
extern PyTypeObject MergeResultType;
extern PyTypeObject IndexType;
PyObject *
git_merge_result_to_python(git_merge_result *merge_result)
{
MergeResult *py_merge_result;
py_merge_result = PyObject_New(MergeResult, &MergeResultType);
if (!py_merge_result)
return NULL;
py_merge_result->result = merge_result;
return (PyObject*) py_merge_result;
}
void
MergeResult_dealloc(MergeResult *self)
{
git_merge_result_free(self->result);
PyObject_Del(self);
}
PyDoc_STRVAR(MergeResult_is_uptodate__doc__, "Is up to date");
PyObject *
MergeResult_is_uptodate__get__(MergeResult *self)
{
if (git_merge_result_is_uptodate(self->result))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(MergeResult_is_fastforward__doc__, "Is fastforward");
PyObject *
MergeResult_is_fastforward__get__(MergeResult *self)
{
if (git_merge_result_is_fastforward(self->result))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(MergeResult_fastforward_oid__doc__, "Fastforward Oid");
PyObject *
MergeResult_fastforward_oid__get__(MergeResult *self)
{
if (git_merge_result_is_fastforward(self->result)) {
git_oid fastforward_oid;
git_merge_result_fastforward_oid(&fastforward_oid, self->result);
return git_oid_to_python((const git_oid *)&fastforward_oid);
}
else Py_RETURN_NONE;
}
PyGetSetDef MergeResult_getseters[] = {
GETTER(MergeResult, is_uptodate),
GETTER(MergeResult, is_fastforward),
GETTER(MergeResult, fastforward_oid),
{NULL},
};
PyDoc_STRVAR(MergeResult__doc__, "MergeResult object.");
PyTypeObject MergeResultType = {
PyVarObject_HEAD_INIT(NULL, 0)
"_pygit2.MergeResult", /* tp_name */
sizeof(MergeResult), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)MergeResult_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
MergeResult__doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
MergeResult_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};

@ -1,37 +0,0 @@
/*
* Copyright 2010-2014 The pygit2 contributors
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2,
* as published by the Free Software Foundation.
*
* In addition to the permissions in the GNU General Public License,
* the authors give you unlimited permission to link the compiled
* version of this file into combinations with other programs,
* and to distribute those combinations without any restriction
* coming from the use of this file. (The General Public License
* restrictions do apply in other respects; for example, they cover
* modification of the file, and distribution when not linked into
* a combined executable.)
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDE_pygit2_merge_result_h
#define INCLUDE_pygit2_merge_result_h
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <git2.h>
PyObject* git_merge_result_to_python(git_merge_result *merge_result);
#endif

@ -66,13 +66,13 @@ Note_remove(Note *self, PyObject* args)
}
PyDoc_STRVAR(Note_oid__doc__,
PyDoc_STRVAR(Note_id__doc__,
"Gets the id of the blob containing the note message\n");
PyObject *
Note_oid__get__(Note *self)
Note_id__get__(Note *self)
{
return git_oid_to_python(git_note_oid(self->note));
return git_oid_to_python(git_note_id(self->note));
}
@ -108,7 +108,7 @@ PyMemberDef Note_members[] = {
PyGetSetDef Note_getseters[] = {
GETTER(Note, message),
GETTER(Note, oid),
GETTER(Note, id),
{NULL}
};

@ -37,36 +37,16 @@ extern PyObject *GitError;
static PyObject *
get_search_path(long level)
{
char *buf = NULL;
size_t len = 64;
git_buf buf = {NULL};
PyObject *py_path;
int error;
char *tmp;
int err;
do {
len *= 2;
tmp = realloc(buf, len);
if (!tmp) {
free(buf);
PyErr_NoMemory();
return NULL;
}
buf = tmp;
err = git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, level, &buf);
if (err < 0)
return Error_set(err);
error = git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, level, buf, len);
} while(error == GIT_EBUFS);
if (error < 0) {
free(buf);
Error_set(error);
return NULL;
}
if (!buf)
return NULL;
py_path = to_unicode(buf, NULL, NULL);
free(buf);
py_path = to_unicode(buf.ptr, NULL, NULL);
git_buf_free(&buf);
if (!py_path)
return NULL;

@ -28,11 +28,6 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
/* Pypy does not provide this header */
#ifndef PYPY_VERSION
# include <osdefs.h>
#endif
#include <git2.h>
#include "error.h"
#include "types.h"
@ -41,11 +36,6 @@
#include "oid.h"
#include "options.h"
/* FIXME: This is for pypy */
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
extern PyObject *GitError;
extern PyTypeObject RepositoryType;
@ -78,7 +68,6 @@ extern PyTypeObject NoteIterType;
extern PyTypeObject BlameType;
extern PyTypeObject BlameIterType;
extern PyTypeObject BlameHunkType;
extern PyTypeObject MergeResultType;
@ -90,21 +79,25 @@ PyDoc_STRVAR(discover_repository__doc__,
PyObject *
discover_repository(PyObject *self, PyObject *args)
{
git_buf repo_path = {NULL};
const char *path;
PyObject *py_repo_path;
int across_fs = 0;
const char *ceiling_dirs = NULL;
char repo_path[MAXPATHLEN];
int err;
if (!PyArg_ParseTuple(args, "s|Is", &path, &across_fs, &ceiling_dirs))
return NULL;
err = git_repository_discover(repo_path, sizeof(repo_path),
path, across_fs, ceiling_dirs);
memset(&repo_path, 0, sizeof(git_buf));
err = git_repository_discover(&repo_path, path, across_fs, ceiling_dirs);
if (err < 0)
return Error_set_str(err, path);
return to_path(repo_path);
py_repo_path = to_path(repo_path.ptr);
git_buf_free(&repo_path);
return py_repo_path;
};
PyDoc_STRVAR(hashfile__doc__,
@ -364,8 +357,11 @@ moduleinit(PyObject* m)
ADD_CONSTANT_INT(m, GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES)
/* Merge */
INIT_TYPE(MergeResultType, NULL, NULL)
ADD_TYPE(m, MergeResult)
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_NONE)
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_NORMAL)
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UP_TO_DATE)
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_FASTFORWARD)
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UNBORN)
/* Global initialization of libgit2 */
git_threads_init();

@ -62,8 +62,7 @@ RefLogIter_iternext(RefLogIter *self)
py_entry->oid_old = git_oid_allocfmt(git_reflog_entry_id_old(entry));
py_entry->oid_new = git_oid_allocfmt(git_reflog_entry_id_new(entry));
py_entry->message = strdup(git_reflog_entry_message(entry));
py_entry->signature = git_signature_dup(
git_reflog_entry_committer(entry));
git_signature_dup(&py_entry->signature, git_reflog_entry_committer(entry));
++(self->i);
@ -160,7 +159,7 @@ Reference_rename(Reference *self, PyObject *py_name)
return NULL;
/* Rename */
err = git_reference_rename(&new_reference, self->reference, c_name, 0);
err = git_reference_rename(&new_reference, self->reference, c_name, 0, NULL, NULL);
git_reference_free(self->reference);
free(c_name);
if (err < 0)
@ -243,7 +242,7 @@ Reference_target__set__(Reference *self, PyObject *py_target)
if (err < 0)
return err;
err = git_reference_set_target(&new_ref, self->reference, &oid);
err = git_reference_set_target(&new_ref, self->reference, &oid, NULL, NULL);
if (err < 0)
goto error;
@ -257,7 +256,7 @@ Reference_target__set__(Reference *self, PyObject *py_target)
if (c_name == NULL)
return -1;
err = git_reference_symbolic_set_target(&new_ref, self->reference, c_name);
err = git_reference_symbolic_set_target(&new_ref, self->reference, c_name, NULL, NULL);
free(c_name);
if (err < 0)
goto error;

@ -1,38 +0,0 @@
/*
* Copyright 2010-2014 The pygit2 contributors
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2,
* as published by the Free Software Foundation.
*
* In addition to the permissions in the GNU General Public License,
* the authors give you unlimited permission to link the compiled
* version of this file into combinations with other programs,
* and to distribute those combinations without any restriction
* coming from the use of this file. (The General Public License
* restrictions do apply in other respects; for example, they cover
* modification of the file, and distribution when not linked into
* a combined executable.)
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDE_pygit2_refspec_h
#define INCLUDE_pygit2_refspec_h
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <git2.h>
#include <git2/refspec.h>
Refspec* wrap_refspec(const Remote *owner, const git_refspec *refspec);
#endif

@ -37,7 +37,6 @@
#include "repository.h"
#include "branch.h"
#include "blame.h"
#include "mergeresult.h"
#include "signature.h"
#include <git2/odb_backend.h>
@ -190,7 +189,7 @@ Repository_head__set__(Repository *self, PyObject *py_refname)
if (refname == NULL)
return -1;
err = git_repository_set_head(self->repo, refname);
err = git_repository_set_head(self->repo, refname, NULL, NULL);
Py_DECREF(trefname);
if (err < 0) {
Error_set_str(err, refname);
@ -546,46 +545,81 @@ Repository_merge_base(Repository *self, PyObject *args)
return git_oid_to_python(&oid);
}
PyDoc_STRVAR(Repository_merge_analysis__doc__,
"merge_analysis(id) -> (Integer, Integer)\n"
"\n"
"Analyzes the given branch and determines the opportunities for merging\n"
"them into the HEAD of the repository\n"
"\n"
"The first returned value is a mixture of the GIT_MERGE_ANALYSIS_NONE, _NORMAL,\n"
" _UP_TO_DATE, _FASTFORWARD and _UNBORN flags.\n"
"The second value is the user's preference from 'merge.ff'");
PyObject *
Repository_merge_analysis(Repository *self, PyObject *py_id)
{
int err;
size_t len;
git_oid id;
git_merge_head *merge_head;
git_merge_analysis_t analysis;
git_merge_preference_t preference;
len = py_oid_to_git_oid(py_id, &id);
if (len == 0)
return NULL;
err = git_merge_head_from_id(&merge_head, self->repo, &id);
if (err < 0)
return Error_set(err);
err = git_merge_analysis(&analysis, &preference, self->repo, (const git_merge_head **) &merge_head, 1);
git_merge_head_free(merge_head);
if (err < 0)
return Error_set(err);
return Py_BuildValue("(ii)", analysis, preference);
}
PyDoc_STRVAR(Repository_merge__doc__,
"merge(oid) -> MergeResult\n"
"merge(id)\n"
"\n"
"Merges the given oid and returns the MergeResult.\n"
"Merges the given id into HEAD.\n"
"\n"
"If the merge is fastforward the MergeResult will contain the new\n"
"fastforward oid.\n"
"If the branch is uptodate, nothing to merge, the MergeResult will\n"
"have the fastforward oid as None.\n"
"If the merge is not fastforward the MergeResult will have the status\n"
"produced by the merge, even if there are conflicts.");
"Merges the given commit(s) into HEAD, writing the results into the\n"
"working directory. Any changes are staged for commit and any conflicts\n"
"are written to the index. Callers should inspect the repository's\n"
"index after this completes, resolve any conflicts and prepare a\n"
"commit.");
PyObject *
Repository_merge(Repository *self, PyObject *py_oid)
{
git_merge_result *merge_result;
git_merge_head *oid_merge_head;
git_oid oid;
const git_merge_opts default_opts = GIT_MERGE_OPTS_INIT;
int err;
size_t len;
PyObject *py_merge_result;
git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
len = py_oid_to_git_oid(py_oid, &oid);
if (len == 0)
return NULL;
err = git_merge_head_from_oid(&oid_merge_head, self->repo, &oid);
err = git_merge_head_from_id(&oid_merge_head, self->repo, &oid);
if (err < 0)
return Error_set(err);
err = git_merge(&merge_result, self->repo,
err = git_merge(self->repo,
(const git_merge_head **)&oid_merge_head, 1,
&default_opts);
&merge_opts, &checkout_opts);
git_merge_head_free(oid_merge_head);
if (err < 0)
return Error_set(err);
py_merge_result = git_merge_result_to_python(merge_result);
return py_merge_result;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Repository_walk__doc__,
@ -888,7 +922,7 @@ Repository_create_branch(Repository *self, PyObject *args)
if (!PyArg_ParseTuple(args, "sO!|i", &c_name, &CommitType, &py_commit, &force))
return NULL;
err = git_branch_create(&c_reference, self->repo, c_name, py_commit->commit, force);
err = git_branch_create(&c_reference, self->repo, c_name, py_commit->commit, force, NULL, NULL);
if (err < 0)
return Error_set(err);
@ -1055,7 +1089,7 @@ Repository_create_reference_direct(Repository *self, PyObject *args,
if (err < 0)
return NULL;
err = git_reference_create(&c_reference, self->repo, c_name, &oid, force);
err = git_reference_create(&c_reference, self->repo, c_name, &oid, force, NULL, NULL);
if (err < 0)
return Error_set(err);
@ -1089,7 +1123,7 @@ Repository_create_reference_symbolic(Repository *self, PyObject *args,
return NULL;
err = git_reference_symbolic_create(&c_reference, self->repo, c_name,
c_target, force);
c_target, force, NULL, NULL);
if (err < 0)
return Error_set(err);
@ -1266,7 +1300,7 @@ PyDoc_STRVAR(Repository_checkout_head__doc__,
PyObject *
Repository_checkout_head(Repository *self, PyObject *args)
{
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
unsigned int strategy;
int err;
@ -1290,7 +1324,7 @@ PyDoc_STRVAR(Repository_checkout_index__doc__,
PyObject *
Repository_checkout_index(Repository *self, PyObject *args)
{
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
unsigned int strategy;
int err;
@ -1314,7 +1348,7 @@ PyDoc_STRVAR(Repository_checkout_tree__doc__,
PyObject *
Repository_checkout_tree(Repository *self, PyObject *args)
{
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
unsigned int strategy;
Object *py_object;
int err;
@ -1513,7 +1547,7 @@ Repository_reset(Repository *self, PyObject* args)
err = git_object_lookup_prefix(&target, self->repo, &oid, len,
GIT_OBJ_ANY);
err = err < 0 ? err : git_reset(self->repo, target, reset_type);
err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL, NULL);
git_object_free(target);
if (err < 0)
return Error_set_oid(err, &oid, len);
@ -1529,6 +1563,7 @@ PyMethodDef Repository_methods[] = {
METHOD(Repository, TreeBuilder, METH_VARARGS),
METHOD(Repository, walk, METH_VARARGS),
METHOD(Repository, merge_base, METH_VARARGS),
METHOD(Repository, merge_analysis, METH_O),
METHOD(Repository, merge, METH_O),
METHOD(Repository, read, METH_O),
METHOD(Repository, write, METH_VARARGS),

@ -94,6 +94,13 @@ Signature_dealloc(Signature *self)
PyObject_Del(self);
}
PyDoc_STRVAR(Signature__pointer__doc__, "Get the signature's pointer. For internal use only.");
PyObject *
Signature__pointer__get__(Repository *self)
{
/* Bytes means a raw buffer */
return PyBytes_FromStringAndSize((char *) &self->repo, sizeof(git_repository *));
}
PyDoc_STRVAR(Signature__encoding__doc__, "Encoding.");
@ -171,6 +178,7 @@ PyGetSetDef Signature_getseters[] = {
GETTER(Signature, email),
GETTER(Signature, time),
GETTER(Signature, offset),
GETTER(Signature, _pointer),
{NULL}
};

@ -284,20 +284,20 @@ TreeEntry *
Tree_getitem_by_index(Tree *self, PyObject *py_index)
{
int index;
const git_tree_entry *entry;
const git_tree_entry *entry_src;
git_tree_entry *entry;
index = Tree_fix_index(self, py_index);
if (PyErr_Occurred())
return NULL;
entry = git_tree_entry_byindex(self->tree, index);
if (!entry) {
entry_src = git_tree_entry_byindex(self->tree, index);
if (!entry_src) {
PyErr_SetObject(PyExc_IndexError, py_index);
return NULL;
}
entry = git_tree_entry_dup(entry);
if (entry == NULL) {
if (git_tree_entry_dup(&entry, entry_src) < 0) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}
@ -550,16 +550,16 @@ TreeIter_dealloc(TreeIter *self)
TreeEntry *
TreeIter_iternext(TreeIter *self)
{
const git_tree_entry *entry;
const git_tree_entry *entry_src;
git_tree_entry *entry;
entry = git_tree_entry_byindex(self->owner->tree, self->i);
if (!entry)
entry_src = git_tree_entry_byindex(self->owner->tree, self->i);
if (!entry_src)
return NULL;
self->i += 1;
entry = git_tree_entry_dup(entry);
if (entry == NULL) {
if (git_tree_entry_dup(&entry, entry_src) < 0) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}

@ -105,19 +105,19 @@ PyObject *
TreeBuilder_get(TreeBuilder *self, PyObject *py_filename)
{
char *filename;
const git_tree_entry *entry;
const git_tree_entry *entry_src;
git_tree_entry *entry;
filename = py_path_to_c_str(py_filename);
if (filename == NULL)
return NULL;
entry = git_treebuilder_get(self->bld, filename);
entry_src = git_treebuilder_get(self->bld, filename);
free(filename);
if (entry == NULL)
if (entry_src == NULL)
Py_RETURN_NONE;
entry = git_tree_entry_dup(entry);
if (entry == NULL) {
if (git_tree_entry_dup(&entry, entry_src) < 0) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}

@ -32,8 +32,8 @@
#include <Python.h>
#include <git2.h>
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 20)
#error You need a compatible libgit2 version (v0.20.x)
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 21)
#error You need a compatible libgit2 version (v0.21.x)
#endif
/*
@ -105,8 +105,8 @@ typedef struct {
PyObject* hunks;
const char * old_file_path;
const char * new_file_path;
char* old_oid;
char* new_oid;
char* old_id;
char* new_id;
char status;
unsigned similarity;
unsigned additions;
@ -208,10 +208,4 @@ typedef struct {
char boundary;
} BlameHunk;
/* git_merge */
typedef struct {
PyObject_HEAD
git_merge_result *result;
} MergeResult;
#endif

@ -65,11 +65,10 @@ class BlameTest(utils.RepoTestCase):
self.assertEqual(HUNKS[i][0], hunk.final_commit_id)
self.assertEqual(HUNKS[i][1], hunk.final_start_line_number)
self.assertEqualSignature(HUNKS[i][2], hunk.final_committer)
self.assertEqual(hunk.orig_commit_id,
'0000000000000000000000000000000000000000')
self.assertEqual(HUNKS[i][0], hunk.orig_commit_id)
self.assertEqual(hunk.orig_path, PATH)
self.assertEqual(HUNKS[i][1], hunk.orig_start_line_number)
self.assertTrue(hunk.orig_committer is None)
self.assertEqualSignature(HUNKS[i][2], hunk.orig_committer)
self.assertEqual(HUNKS[i][3], hunk.boundary)
def test_blame_with_invalid_index(self):
@ -93,11 +92,10 @@ class BlameTest(utils.RepoTestCase):
self.assertEqual(HUNKS[i][0], hunk.final_commit_id)
self.assertEqual(HUNKS[i][1], hunk.final_start_line_number)
self.assertEqualSignature(HUNKS[i][2], hunk.final_committer)
self.assertEqual(hunk.orig_commit_id,
'0000000000000000000000000000000000000000')
self.assertEqual(HUNKS[i][0], hunk.orig_commit_id)
self.assertEqual(hunk.orig_path, PATH)
self.assertEqual(HUNKS[i][1], hunk.orig_start_line_number)
self.assertTrue(hunk.orig_committer is None)
self.assertEqualSignature(HUNKS[i][2], hunk.orig_committer)
self.assertEqual(HUNKS[i][3], hunk.boundary)
def test_blame_with_invalid_line(self):
@ -131,11 +129,10 @@ class BlameTest(utils.RepoTestCase):
self.assertEqual(HUNKS[i][0], hunk.final_commit_id)
self.assertEqual(HUNKS[i][1], hunk.final_start_line_number)
self.assertEqualSignature(HUNKS[i][2], hunk.final_committer)
self.assertEqual(hunk.orig_commit_id,
'0000000000000000000000000000000000000000')
self.assertEqual(HUNKS[i][0], hunk.orig_commit_id)
self.assertEqual(hunk.orig_path, PATH)
self.assertEqual(HUNKS[i][1], hunk.orig_start_line_number)
self.assertTrue(hunk.orig_committer is None)
self.assertEqualSignature(HUNKS[i][2], hunk.orig_committer)
self.assertEqual(HUNKS[i][3], hunk.boundary)
if __name__ == '__main__':

@ -257,13 +257,13 @@ class DiffTest(utils.BareRepoTestCase):
self.assertEqual(diff.patch, PATCH)
self.assertEqual(len(diff), len([patch for patch in diff]))
def test_diff_oids(self):
def test_diff_ids(self):
commit_a = self.repo[COMMIT_SHA1_1]
commit_b = self.repo[COMMIT_SHA1_2]
patch = commit_a.tree.diff_to_tree(commit_b.tree)[0]
self.assertEqual(patch.old_oid,
self.assertEqual(patch.old_id,
'7f129fd57e31e935c6d60a0c794efe4e6927664b')
self.assertEqual(patch.new_oid,
self.assertEqual(patch.new_id,
'af431f20fc541ed6d5afede3e2dc7160f6f01f16')
def test_hunk_content(self):

@ -181,13 +181,13 @@ class IndexTest(utils.RepoTestCase):
index = self.repo.index
entry = index['hello.txt']
ign_entry = index['.gitignore']
self.assertNotEqual(ign_entry.oid, entry.oid)
self.assertNotEqual(ign_entry.id, entry.id)
self.assertNotEqual(entry.mode, pygit2.GIT_FILEMODE_BLOB_EXECUTABLE)
entry.path = 'foo.txt'
entry.oid = ign_entry.oid
entry.id = ign_entry.id
entry.mode = pygit2.GIT_FILEMODE_BLOB_EXECUTABLE
self.assertEqual('foo.txt', entry.path)
self.assertEqual(ign_entry.oid, entry.oid)
self.assertEqual(ign_entry.id, entry.id)
self.assertEqual(pygit2.GIT_FILEMODE_BLOB_EXECUTABLE, entry.mode)
def test_write_tree_to(self):
@ -201,7 +201,7 @@ class IndexEntryTest(utils.RepoTestCase):
def test_create_entry(self):
index = self.repo.index
hello_entry = index['hello.txt']
entry = pygit2.IndexEntry('README.md', hello_entry.oid, hello_entry.mode)
entry = pygit2.IndexEntry('README.md', hello_entry.id, hello_entry.mode)
index.add(entry)
tree_id = index.write_tree()
self.assertEqual('60e769e57ae1d6a2ab75d8d253139e6260e1f912', str(tree_id))

@ -58,7 +58,7 @@ class NotesTest(utils.BareRepoTestCase):
def test_lookup_note(self):
annotated_id = self.repo.head.target.hex
note = self.repo.lookup_note(annotated_id)
self.assertEqual(NOTES[0][0], note.oid.hex)
self.assertEqual(NOTES[0][0], note.id.hex)
self.assertEqual(NOTES[0][1], note.message)
def test_remove_note(self):
@ -70,7 +70,7 @@ class NotesTest(utils.BareRepoTestCase):
def test_iterate_notes(self):
for i, note in enumerate(self.repo.notes()):
entry = (note.oid.hex, note.message, note.annotated_id)
entry = (note.id.hex, note.message, note.annotated_id)
self.assertEqual(NOTES[i], entry)
def test_iterate_non_existing_ref(self):

@ -61,11 +61,12 @@ class RepositoryTest(utils.RepoTestCase):
remote = self.repo.remotes[0]
self.assertEqual(REMOTE_NAME, remote.name)
remote.name = 'new'
problems = remote.rename('new')
self.assertEqual([], problems)
self.assertEqual('new', remote.name)
self.assertRaisesAssign(ValueError, remote, 'name', '')
self.assertRaisesAssign(ValueError, remote, 'name', None)
self.assertRaises(ValueError, remote.rename, '')
self.assertRaises(ValueError, remote.rename, None)
def test_remote_set_url(self):
@ -153,7 +154,7 @@ class RepositoryTest(utils.RepoTestCase):
def test_remote_save(self):
remote = self.repo.remotes[0]
remote.name = 'new-name'
remote.rename('new-name')
remote.url = 'http://example.com/test.git'
remote.save()

@ -40,6 +40,8 @@ from os.path import join, realpath
# Import from pygit2
from pygit2 import GIT_OBJ_ANY, GIT_OBJ_BLOB, GIT_OBJ_COMMIT
from pygit2 import GIT_MERGE_ANALYSIS_NONE, GIT_MERGE_ANALYSIS_NORMAL, GIT_MERGE_ANALYSIS_UP_TO_DATE
from pygit2 import GIT_MERGE_ANALYSIS_FASTFORWARD, GIT_MERGE_ANALYSIS_UNBORN
from pygit2 import init_repository, clone_repository, clone_into, discover_repository
from pygit2 import Oid, Reference, hashfile
import pygit2
@ -308,57 +310,50 @@ class RepositoryTest_III(utils.RepoTestCaseForMerging):
def test_merge_none(self):
self.assertRaises(TypeError, self.repo.merge, None)
def test_merge_uptodate(self):
def test_merge_analysis_uptodate(self):
branch_head_hex = '5ebeeebb320790caf276b9fc8b24546d63316533'
branch_oid = self.repo.get(branch_head_hex).id
merge_result = self.repo.merge(branch_oid)
self.assertTrue(merge_result.is_uptodate)
self.assertFalse(merge_result.is_fastforward)
self.assertEqual(None, merge_result.fastforward_oid)
branch_id = self.repo.get(branch_head_hex).id
analysis, preference = self.repo.merge_analysis(branch_id)
self.assertTrue(analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)
self.assertFalse(analysis & GIT_MERGE_ANALYSIS_FASTFORWARD)
self.assertEqual({}, self.repo.status())
def test_merge_fastforward(self):
def test_merge_analysis_fastforward(self):
branch_head_hex = 'e97b4cfd5db0fb4ebabf4f203979ca4e5d1c7c87'
branch_oid = self.repo.get(branch_head_hex).id
merge_result = self.repo.merge(branch_oid)
self.assertFalse(merge_result.is_uptodate)
self.assertTrue(merge_result.is_fastforward)
# Asking twice to assure the reference counting is correct
self.assertEqual(branch_head_hex, merge_result.fastforward_oid.hex)
self.assertEqual(branch_head_hex, merge_result.fastforward_oid.hex)
branch_id = self.repo.get(branch_head_hex).id
analysis, preference = self.repo.merge_analysis(branch_id)
self.assertFalse(analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)
self.assertTrue(analysis & GIT_MERGE_ANALYSIS_FASTFORWARD)
self.assertEqual({}, self.repo.status())
def test_merge_no_fastforward_no_conflicts(self):
branch_head_hex = '03490f16b15a09913edb3a067a3dc67fbb8d41f1'
branch_oid = self.repo.get(branch_head_hex).id
merge_result = self.repo.merge(branch_oid)
self.assertFalse(merge_result.is_uptodate)
self.assertFalse(merge_result.is_fastforward)
branch_id = self.repo.get(branch_head_hex).id
analysis, preference = self.repo.merge_analysis(branch_id)
self.assertFalse(analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)
self.assertFalse(analysis & GIT_MERGE_ANALYSIS_FASTFORWARD)
# Asking twice to assure the reference counting is correct
self.assertEqual(None, merge_result.fastforward_oid)
self.assertEqual(None, merge_result.fastforward_oid)
self.assertEqual({'bye.txt': 1}, self.repo.status())
self.assertEqual({'bye.txt': 1}, self.repo.status())
# Checking the index works as expected
self.repo.index.remove('bye.txt')
self.repo.index.write()
self.assertEqual({'bye.txt': 128}, self.repo.status())
self.assertEqual({}, self.repo.status())
self.assertEqual({}, self.repo.status())
def test_merge_no_fastforward_conflicts(self):
branch_head_hex = '1b2bae55ac95a4be3f8983b86cd579226d0eb247'
branch_oid = self.repo.get(branch_head_hex).id
merge_result = self.repo.merge(branch_oid)
self.assertFalse(merge_result.is_uptodate)
self.assertFalse(merge_result.is_fastforward)
branch_id = self.repo.get(branch_head_hex).id
analysis, preference = self.repo.merge_analysis(branch_id)
self.assertFalse(analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)
self.assertFalse(analysis & GIT_MERGE_ANALYSIS_FASTFORWARD)
self.repo.merge(branch_id)
status = pygit2.GIT_STATUS_WT_NEW | pygit2.GIT_STATUS_INDEX_DELETED
# Asking twice to assure the reference counting is correct
self.assertEqual(None, merge_result.fastforward_oid)
self.assertEqual(None, merge_result.fastforward_oid)
self.assertEqual({'.gitignore': 132}, self.repo.status())
self.assertEqual({'.gitignore': 132}, self.repo.status())
self.assertEqual({'.gitignore': status}, self.repo.status())
self.assertEqual({'.gitignore': status}, self.repo.status())
# Checking the index works as expected
self.repo.index.add('.gitignore')
self.repo.index.write()
self.assertEqual({'.gitignore': 2}, self.repo.status())
self.assertEqual({'.gitignore': pygit2.GIT_STATUS_INDEX_MODIFIED}, self.repo.status())
def test_merge_invalid_hex(self):
branch_head_hex = '12345678'