Merge remote-tracking branch 'carlos/development'
Conflicts: pygit2/remote.py
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
cd ~
|
cd ~
|
||||||
|
|
||||||
git clone --depth=1 -b v0.21.2 https://github.com/libgit2/libgit2.git
|
git clone --depth=1 -b maint/v0.22 https://github.com/libgit2/libgit2.git
|
||||||
cd libgit2/
|
cd libgit2/
|
||||||
|
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
|
@@ -14,7 +14,7 @@ Requirements
|
|||||||
============
|
============
|
||||||
|
|
||||||
- Python 2.7, 3.2+ or pypy (including the development headers)
|
- Python 2.7, 3.2+ or pypy (including the development headers)
|
||||||
- Libgit2 v0.21.1+
|
- Libgit2 v0.22.x
|
||||||
- cffi 0.8.1+
|
- cffi 0.8.1+
|
||||||
- Libssh2, optional, used for SSH network operations.
|
- Libssh2, optional, used for SSH network operations.
|
||||||
|
|
||||||
@@ -34,11 +34,11 @@ while the last number |lq| *.micro* |rq| auto-increments independently.
|
|||||||
|
|
||||||
As illustration see this table of compatible releases:
|
As illustration see this table of compatible releases:
|
||||||
|
|
||||||
+-----------+---------------------------------------+------------------------------+--------------+
|
+-----------+--------+----------------------------------------+-------------------------------+
|
||||||
|**libgit2**|0.21.1, 0.21.2 |0.20.0 |0.19.0 |
|
|**libgit2**| 0.22.0 | 0.21.1, 0.21.2 |0.20.0 |
|
||||||
+-----------+---------------------------------------+------------------------------+--------------+
|
+-----------+--------+----------------------------------------+-------------------------------+
|
||||||
|**pygit2** |0.21.0, 0.21.1, 0.21.2, 0.21.3, 0.21.4 |0.20.0, 0.20.1, 0.20.2, 0.20.3|0.19.0, 0.19.1|
|
|**pygit2** | 0.22.0 | 0.21.0, 0.21.1, 0.21.2, 0.21.3, 0.21.4 | 0.20.0, 0.20.1, 0.20.2, 0.20.3|
|
||||||
+-----------+---------------------------------------+------------------------------+--------------+
|
+-----------+--------+----------------------------------------+-------------------------------+
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
@@ -55,9 +55,9 @@ directory, do:
|
|||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
$ wget https://github.com/libgit2/libgit2/archive/v0.21.2.tar.gz
|
$ wget https://github.com/libgit2/libgit2/archive/v0.22.0.tar.gz
|
||||||
$ tar xzf v0.21.2.tar.gz
|
$ tar xzf v0.22.0.tar.gz
|
||||||
$ cd libgit2-0.21.2/
|
$ cd libgit2-0.22.0/
|
||||||
$ cmake .
|
$ cmake .
|
||||||
$ make
|
$ make
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
@@ -41,7 +41,7 @@ from .index import Index, IndexEntry
|
|||||||
from .remote import Remote, get_credentials
|
from .remote import Remote, get_credentials
|
||||||
from .repository import Repository
|
from .repository import Repository
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from .utils import to_bytes
|
from .utils import to_bytes, to_str
|
||||||
from ._utils import __version__
|
from ._utils import __version__
|
||||||
|
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ def init_repository(path, bare=False,
|
|||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
# Ok
|
# Ok
|
||||||
return Repository(path)
|
return Repository(to_str(path))
|
||||||
|
|
||||||
|
|
||||||
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
||||||
@@ -123,7 +123,7 @@ def _credentials_cb(cred_out, url, username_from_url, allowed, data):
|
|||||||
d = ffi.from_handle(data)
|
d = ffi.from_handle(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ccred = get_credentials(d['callback'], url, username_from_url, allowed)
|
ccred = get_credentials(d['credentials_cb'], url, username_from_url, allowed)
|
||||||
cred_out[0] = ccred[0]
|
cred_out[0] = ccred[0]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
d['exception'] = e
|
d['exception'] = e
|
||||||
@@ -131,10 +131,54 @@ def _credentials_cb(cred_out, url, username_from_url, allowed, data):
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ffi.callback('int (*git_repository_create_cb)(git_repository **out,'
|
||||||
|
'const char *path, int bare, void *payload)')
|
||||||
|
def _repository_create_cb(repo_out, path, bare, data):
|
||||||
|
d = ffi.from_handle(data)
|
||||||
|
try:
|
||||||
|
repository = d['repository_cb'](ffi.string(path), bare != 0)
|
||||||
|
# we no longer own the C object
|
||||||
|
repository._disown()
|
||||||
|
repo_out[0] = repository._repo
|
||||||
|
except Exception as e:
|
||||||
|
d['exception'] = e
|
||||||
|
return C.GIT_EUSER
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@ffi.callback('int (*git_remote_create_cb)(git_remote **out, git_repository *repo,'
|
||||||
|
'const char *name, const char *url, void *payload)')
|
||||||
|
def _remote_create_cb(remote_out, repo, name, url, data):
|
||||||
|
d = ffi.from_handle(data)
|
||||||
|
try:
|
||||||
|
remote = d['remote_cb'](Repository._from_c(repo, False), ffi.string(name), ffi.string(url))
|
||||||
|
remote_out[0] = remote._remote
|
||||||
|
# we no longer own the C object
|
||||||
|
remote._remote = ffi.NULL
|
||||||
|
except Exception as e:
|
||||||
|
d['exception'] = e
|
||||||
|
return C.GIT_EUSER
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@ffi.callback('int (*git_transport_certificate_check_cb)'
|
||||||
|
'(git_cert *cert, int valid, const char *host, void *payload)')
|
||||||
|
def _certificate_cb(cert_i, valid, host, data):
|
||||||
|
d = ffi.from_handle(data)
|
||||||
|
try:
|
||||||
|
# python's parting is deep in the libraries and assumes an OpenSSL-owned cert
|
||||||
|
val = d['certificate_cb'](None, bool(valid), ffi.string(host))
|
||||||
|
if not val:
|
||||||
|
return C.GIT_ECERTIFICATE
|
||||||
|
except Exception as e:
|
||||||
|
d['exception'] = e
|
||||||
|
return C.GIT_EUSER
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
def clone_repository(
|
def clone_repository(
|
||||||
url, path, bare=False, ignore_cert_errors=False,
|
url, path, bare=False, repository=None, remote=None,
|
||||||
remote_name="origin", checkout_branch=None, credentials=None):
|
checkout_branch=None, credentials=None, certificate=None):
|
||||||
"""Clones a new Git repository from *url* in the given *path*.
|
"""Clones a new Git repository from *url* in the given *path*.
|
||||||
|
|
||||||
Returns a Repository class pointing to the newly cloned repository.
|
Returns a Repository class pointing to the newly cloned repository.
|
||||||
@@ -145,7 +189,9 @@ def clone_repository(
|
|||||||
|
|
||||||
:param bool bare: Whether the local repository should be bare
|
:param bool bare: Whether the local repository should be bare
|
||||||
|
|
||||||
:param str remote_name: Name to give the remote at *url*.
|
:param callable remote: Callback for the remote to use.
|
||||||
|
|
||||||
|
:param callable repository: Callback for the repository to use.
|
||||||
|
|
||||||
:param str checkout_branch: Branch to checkout after the
|
:param str checkout_branch: Branch to checkout after the
|
||||||
clone. The default is to use the remote's default branch.
|
clone. The default is to use the remote's default branch.
|
||||||
@@ -153,8 +199,22 @@ def clone_repository(
|
|||||||
:param callable credentials: authentication to use if the remote
|
:param callable credentials: authentication to use if the remote
|
||||||
requires it
|
requires it
|
||||||
|
|
||||||
|
:param callable certificate: callback to verify the host's
|
||||||
|
certificate or fingerprint.
|
||||||
|
|
||||||
:rtype: Repository
|
:rtype: Repository
|
||||||
|
|
||||||
|
The repository callback has `(path, bare) -> Repository` as a
|
||||||
|
signature. The Repository it returns will be used instead of
|
||||||
|
creating a new one.
|
||||||
|
|
||||||
|
The remote callback has `(Repository, name, url) -> Remote` as a
|
||||||
|
signature. The Remote it returns will be used instead of the default
|
||||||
|
one.
|
||||||
|
|
||||||
|
The certificate callback has `(cert, valid, hostname) -> bool` as
|
||||||
|
a signature. Return True to accept the connection, False to abort.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
opts = ffi.new('git_clone_options *')
|
opts = ffi.new('git_clone_options *')
|
||||||
@@ -164,7 +224,10 @@ def clone_repository(
|
|||||||
|
|
||||||
# Data, let's use a dict as we don't really want much more
|
# Data, let's use a dict as we don't really want much more
|
||||||
d = {}
|
d = {}
|
||||||
d['callback'] = credentials
|
d['credentials_cb'] = credentials
|
||||||
|
d['repository_cb'] = repository
|
||||||
|
d['remote_cb'] = remote
|
||||||
|
d['certificate_cb'] = certificate
|
||||||
d_handle = ffi.new_handle(d)
|
d_handle = ffi.new_handle(d)
|
||||||
|
|
||||||
# Perform the initialization with the version we compiled
|
# Perform the initialization with the version we compiled
|
||||||
@@ -176,49 +239,32 @@ def clone_repository(
|
|||||||
checkout_branch_ref = ffi.new('char []', to_bytes(branch))
|
checkout_branch_ref = ffi.new('char []', to_bytes(branch))
|
||||||
opts.checkout_branch = checkout_branch_ref
|
opts.checkout_branch = checkout_branch_ref
|
||||||
|
|
||||||
remote_name_ref = ffi.new('char []', to_bytes(remote_name))
|
if repository:
|
||||||
opts.remote_name = remote_name_ref
|
opts.repository_cb = _repository_create_cb
|
||||||
|
opts.repository_cb_payload = d_handle
|
||||||
|
|
||||||
|
if remote:
|
||||||
|
opts.remote_cb = _remote_create_cb
|
||||||
|
opts.remote_cb_payload = d_handle
|
||||||
|
|
||||||
|
|
||||||
opts.ignore_cert_errors = ignore_cert_errors
|
|
||||||
opts.bare = bare
|
opts.bare = bare
|
||||||
if credentials:
|
if credentials:
|
||||||
opts.remote_callbacks.credentials = _credentials_cb
|
opts.remote_callbacks.credentials = _credentials_cb
|
||||||
opts.remote_callbacks.payload = d_handle
|
opts.remote_callbacks.payload = d_handle
|
||||||
|
|
||||||
|
if certificate:
|
||||||
|
opts.remote_callbacks.certificate_check = _certificate_cb
|
||||||
|
opts.remote_callbacks.payload = d_handle
|
||||||
|
|
||||||
err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
|
err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
|
||||||
C.git_repository_free(crepo[0])
|
|
||||||
|
|
||||||
if 'exception' in d:
|
if 'exception' in d:
|
||||||
raise d['exception']
|
raise d['exception']
|
||||||
|
|
||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
return Repository(path)
|
return Repository._from_c(crepo[0], owned=True)
|
||||||
|
|
||||||
|
|
||||||
def clone_into(repo, remote, branch=None):
|
|
||||||
"""Clone into an empty repository from the specified remote
|
|
||||||
|
|
||||||
:param Repository repo: The empty repository into which to clone
|
|
||||||
|
|
||||||
:param Remote remote: The remote from which to clone
|
|
||||||
|
|
||||||
:param str branch: Branch to checkout after the clone. Pass None
|
|
||||||
to use the remotes's default branch.
|
|
||||||
|
|
||||||
This allows you specify arbitrary repository and remote configurations
|
|
||||||
before performing the clone step itself. E.g. you can replicate git-clone's
|
|
||||||
'--mirror' option by setting a refspec of '+refs/*:refs/*', 'core.mirror'
|
|
||||||
to true and calling this function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
err = C.git_clone_into(repo._repo, remote._remote, ffi.NULL,
|
|
||||||
to_bytes(branch), ffi.NULL)
|
|
||||||
|
|
||||||
if remote._stored_exception:
|
|
||||||
raise remote._stored_exception
|
|
||||||
|
|
||||||
check_error(err)
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|
||||||
|
127
pygit2/decl.h
127
pygit2/decl.h
@@ -1,7 +1,6 @@
|
|||||||
typedef ... git_repository;
|
typedef ... git_repository;
|
||||||
typedef ... git_remote;
|
typedef ... git_remote;
|
||||||
typedef ... git_refspec;
|
typedef ... git_refspec;
|
||||||
typedef ... git_push;
|
|
||||||
typedef ... git_cred;
|
typedef ... git_cred;
|
||||||
typedef ... git_object;
|
typedef ... git_object;
|
||||||
typedef ... git_tree;
|
typedef ... git_tree;
|
||||||
@@ -112,9 +111,38 @@ typedef enum {
|
|||||||
GIT_CREDTYPE_SSH_KEY,
|
GIT_CREDTYPE_SSH_KEY,
|
||||||
GIT_CREDTYPE_SSH_CUSTOM,
|
GIT_CREDTYPE_SSH_CUSTOM,
|
||||||
GIT_CREDTYPE_DEFAULT,
|
GIT_CREDTYPE_DEFAULT,
|
||||||
|
GIT_CREDTYPE_SSH_INTERACTIVE,
|
||||||
|
GIT_CREDTYPE_USERNAME,
|
||||||
...
|
...
|
||||||
} git_credtype_t;
|
} git_credtype_t;
|
||||||
|
|
||||||
|
typedef enum git_cert_t {
|
||||||
|
GIT_CERT_X509,
|
||||||
|
GIT_CERT_HOSTKEY_LIBSSH2,
|
||||||
|
} git_cert_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GIT_CERT_SSH_MD5 = 1,
|
||||||
|
GIT_CERT_SSH_SHA1 = 2,
|
||||||
|
} git_cert_ssh_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
git_cert_t cert_type;
|
||||||
|
git_cert_ssh_t type;
|
||||||
|
unsigned char hash_md5[16];
|
||||||
|
unsigned char hash_sha1[20];
|
||||||
|
} git_cert_hostkey;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
git_cert_t cert_type;
|
||||||
|
void *data;
|
||||||
|
size_t len;
|
||||||
|
} git_cert_x509;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
git_cert_t cert_type;
|
||||||
|
} git_cert;
|
||||||
|
|
||||||
typedef int (*git_transport_message_cb)(const char *str, int len, void *data);
|
typedef int (*git_transport_message_cb)(const char *str, int len, void *data);
|
||||||
typedef int (*git_cred_acquire_cb)(
|
typedef int (*git_cred_acquire_cb)(
|
||||||
git_cred **cred,
|
git_cred **cred,
|
||||||
@@ -123,40 +151,59 @@ typedef int (*git_cred_acquire_cb)(
|
|||||||
unsigned int allowed_types,
|
unsigned int allowed_types,
|
||||||
void *payload);
|
void *payload);
|
||||||
typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload);
|
typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload);
|
||||||
|
typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload);
|
||||||
|
|
||||||
|
typedef int (*git_packbuilder_progress)(
|
||||||
|
int stage,
|
||||||
|
unsigned int current,
|
||||||
|
unsigned int total,
|
||||||
|
void *payload);
|
||||||
|
typedef int (*git_push_transfer_progress)(
|
||||||
|
unsigned int current,
|
||||||
|
unsigned int total,
|
||||||
|
size_t bytes,
|
||||||
|
void* payload);
|
||||||
|
|
||||||
struct git_remote_callbacks {
|
struct git_remote_callbacks {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
git_transport_message_cb sideband_progress;
|
git_transport_message_cb sideband_progress;
|
||||||
int (*completion)(git_remote_completion_type type, void *data);
|
int (*completion)(git_remote_completion_type type, void *data);
|
||||||
git_cred_acquire_cb credentials;
|
git_cred_acquire_cb credentials;
|
||||||
|
git_transport_certificate_check_cb certificate_check;
|
||||||
git_transfer_progress_cb transfer_progress;
|
git_transfer_progress_cb transfer_progress;
|
||||||
int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
|
int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
|
||||||
|
git_packbuilder_progress pack_progress;
|
||||||
|
git_push_transfer_progress push_transfer_progress;
|
||||||
|
int (*push_update_reference)(const char *refname, const char *status, void *data);
|
||||||
void *payload;
|
void *payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct git_remote_callbacks git_remote_callbacks;
|
typedef struct git_remote_callbacks git_remote_callbacks;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int version;
|
||||||
|
unsigned int pb_parallelism;
|
||||||
|
} git_push_options;
|
||||||
|
|
||||||
int git_remote_list(git_strarray *out, git_repository *repo);
|
int git_remote_list(git_strarray *out, git_repository *repo);
|
||||||
int git_remote_load(git_remote **out, git_repository *repo, const char *name);
|
int git_remote_lookup(git_remote **out, git_repository *repo, const char *name);
|
||||||
int git_remote_create(
|
int git_remote_create(
|
||||||
git_remote **out,
|
git_remote **out,
|
||||||
git_repository *repo,
|
git_repository *repo,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *url);
|
const char *url);
|
||||||
int git_remote_delete(git_remote *remote);
|
int git_remote_delete(git_repository *repo, const char *name);
|
||||||
int git_repository_state_cleanup(git_repository *repo);
|
int git_repository_state_cleanup(git_repository *repo);
|
||||||
|
|
||||||
const char * git_remote_name(const git_remote *remote);
|
const char * git_remote_name(const git_remote *remote);
|
||||||
|
|
||||||
int git_remote_rename(
|
int git_remote_rename(git_strarray *problems, git_repository *repo, const char *name, const char *new_name);
|
||||||
git_strarray *problems,
|
|
||||||
git_remote *remote,
|
|
||||||
const char *new_name);
|
|
||||||
const char * git_remote_url(const git_remote *remote);
|
const char * git_remote_url(const git_remote *remote);
|
||||||
int git_remote_set_url(git_remote *remote, const char* url);
|
int git_remote_set_url(git_remote *remote, const char* url);
|
||||||
const char * git_remote_pushurl(const git_remote *remote);
|
const char * git_remote_pushurl(const git_remote *remote);
|
||||||
int git_remote_set_pushurl(git_remote *remote, const char* url);
|
int git_remote_set_pushurl(git_remote *remote, const char* url);
|
||||||
int git_remote_fetch(git_remote *remote, const git_signature *signature, const char *reflog_message);
|
int git_remote_fetch(git_remote *remote, const git_strarray *refspecs, const git_signature *signature, const char *reflog_message);
|
||||||
|
int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_options *opts, const git_signature *signature, const char *reflog_message);
|
||||||
const git_transfer_progress * git_remote_stats(git_remote *remote);
|
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_push(git_remote *remote, const char *refspec);
|
||||||
int git_remote_add_fetch(git_remote *remote, const char *refspec);
|
int git_remote_add_fetch(git_remote *remote, const char *refspec);
|
||||||
@@ -173,22 +220,6 @@ int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array);
|
|||||||
|
|
||||||
void git_remote_free(git_remote *remote);
|
void git_remote_free(git_remote *remote);
|
||||||
|
|
||||||
int git_push_new(git_push **push, git_remote *remote);
|
|
||||||
int git_push_add_refspec(git_push *push, const char *refspec);
|
|
||||||
int git_push_finish(git_push *push);
|
|
||||||
int git_push_unpack_ok(git_push *push);
|
|
||||||
|
|
||||||
int git_push_status_foreach(
|
|
||||||
git_push *push,
|
|
||||||
int (*cb)(const char *ref, const char *msg, void *data),
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
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);
|
const char * git_refspec_src(const git_refspec *refspec);
|
||||||
const char * git_refspec_dst(const git_refspec *refspec);
|
const char * git_refspec_dst(const git_refspec *refspec);
|
||||||
int git_refspec_force(const git_refspec *refspec);
|
int git_refspec_force(const git_refspec *refspec);
|
||||||
@@ -267,14 +298,12 @@ typedef int (*git_diff_notify_cb)(
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
git_submodule_ignore_t ignore_submodules;
|
git_submodule_ignore_t ignore_submodules;
|
||||||
git_strarray pathspec;
|
git_strarray pathspec;
|
||||||
git_diff_notify_cb notify_cb;
|
git_diff_notify_cb notify_cb;
|
||||||
void *notify_payload;
|
void *notify_payload;
|
||||||
|
uint32_t context_lines;
|
||||||
uint16_t context_lines;
|
uint32_t interhunk_lines;
|
||||||
uint16_t interhunk_lines;
|
|
||||||
uint16_t id_abbrev;
|
uint16_t id_abbrev;
|
||||||
git_off_t max_size;
|
git_off_t max_size;
|
||||||
const char *old_prefix;
|
const char *old_prefix;
|
||||||
@@ -345,13 +374,6 @@ typedef struct git_checkout_options {
|
|||||||
const char *their_label;
|
const char *their_label;
|
||||||
} git_checkout_options;
|
} 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;
|
|
||||||
|
|
||||||
int git_checkout_init_options(git_checkout_options *opts, unsigned int version);
|
int git_checkout_init_options(git_checkout_options *opts, unsigned int version);
|
||||||
int git_checkout_tree(git_repository *repo, const git_object *treeish, const git_checkout_options *opts);
|
int git_checkout_tree(git_repository *repo, const git_object *treeish, const git_checkout_options *opts);
|
||||||
int git_checkout_head(git_repository *repo, const git_checkout_options *opts);
|
int git_checkout_head(git_repository *repo, const git_checkout_options *opts);
|
||||||
@@ -361,18 +383,38 @@ int git_checkout_index(git_repository *repo, git_index *index, const git_checkou
|
|||||||
* git_clone
|
* git_clone
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef int (*git_remote_create_cb)(
|
||||||
|
git_remote **out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *name,
|
||||||
|
const char *url,
|
||||||
|
void *payload);
|
||||||
|
|
||||||
|
typedef int (*git_repository_create_cb)(
|
||||||
|
git_repository **out,
|
||||||
|
const char *path,
|
||||||
|
int bare,
|
||||||
|
void *payload);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GIT_CLONE_LOCAL_AUTO,
|
||||||
|
GIT_CLONE_LOCAL,
|
||||||
|
GIT_CLONE_NO_LOCAL,
|
||||||
|
GIT_CLONE_LOCAL_NO_LINKS,
|
||||||
|
} git_clone_local_t;
|
||||||
|
|
||||||
typedef struct git_clone_options {
|
typedef struct git_clone_options {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
|
|
||||||
git_checkout_options checkout_opts;
|
git_checkout_options checkout_opts;
|
||||||
git_remote_callbacks remote_callbacks;
|
git_remote_callbacks remote_callbacks;
|
||||||
|
|
||||||
int bare;
|
int bare;
|
||||||
int ignore_cert_errors;
|
|
||||||
git_clone_local_t local;
|
git_clone_local_t local;
|
||||||
const char *remote_name;
|
|
||||||
const char* checkout_branch;
|
const char* checkout_branch;
|
||||||
git_signature *signature;
|
git_signature *signature;
|
||||||
|
git_repository_create_cb repository_cb;
|
||||||
|
void *repository_cb_payload;
|
||||||
|
git_remote_create_cb remote_cb;
|
||||||
|
void *remote_cb_payload;
|
||||||
} git_clone_options;
|
} git_clone_options;
|
||||||
|
|
||||||
#define GIT_CLONE_OPTIONS_VERSION ...
|
#define GIT_CLONE_OPTIONS_VERSION ...
|
||||||
@@ -383,13 +425,6 @@ int git_clone(git_repository **out,
|
|||||||
const char *local_path,
|
const char *local_path,
|
||||||
const git_clone_options *options);
|
const git_clone_options *options);
|
||||||
|
|
||||||
int git_clone_into(
|
|
||||||
git_repository *repo,
|
|
||||||
git_remote *remote,
|
|
||||||
const git_checkout_options *co_opts,
|
|
||||||
const char *branch,
|
|
||||||
const git_signature *signature);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* git_config
|
* git_config
|
||||||
*/
|
*/
|
||||||
|
154
pygit2/remote.py
154
pygit2/remote.py
@@ -121,6 +121,16 @@ class Remote(object):
|
|||||||
:param Oid new: the reference's new value
|
:param Oid new: the reference's new value
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def push_update_reference(self, refname, message):
|
||||||
|
"""Push update reference callback
|
||||||
|
|
||||||
|
Override with your own function to report the remote's
|
||||||
|
acceptace or rejection of reference updates.
|
||||||
|
|
||||||
|
:param str refname: the name of the reference (on the remote)
|
||||||
|
:param str messsage: rejection message from the remote. If None, the update was accepted.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, repo, ptr):
|
def __init__(self, repo, ptr):
|
||||||
"""The constructor is for internal use only"""
|
"""The constructor is for internal use only"""
|
||||||
|
|
||||||
@@ -137,25 +147,6 @@ class Remote(object):
|
|||||||
|
|
||||||
return maybe_string(C.git_remote_name(self._remote))
|
return maybe_string(C.git_remote_name(self._remote))
|
||||||
|
|
||||||
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")
|
|
||||||
|
|
||||||
problems = ffi.new('git_strarray *')
|
|
||||||
err = C.git_remote_rename(problems, self._remote, to_bytes(new_name))
|
|
||||||
check_error(err)
|
|
||||||
|
|
||||||
ret = strarray_to_strings(problems)
|
|
||||||
C.git_strarray_free(problems)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
"""Url of the remote"""
|
"""Url of the remote"""
|
||||||
@@ -178,14 +169,6 @@ class Remote(object):
|
|||||||
err = C.git_remote_set_pushurl(self._remote, to_bytes(value))
|
err = C.git_remote_set_pushurl(self._remote, to_bytes(value))
|
||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
"""Remove this remote
|
|
||||||
|
|
||||||
All remote-tracking branches and configuration settings for the remote will be removed.
|
|
||||||
"""
|
|
||||||
err = C.git_remote_delete(self._remote)
|
|
||||||
check_error(err)
|
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""save()
|
"""save()
|
||||||
|
|
||||||
@@ -231,7 +214,7 @@ class Remote(object):
|
|||||||
self._stored_exception = None
|
self._stored_exception = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
err = C.git_remote_fetch(self._remote, ptr, to_bytes(message))
|
err = C.git_remote_fetch(self._remote, ffi.NULL, ptr, to_bytes(message))
|
||||||
if self._stored_exception:
|
if self._stored_exception:
|
||||||
raise self._stored_exception
|
raise self._stored_exception
|
||||||
|
|
||||||
@@ -306,27 +289,30 @@ class Remote(object):
|
|||||||
err = C.git_remote_add_push(self._remote, to_bytes(spec))
|
err = C.git_remote_add_push(self._remote, to_bytes(spec))
|
||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
@ffi.callback("int (*cb)(const char *ref, const char *msg, void *data)")
|
def push(self, specs, signature=None, message=None):
|
||||||
def _push_cb(ref, msg, data):
|
"""push(specs, signature, message)
|
||||||
self = ffi.from_handle(data)
|
|
||||||
if msg:
|
|
||||||
self._bad_message = ffi.string(msg).decode()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def push(self, spec, signature=None, message=None):
|
Push the given refspec to the remote. Raises ``GitError`` on
|
||||||
"""push(refspec, signature, message)
|
protocol error or unpack failure.
|
||||||
|
|
||||||
Push the given refspec to the remote. Raises ``GitError`` on error.
|
:param [str] specs: push refspecs to use
|
||||||
|
|
||||||
:param str spec: push refspec to use
|
|
||||||
:param Signature signature: signature to use when updating the tips
|
:param Signature signature: signature to use when updating the tips
|
||||||
:param str message: message to use when updating the tips
|
:param str message: message to use when updating the tips
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Get the default callbacks first
|
# Get the default callbacks first
|
||||||
defaultcallbacks = ffi.new('git_remote_callbacks *')
|
defaultcallbacks = ffi.new('git_remote_callbacks *')
|
||||||
err = C.git_remote_init_callbacks(defaultcallbacks, 1)
|
err = C.git_remote_init_callbacks(defaultcallbacks, 1)
|
||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
|
refspecs, refspecs_refs = strings_to_strarray(specs)
|
||||||
|
if signature:
|
||||||
|
sig_cptr = ffi.new('git_signature **')
|
||||||
|
ffi.buffer(sig_cptr)[:] = signature._pointer[:]
|
||||||
|
sig_ptr = sig_cptr[0]
|
||||||
|
else:
|
||||||
|
sig_ptr = ffi.NULL
|
||||||
|
|
||||||
# Build custom callback structure
|
# Build custom callback structure
|
||||||
callbacks = ffi.new('git_remote_callbacks *')
|
callbacks = ffi.new('git_remote_callbacks *')
|
||||||
callbacks.version = 1
|
callbacks.version = 1
|
||||||
@@ -334,53 +320,23 @@ class Remote(object):
|
|||||||
callbacks.transfer_progress = self._transfer_progress_cb
|
callbacks.transfer_progress = self._transfer_progress_cb
|
||||||
callbacks.update_tips = self._update_tips_cb
|
callbacks.update_tips = self._update_tips_cb
|
||||||
callbacks.credentials = self._credentials_cb
|
callbacks.credentials = self._credentials_cb
|
||||||
|
callbacks.push_update_reference = self._push_update_reference_cb
|
||||||
# We need to make sure that this handle stays alive
|
# We need to make sure that this handle stays alive
|
||||||
self._self_handle = ffi.new_handle(self)
|
self._self_handle = ffi.new_handle(self)
|
||||||
callbacks.payload = self._self_handle
|
callbacks.payload = self._self_handle
|
||||||
|
|
||||||
err = C.git_remote_set_callbacks(self._remote, callbacks)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
err = C.git_remote_set_callbacks(self._remote, callbacks)
|
||||||
check_error(err)
|
check_error(err)
|
||||||
except:
|
except:
|
||||||
self._self_handle = None
|
self._self_handle = None
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
cpush = ffi.new('git_push **')
|
|
||||||
err = C.git_push_new(cpush, self._remote)
|
|
||||||
check_error(err)
|
|
||||||
|
|
||||||
push = cpush[0]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
err = C.git_push_add_refspec(push, to_bytes(spec))
|
err = C.git_remote_push(self._remote, refspecs, ffi.NULL, sig_ptr, to_bytes(message))
|
||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
err = C.git_push_finish(push)
|
|
||||||
check_error(err)
|
|
||||||
|
|
||||||
if not C.git_push_unpack_ok(push):
|
|
||||||
raise GitError("remote failed to unpack objects")
|
|
||||||
|
|
||||||
err = C.git_push_status_foreach(push, self._push_cb,
|
|
||||||
ffi.new_handle(self))
|
|
||||||
check_error(err)
|
|
||||||
|
|
||||||
if hasattr(self, '_bad_message'):
|
|
||||||
raise GitError(self._bad_message)
|
|
||||||
|
|
||||||
if signature:
|
|
||||||
ptr = signature._pointer[:]
|
|
||||||
else:
|
|
||||||
ptr = ffi.NULL
|
|
||||||
|
|
||||||
err = C.git_push_update_tips(push, ptr, to_bytes(message))
|
|
||||||
check_error(err)
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self._self_handle = None
|
self._self_handle = None
|
||||||
C.git_push_free(push)
|
|
||||||
|
|
||||||
# These functions exist to be called by the git_remote as
|
# These functions exist to be called by the git_remote as
|
||||||
# callbacks. They proxy the call to whatever the user set
|
# callbacks. They proxy the call to whatever the user set
|
||||||
@@ -437,6 +393,23 @@ class Remote(object):
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ffi.callback("int (*push_update_reference)(const char *ref, const char *msg, void *data)")
|
||||||
|
def _push_update_reference_cb(ref, msg, data):
|
||||||
|
self = ffi.from_handle(data)
|
||||||
|
|
||||||
|
if not hasattr(self, 'push_update_reference') or not self.push_update_reference:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
refname = ffi.string(ref)
|
||||||
|
message = maybe_string(msg)
|
||||||
|
self.push_update_reference(refname, message)
|
||||||
|
except Exception as e:
|
||||||
|
self._stored_exception = e
|
||||||
|
return C.GIT_EUSER
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
||||||
'const char *username_from_url, unsigned int allowed_types,'
|
'const char *username_from_url, unsigned int allowed_types,'
|
||||||
'void *data)')
|
'void *data)')
|
||||||
@@ -528,7 +501,7 @@ class RemoteCollection(object):
|
|||||||
|
|
||||||
cremote = ffi.new('git_remote **')
|
cremote = ffi.new('git_remote **')
|
||||||
for i in range(names.count):
|
for i in range(names.count):
|
||||||
err = C.git_remote_load(cremote, self._repo._repo, names.strings[i])
|
err = C.git_remote_lookup(cremote, self._repo._repo, names.strings[i])
|
||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
yield Remote(self._repo, cremote[0])
|
yield Remote(self._repo, cremote[0])
|
||||||
@@ -540,7 +513,7 @@ class RemoteCollection(object):
|
|||||||
return list(self)[name]
|
return list(self)[name]
|
||||||
|
|
||||||
cremote = ffi.new('git_remote **')
|
cremote = ffi.new('git_remote **')
|
||||||
err = C.git_remote_load(cremote, self._repo._repo, to_bytes(name))
|
err = C.git_remote_lookup(cremote, self._repo._repo, to_bytes(name))
|
||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
return Remote(self._repo, cremote[0])
|
return Remote(self._repo, cremote[0])
|
||||||
@@ -557,3 +530,36 @@ class RemoteCollection(object):
|
|||||||
check_error(err)
|
check_error(err)
|
||||||
|
|
||||||
return Remote(self._repo, cremote[0])
|
return Remote(self._repo, cremote[0])
|
||||||
|
|
||||||
|
def rename(self, name, new_name):
|
||||||
|
"""rename(name, new_name) -> [str]
|
||||||
|
|
||||||
|
Rename a remote in the configuration. The refspecs in strandard
|
||||||
|
format will be renamed.
|
||||||
|
|
||||||
|
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("Current remote name must be a non-empty string")
|
||||||
|
|
||||||
|
if not new_name:
|
||||||
|
raise ValueError("New remote name must be a non-empty string")
|
||||||
|
|
||||||
|
problems = ffi.new('git_strarray *')
|
||||||
|
err = C.git_remote_rename(problems, self._repo._repo, to_bytes(name), to_bytes(new_name))
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
ret = strarray_to_strings(problems)
|
||||||
|
C.git_strarray_free(problems)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def delete(self, name):
|
||||||
|
"""Remove a remote from the configuration
|
||||||
|
|
||||||
|
All remote-tracking branches and configuration settings for the remote will be removed.
|
||||||
|
"""
|
||||||
|
err = C.git_remote_delete(self._repo._repo, to_bytes(name))
|
||||||
|
check_error(err)
|
||||||
|
@@ -57,7 +57,18 @@ class Repository(_Repository):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(Repository, self).__init__(*args, **kwargs)
|
super(Repository, self).__init__(*args, **kwargs)
|
||||||
|
self._common_init()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _from_c(cls, ptr, owned):
|
||||||
|
cptr = ffi.new('git_repository **')
|
||||||
|
cptr[0] = ptr
|
||||||
|
repo = cls.__new__(cls)
|
||||||
|
super(cls, repo)._from_c(bytes(ffi.buffer(cptr)[:]), owned)
|
||||||
|
repo._common_init()
|
||||||
|
return repo
|
||||||
|
|
||||||
|
def _common_init(self):
|
||||||
self.remotes = RemoteCollection(self)
|
self.remotes = RemoteCollection(self)
|
||||||
|
|
||||||
# Get the pointer as the contents of a buffer and store it for
|
# Get the pointer as the contents of a buffer and store it for
|
||||||
|
@@ -210,7 +210,6 @@ moduleinit(PyObject* m)
|
|||||||
ADD_CONSTANT_INT(m, GIT_OBJ_BLOB)
|
ADD_CONSTANT_INT(m, GIT_OBJ_BLOB)
|
||||||
ADD_CONSTANT_INT(m, GIT_OBJ_TAG)
|
ADD_CONSTANT_INT(m, GIT_OBJ_TAG)
|
||||||
/* Valid modes for index and tree entries. */
|
/* Valid modes for index and tree entries. */
|
||||||
ADD_CONSTANT_INT(m, GIT_FILEMODE_NEW)
|
|
||||||
ADD_CONSTANT_INT(m, GIT_FILEMODE_TREE)
|
ADD_CONSTANT_INT(m, GIT_FILEMODE_TREE)
|
||||||
ADD_CONSTANT_INT(m, GIT_FILEMODE_BLOB)
|
ADD_CONSTANT_INT(m, GIT_FILEMODE_BLOB)
|
||||||
ADD_CONSTANT_INT(m, GIT_FILEMODE_BLOB_EXECUTABLE)
|
ADD_CONSTANT_INT(m, GIT_FILEMODE_BLOB_EXECUTABLE)
|
||||||
@@ -347,7 +346,7 @@ moduleinit(PyObject* m)
|
|||||||
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UNBORN)
|
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UNBORN)
|
||||||
|
|
||||||
/* Global initialization of libgit2 */
|
/* Global initialization of libgit2 */
|
||||||
git_threads_init();
|
git_libgit2_init();
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@@ -55,6 +55,9 @@ extern PyTypeObject ReferenceType;
|
|||||||
extern PyTypeObject NoteType;
|
extern PyTypeObject NoteType;
|
||||||
extern PyTypeObject NoteIterType;
|
extern PyTypeObject NoteIterType;
|
||||||
|
|
||||||
|
/* forward-declaration for Repsository._from_c() */
|
||||||
|
PyTypeObject RepositoryType;
|
||||||
|
|
||||||
git_otype
|
git_otype
|
||||||
int_to_loose_object_type(int type_id)
|
int_to_loose_object_type(int type_id)
|
||||||
{
|
{
|
||||||
@@ -88,19 +91,62 @@ Repository_init(Repository *self, PyObject *args, PyObject *kwds)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->owned = 1;
|
||||||
self->config = NULL;
|
self->config = NULL;
|
||||||
self->index = NULL;
|
self->index = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(Repository__from_c__doc__, "Init a Repository from a pointer. For internal use only.");
|
||||||
|
PyObject *
|
||||||
|
Repository__from_c(Repository *py_repo, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *py_pointer, *py_free;
|
||||||
|
char *buffer;
|
||||||
|
Py_ssize_t len;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
py_repo->repo = NULL;
|
||||||
|
py_repo->config = NULL;
|
||||||
|
py_repo->index = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "OO!", &py_pointer, &PyBool_Type, &py_free))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
err = PyBytes_AsStringAndSize(py_pointer, &buffer, &len);
|
||||||
|
if (err < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (len != sizeof(git_repository *)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "invalid pointer length");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
py_repo->repo = *((git_repository **) buffer);
|
||||||
|
py_repo->owned = py_free == Py_True;
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(Repository__disown__doc__, "Mark the object as not-owned by us. For internal use only.");
|
||||||
|
PyObject *
|
||||||
|
Repository__disown(Repository *py_repo)
|
||||||
|
{
|
||||||
|
py_repo->owned = 0;
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Repository_dealloc(Repository *self)
|
Repository_dealloc(Repository *self)
|
||||||
{
|
{
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
Py_CLEAR(self->index);
|
Py_CLEAR(self->index);
|
||||||
Py_CLEAR(self->config);
|
Py_CLEAR(self->config);
|
||||||
|
|
||||||
|
if (self->owned)
|
||||||
git_repository_free(self->repo);
|
git_repository_free(self->repo);
|
||||||
|
|
||||||
Py_TYPE(self)->tp_free(self);
|
Py_TYPE(self)->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +572,7 @@ Repository_merge_analysis(Repository *self, PyObject *py_id)
|
|||||||
int err;
|
int err;
|
||||||
size_t len;
|
size_t len;
|
||||||
git_oid id;
|
git_oid id;
|
||||||
git_merge_head *merge_head;
|
git_annotated_commit *commit;
|
||||||
git_merge_analysis_t analysis;
|
git_merge_analysis_t analysis;
|
||||||
git_merge_preference_t preference;
|
git_merge_preference_t preference;
|
||||||
|
|
||||||
@@ -534,12 +580,12 @@ Repository_merge_analysis(Repository *self, PyObject *py_id)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
err = git_merge_head_from_id(&merge_head, self->repo, &id);
|
err = git_annotated_commit_lookup(&commit, self->repo, &id);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
err = git_merge_analysis(&analysis, &preference, self->repo, (const git_merge_head **) &merge_head, 1);
|
err = git_merge_analysis(&analysis, &preference, self->repo, (const git_annotated_commit **) &commit, 1);
|
||||||
git_merge_head_free(merge_head);
|
git_annotated_commit_free(commit);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
@@ -561,7 +607,7 @@ PyDoc_STRVAR(Repository_merge__doc__,
|
|||||||
PyObject *
|
PyObject *
|
||||||
Repository_merge(Repository *self, PyObject *py_oid)
|
Repository_merge(Repository *self, PyObject *py_oid)
|
||||||
{
|
{
|
||||||
git_merge_head *oid_merge_head;
|
git_annotated_commit *commit;
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
int err;
|
int err;
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -572,16 +618,16 @@ Repository_merge(Repository *self, PyObject *py_oid)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
err = git_merge_head_from_id(&oid_merge_head, self->repo, &oid);
|
err = git_annotated_commit_lookup(&commit, self->repo, &oid);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||||
err = git_merge(self->repo,
|
err = git_merge(self->repo,
|
||||||
(const git_merge_head **)&oid_merge_head, 1,
|
(const git_annotated_commit **)&commit, 1,
|
||||||
&merge_opts, &checkout_opts);
|
&merge_opts, &checkout_opts);
|
||||||
|
|
||||||
git_merge_head_free(oid_merge_head);
|
git_annotated_commit_free(commit);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
@@ -1225,7 +1271,7 @@ Repository_TreeBuilder(Repository *self, PyObject *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = git_treebuilder_create(&bld, tree);
|
err = git_treebuilder_new(&bld, self->repo, tree);
|
||||||
if (must_free != NULL)
|
if (must_free != NULL)
|
||||||
git_tree_free(must_free);
|
git_tree_free(must_free);
|
||||||
|
|
||||||
@@ -1318,8 +1364,8 @@ Repository_create_note(Repository *self, PyObject* args)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
err = git_note_create(¬e_id, self->repo, py_author->signature,
|
err = git_note_create(¬e_id, self->repo, ref, py_author->signature,
|
||||||
py_committer->signature, ref,
|
py_committer->signature,
|
||||||
&annotated_id, message, force);
|
&annotated_id, message, force);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
@@ -1380,7 +1426,7 @@ Repository_reset(Repository *self, PyObject* args)
|
|||||||
|
|
||||||
err = git_object_lookup_prefix(&target, self->repo, &oid, len,
|
err = git_object_lookup_prefix(&target, self->repo, &oid, len,
|
||||||
GIT_OBJ_ANY);
|
GIT_OBJ_ANY);
|
||||||
err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL, NULL);
|
err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL, NULL, NULL);
|
||||||
git_object_free(target);
|
git_object_free(target);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set_oid(err, &oid, len);
|
return Error_set_oid(err, &oid, len);
|
||||||
@@ -1415,6 +1461,8 @@ PyMethodDef Repository_methods[] = {
|
|||||||
METHOD(Repository, listall_branches, METH_VARARGS),
|
METHOD(Repository, listall_branches, METH_VARARGS),
|
||||||
METHOD(Repository, create_branch, METH_VARARGS),
|
METHOD(Repository, create_branch, METH_VARARGS),
|
||||||
METHOD(Repository, reset, METH_VARARGS),
|
METHOD(Repository, reset, METH_VARARGS),
|
||||||
|
METHOD(Repository, _from_c, METH_VARARGS),
|
||||||
|
METHOD(Repository, _disown, METH_NOARGS),
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -88,7 +88,7 @@ TreeBuilder_write(TreeBuilder *self)
|
|||||||
int err;
|
int err;
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
|
|
||||||
err = git_treebuilder_write(&oid, self->repo->repo, self->bld);
|
err = git_treebuilder_write(&oid, self->bld);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
|
@@ -32,8 +32,8 @@
|
|||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <git2.h>
|
#include <git2.h>
|
||||||
|
|
||||||
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 21)
|
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 22)
|
||||||
#error You need a compatible libgit2 version (v0.21.x)
|
#error You need a compatible libgit2 version (v0.22.x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -47,6 +47,7 @@ typedef struct {
|
|||||||
git_repository *repo;
|
git_repository *repo;
|
||||||
PyObject *index; /* It will be None for a bare repository */
|
PyObject *index; /* It will be None for a bare repository */
|
||||||
PyObject *config; /* It will be None for a bare repository */
|
PyObject *config; /* It will be None for a bare repository */
|
||||||
|
int owned; /* _from_c() sometimes means we don't own the C pointer */
|
||||||
} Repository;
|
} Repository;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -71,19 +71,19 @@ class RepositoryTest(utils.RepoTestCase):
|
|||||||
remote = self.repo.remotes[1]
|
remote = self.repo.remotes[1]
|
||||||
|
|
||||||
self.assertEqual(name, remote.name)
|
self.assertEqual(name, remote.name)
|
||||||
remote.delete()
|
self.repo.remotes.delete(remote.name)
|
||||||
self.assertEqual(1, len(self.repo.remotes))
|
self.assertEqual(1, len(self.repo.remotes))
|
||||||
|
|
||||||
def test_remote_rename(self):
|
def test_remote_rename(self):
|
||||||
remote = self.repo.remotes[0]
|
remote = self.repo.remotes[0]
|
||||||
|
|
||||||
self.assertEqual(REMOTE_NAME, remote.name)
|
self.assertEqual(REMOTE_NAME, remote.name)
|
||||||
problems = remote.rename('new')
|
problems = self.repo.remotes.rename(remote.name, "new")
|
||||||
self.assertEqual([], problems)
|
self.assertEqual([], problems)
|
||||||
self.assertEqual('new', remote.name)
|
self.assertNotEqual('new', remote.name)
|
||||||
|
|
||||||
self.assertRaises(ValueError, remote.rename, '')
|
self.assertRaises(ValueError, self.repo.remotes.rename, '', '')
|
||||||
self.assertRaises(ValueError, remote.rename, None)
|
self.assertRaises(ValueError, self.repo.remotes.rename, None, None)
|
||||||
|
|
||||||
|
|
||||||
def test_remote_set_url(self):
|
def test_remote_set_url(self):
|
||||||
@@ -183,13 +183,9 @@ class RepositoryTest(utils.RepoTestCase):
|
|||||||
|
|
||||||
def test_remote_save(self):
|
def test_remote_save(self):
|
||||||
remote = self.repo.remotes[0]
|
remote = self.repo.remotes[0]
|
||||||
|
|
||||||
remote.rename('new-name')
|
|
||||||
remote.url = 'http://example.com/test.git'
|
remote.url = 'http://example.com/test.git'
|
||||||
|
|
||||||
remote.save()
|
remote.save()
|
||||||
|
|
||||||
self.assertEqual('new-name', self.repo.remotes[0].name)
|
|
||||||
self.assertEqual('http://example.com/test.git',
|
self.assertEqual('http://example.com/test.git',
|
||||||
self.repo.remotes[0].url)
|
self.repo.remotes[0].url)
|
||||||
|
|
||||||
@@ -278,11 +274,11 @@ class PushTestCase(unittest.TestCase):
|
|||||||
'refs/heads/master', tip.author, tip.author, 'empty commit',
|
'refs/heads/master', tip.author, tip.author, 'empty commit',
|
||||||
tip.tree.id, [tip.id]
|
tip.tree.id, [tip.id]
|
||||||
)
|
)
|
||||||
self.remote.push('refs/heads/master')
|
self.remote.push(['refs/heads/master'])
|
||||||
self.assertEqual(self.origin[self.origin.head.target].id, oid)
|
self.assertEqual(self.origin[self.origin.head.target].id, oid)
|
||||||
|
|
||||||
def test_push_when_up_to_date_succeeds(self):
|
def test_push_when_up_to_date_succeeds(self):
|
||||||
self.remote.push('refs/heads/master')
|
self.remote.push(['refs/heads/master'])
|
||||||
origin_tip = self.origin[self.origin.head.target].id
|
origin_tip = self.origin[self.origin.head.target].id
|
||||||
clone_tip = self.clone[self.clone.head.target].id
|
clone_tip = self.clone[self.clone.head.target].id
|
||||||
self.assertEqual(origin_tip, clone_tip)
|
self.assertEqual(origin_tip, clone_tip)
|
||||||
@@ -298,7 +294,8 @@ class PushTestCase(unittest.TestCase):
|
|||||||
'refs/heads/master', tip.author, tip.author, 'other commit',
|
'refs/heads/master', tip.author, tip.author, 'other commit',
|
||||||
tip.tree.id, [tip.id]
|
tip.tree.id, [tip.id]
|
||||||
)
|
)
|
||||||
self.assertRaises(pygit2.GitError, self.remote.push, 'refs/heads/master')
|
|
||||||
|
self.assertRaises(pygit2.GitError, self.remote.push, ['refs/heads/master'])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@@ -41,7 +41,7 @@ import sys
|
|||||||
|
|
||||||
# Import from pygit2
|
# Import from pygit2
|
||||||
from pygit2 import GIT_OBJ_ANY, GIT_OBJ_BLOB, GIT_OBJ_COMMIT
|
from pygit2 import GIT_OBJ_ANY, GIT_OBJ_BLOB, GIT_OBJ_COMMIT
|
||||||
from pygit2 import init_repository, clone_repository, clone_into, discover_repository
|
from pygit2 import init_repository, clone_repository, discover_repository
|
||||||
from pygit2 import Oid, Reference, hashfile
|
from pygit2 import Oid, Reference, hashfile
|
||||||
import pygit2
|
import pygit2
|
||||||
from . import utils
|
from . import utils
|
||||||
@@ -440,19 +440,22 @@ class CloneRepositoryTest(utils.NoRepoTestCase):
|
|||||||
self.assertFalse(repo.is_empty)
|
self.assertFalse(repo.is_empty)
|
||||||
self.assertTrue(repo.is_bare)
|
self.assertTrue(repo.is_bare)
|
||||||
|
|
||||||
def test_clone_remote_name(self):
|
def test_clone_repository_and_remote_callbacks(self):
|
||||||
repo_path = "./test/data/testrepo.git/"
|
src_repo_relpath = "./test/data/testrepo.git/"
|
||||||
repo = clone_repository(
|
repo_path = os.path.join(self._temp_dir, "clone-into")
|
||||||
repo_path, self._temp_dir, remote_name="custom_remote")
|
url = 'file://' + os.path.realpath(src_repo_relpath)
|
||||||
self.assertFalse(repo.is_empty)
|
|
||||||
self.assertEqual(repo.remotes[0].name, "custom_remote")
|
|
||||||
|
|
||||||
def test_clone_into(self):
|
def create_repository(path, bare):
|
||||||
repo_path = "./test/data/testrepo.git/"
|
return init_repository(path, bare)
|
||||||
repo = init_repository(os.path.join(self._temp_dir, "clone-into"))
|
|
||||||
remote = repo.create_remote("origin", 'file://' + os.path.realpath(repo_path))
|
# here we override the name
|
||||||
clone_into(repo, remote)
|
def create_remote(repo, name, url):
|
||||||
self.assertTrue('refs/remotes/origin/master' in repo.listall_references())
|
return repo.remotes.create("custom_remote", url)
|
||||||
|
|
||||||
|
repo = clone_repository(url, repo_path, repository=create_repository, remote=create_remote)
|
||||||
|
self.assertFalse(repo.is_empty)
|
||||||
|
self.assertTrue('refs/remotes/custom_remote/master' in repo.listall_references())
|
||||||
|
self.assertIsNotNone(repo.remotes["custom_remote"])
|
||||||
|
|
||||||
def test_clone_with_credentials(self):
|
def test_clone_with_credentials(self):
|
||||||
credentials = pygit2.UserPass("libgit2", "libgit2")
|
credentials = pygit2.UserPass("libgit2", "libgit2")
|
||||||
|
Reference in New Issue
Block a user