Merge tag '0.22.0' into debian/unstable
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
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/
|
||||
|
||||
mkdir build && cd build
|
||||
|
||||
60
README.rst
60
README.rst
@@ -2,7 +2,7 @@
|
||||
pygit2 - libgit2 bindings in Python
|
||||
######################################################################
|
||||
|
||||
.. image:: https://secure.travis-ci.org/libgit2/pygit2.png
|
||||
.. image:: https://secure.travis-ci.org/libgit2/pygit2.svg
|
||||
:target: http://travis-ci.org/libgit2/pygit2
|
||||
|
||||
Pygit2 is a set of Python bindings to the libgit2 shared library, libgit2
|
||||
@@ -25,6 +25,62 @@ How to install
|
||||
Changelog
|
||||
==============
|
||||
|
||||
0.22.0 (2015-01-16)
|
||||
-------------------
|
||||
|
||||
New:
|
||||
|
||||
- Update to libgit2 v0.22
|
||||
`#459 <https://github.com/libgit2/pygit2/pull/459>`_
|
||||
|
||||
- Add support for libgit2 feature detection
|
||||
(new ``pygit2.features`` and ``pygit2.GIT_FEATURE_*``)
|
||||
`#475 <https://github.com/libgit2/pygit2/pull/475>`_
|
||||
|
||||
- New ``Repository.remotes`` (``RemoteCollection``)
|
||||
`#447 <https://github.com/libgit2/pygit2/pull/447>`_
|
||||
|
||||
API Changes:
|
||||
|
||||
- Prototype of ``clone_repository`` changed, check documentation
|
||||
|
||||
- Removed ``clone_into``, use ``clone_repository`` with callbacks instead
|
||||
|
||||
- Use ``Repository.remotes.rename(name, new_name)`` instead of
|
||||
``Remote.rename(new_name)``
|
||||
|
||||
- Use ``Repository.remotes.delete(name)`` instead of ``Remote.delete()``
|
||||
|
||||
- Now ``Remote.push(...)`` takes a list of refspecs instead of just one
|
||||
|
||||
- Change ``Patch.old_id``, ``Patch.new_id``, ``Note.annotated_id``,
|
||||
``RefLogEntry.oid_old`` and ``RefLogEntry.oid_new`` to be ``Oid`` objects
|
||||
instead of strings
|
||||
`#449 <https://github.com/libgit2/pygit2/pull/449>`_
|
||||
|
||||
Other:
|
||||
|
||||
- Fix ``init_repository`` when passing optional parameters ``workdir_path``,
|
||||
``description``, ``template_path``, ``initial_head`` or ``origin_url``
|
||||
`#466 <https://github.com/libgit2/pygit2/issues/466>`_
|
||||
`#471 <https://github.com/libgit2/pygit2/pull/471>`_
|
||||
|
||||
- Fix use-after-free when patch outlives diff
|
||||
`#457 <https://github.com/libgit2/pygit2/issues/457>`_
|
||||
`#461 <https://github.com/libgit2/pygit2/pull/461>`_
|
||||
`#474 <https://github.com/libgit2/pygit2/pull/474>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#456 <https://github.com/libgit2/pygit2/issues/456>`_
|
||||
`#462 <https://github.com/libgit2/pygit2/pull/462>`_
|
||||
`#465 <https://github.com/libgit2/pygit2/pull/465>`_
|
||||
`#472 <https://github.com/libgit2/pygit2/pull/472>`_
|
||||
`#473 <https://github.com/libgit2/pygit2/pull/473>`_
|
||||
|
||||
- Make the GPL exception explicit in setup.py
|
||||
`#450 <https://github.com/libgit2/pygit2/pull/450>`_
|
||||
|
||||
|
||||
0.21.4 (2014-11-04)
|
||||
-------------------
|
||||
|
||||
@@ -446,7 +502,7 @@ Other: `#331 <https://github.com/libgit2/pygit2/pull/331>`_
|
||||
Authors
|
||||
==============
|
||||
|
||||
77 developers have contributed at least 1 commit to pygit2::
|
||||
83 developers have contributed at least 1 commit to pygit2::
|
||||
|
||||
J. David Ibáñez Sebastian Thiel András Veres-Szentkirályi
|
||||
Carlos Martín Nieto Fraser Tweedale Ash Berlin
|
||||
|
||||
@@ -50,9 +50,9 @@ copyright = u'2010-2014 The pygit2 contributors'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.21'
|
||||
version = '0.22'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.21.4'
|
||||
release = '0.22.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
8
docs/features.rst
Normal file
8
docs/features.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
**********************************************************************
|
||||
Feature detection
|
||||
**********************************************************************
|
||||
|
||||
.. py:data:: pygit2.features
|
||||
|
||||
This variable contains a combination of `GIT_FEATURE_*` flags,
|
||||
indicating which features a particular build of libgit2 supports.
|
||||
@@ -18,7 +18,7 @@ library that has been built against. The version number has a
|
||||
.. py:data:: LIBGIT2_VER_MAJOR
|
||||
|
||||
Integer value of the major version number. For example, for the version
|
||||
``0.21.2``::
|
||||
``0.22.0``::
|
||||
|
||||
>>> print LIBGIT2_VER_MAJOR
|
||||
0
|
||||
@@ -26,25 +26,25 @@ library that has been built against. The version number has a
|
||||
.. py:data:: LIBGIT2_VER_MINOR
|
||||
|
||||
Integer value of the minor version number. For example, for the version
|
||||
``0.21.2``::
|
||||
``0.22.0``::
|
||||
|
||||
>>> print LIBGIT2_VER_MINOR
|
||||
21
|
||||
22
|
||||
|
||||
.. py:data:: LIBGIT2_VER_REVISION
|
||||
|
||||
Integer value of the revision version number. For example, for the version
|
||||
``0.21.2``::
|
||||
``0.22.0``::
|
||||
|
||||
>>> print LIBGIT2_VER_REVISION
|
||||
1
|
||||
0
|
||||
|
||||
.. py:data:: LIBGIT2_VERSION
|
||||
|
||||
The libgit2 version number as a string::
|
||||
|
||||
>>> print LIBGIT2_VERSION
|
||||
'0.21.2'
|
||||
'0.22.0'
|
||||
|
||||
Errors
|
||||
======
|
||||
|
||||
@@ -47,6 +47,7 @@ Usage guide:
|
||||
remotes
|
||||
blame
|
||||
settings
|
||||
features
|
||||
|
||||
|
||||
Indices and tables
|
||||
|
||||
@@ -14,8 +14,9 @@ Requirements
|
||||
============
|
||||
|
||||
- Python 2.7, 3.2+ or pypy (including the development headers)
|
||||
- Libgit2 v0.21.1+
|
||||
- Libgit2 v0.22.x
|
||||
- cffi 0.8.1+
|
||||
- Libssh2, optional, used for SSH network operations.
|
||||
|
||||
.. warning::
|
||||
|
||||
@@ -33,11 +34,11 @@ while the last number |lq| *.micro* |rq| auto-increments independently.
|
||||
|
||||
As illustration see this table of compatible releases:
|
||||
|
||||
+-----------+---------------------------------------+------------------------------+--------------+
|
||||
|**libgit2**|0.21.1, 0.21.2 |0.20.0 |0.19.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|
|
||||
+-----------+---------------------------------------+------------------------------+--------------+
|
||||
+-----------+--------+----------------------------------------+-------------------------------+
|
||||
|**libgit2**| 0.22.0 | 0.21.1, 0.21.2 |0.20.0 |
|
||||
+-----------+--------+----------------------------------------+-------------------------------+
|
||||
|**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::
|
||||
|
||||
@@ -54,9 +55,9 @@ directory, do:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.21.2.tar.gz
|
||||
$ tar xzf v0.21.2.tar.gz
|
||||
$ cd libgit2-0.21.2/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.22.0.tar.gz
|
||||
$ tar xzf v0.22.0.tar.gz
|
||||
$ cd libgit2-0.22.0/
|
||||
$ cmake .
|
||||
$ make
|
||||
$ sudo make install
|
||||
@@ -138,9 +139,9 @@ Install libgit2 (see we define the installation prefix):
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.21.2.tar.gz
|
||||
$ tar xzf v0.21.2.tar.gz
|
||||
$ cd libgit2-0.21.2/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.22.0.tar.gz
|
||||
$ tar xzf v0.22.0.tar.gz
|
||||
$ cd libgit2-0.22.0/
|
||||
$ cmake . -DCMAKE_INSTALL_PREFIX=$LIBGIT2
|
||||
$ make
|
||||
$ make install
|
||||
@@ -193,9 +194,9 @@ from a bash shell:
|
||||
.. code-block:: sh
|
||||
|
||||
$ export LIBGIT2=C:/Dev/libgit2
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.21.2.tar.gz
|
||||
$ tar xzf v0.21.2.tar.gz
|
||||
$ cd libgit2-0.21.2/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.22.0.tar.gz
|
||||
$ tar xzf v0.22.0.tar.gz
|
||||
$ cd libgit2-0.22.0/
|
||||
$ cmake . -DSTDCALL=OFF -DCMAKE_INSTALL_PREFIX=$LIBGIT2 -G "Visual Studio 9 2008"
|
||||
$ cmake --build . --config release --target install
|
||||
$ ctest -v
|
||||
|
||||
@@ -17,7 +17,6 @@ Main porcelain commands
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
git-branch (List, create, or delete branches.) <recipes/git-branch>
|
||||
git-init (Create an empty git repository or reinitialize an existing one.) <recipes/git-init>
|
||||
git-log (Show commit logs.) <recipes/git-log>
|
||||
git-show (Show various types of objects.) <recipes/git-show>
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
**********************************************************************
|
||||
git-branch
|
||||
**********************************************************************
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Listing branches
|
||||
----------------------------------------------------------------------
|
||||
|
||||
======================================================================
|
||||
List all branches
|
||||
======================================================================
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$> git branch
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> regex = re.compile('^refs/heads/')
|
||||
>>> branches = filter(lambda r: regex.match(r), repo.listall_references())
|
||||
|
||||
`Note that the next release will probably allow` ``repo.listall_branches()``.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
References
|
||||
----------------------------------------------------------------------
|
||||
|
||||
- git-branch_.
|
||||
|
||||
.. _git-branch: https://www.kernel.org/pub/software/scm/git/docs/git-branch.html
|
||||
@@ -2,10 +2,18 @@
|
||||
Remotes
|
||||
**********************************************************************
|
||||
|
||||
.. py:attribute:: Repository.remotes
|
||||
|
||||
The collection of configured remotes, an instance of
|
||||
:py:class:`pygit2.remote.RemoteCollection`
|
||||
|
||||
.. autoattribute:: pygit2.Repository.remotes
|
||||
.. automethod:: pygit2.Repository.create_remote
|
||||
|
||||
The remote collection
|
||||
==========================
|
||||
|
||||
.. autoclass:: pygit2.remote.RemoteCollection
|
||||
:members:
|
||||
|
||||
The Remote type
|
||||
====================
|
||||
@@ -24,6 +32,10 @@ This class contains the data which is available to us during a fetch.
|
||||
The Refspec type
|
||||
===================
|
||||
|
||||
Refspecs objects are not constructed directly, but returned by
|
||||
:meth:`pygit2.Remote.get_refspec`. To create a new a refspec on a Remote, use
|
||||
:meth:`pygit2.Remote.add_fetch` or :meth:`pygit2.Remote.add_push`.
|
||||
|
||||
.. autoclass:: pygit2.refspec.Refspec
|
||||
:members:
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ from .index import Index, IndexEntry
|
||||
from .remote import Remote, get_credentials
|
||||
from .repository import Repository
|
||||
from .settings import Settings
|
||||
from .utils import to_bytes
|
||||
from .utils import to_bytes, to_str
|
||||
from ._utils import __version__
|
||||
|
||||
|
||||
@@ -86,11 +86,26 @@ def init_repository(path, bare=False,
|
||||
C.git_repository_init_init_options(options, C.GIT_REPOSITORY_INIT_OPTIONS_VERSION)
|
||||
options.flags = flags
|
||||
options.mode = mode
|
||||
options.workdir_path = to_bytes(workdir_path)
|
||||
options.description = to_bytes(description)
|
||||
options.template_path = to_bytes(template_path)
|
||||
options.initial_head = to_bytes(initial_head)
|
||||
options.origin_url = to_bytes(origin_url)
|
||||
|
||||
if workdir_path:
|
||||
workdir_path_ref = ffi.new('char []', to_bytes(workdir_path))
|
||||
options.workdir_path = workdir_path_ref
|
||||
|
||||
if description:
|
||||
description_ref = ffi.new('char []', to_bytes(description))
|
||||
options.description = description_ref
|
||||
|
||||
if template_path:
|
||||
template_path_ref = ffi.new('char []', to_bytes(template_path))
|
||||
options.template_path = template_path_ref
|
||||
|
||||
if initial_head:
|
||||
initial_head_ref = ffi.new('char []', to_bytes(initial_head))
|
||||
options.initial_head = initial_head_ref
|
||||
|
||||
if origin_url:
|
||||
origin_url_ref = ffi.new('char []', to_bytes(origin_url))
|
||||
options.origin_url = origin_url_ref
|
||||
|
||||
# Call
|
||||
crepository = ffi.new('git_repository **')
|
||||
@@ -98,7 +113,7 @@ def init_repository(path, bare=False,
|
||||
check_error(err)
|
||||
|
||||
# Ok
|
||||
return Repository(path)
|
||||
return Repository(to_str(path))
|
||||
|
||||
|
||||
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
||||
@@ -108,7 +123,7 @@ def _credentials_cb(cred_out, url, username_from_url, allowed, data):
|
||||
d = ffi.from_handle(data)
|
||||
|
||||
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]
|
||||
except Exception as e:
|
||||
d['exception'] = e
|
||||
@@ -116,10 +131,54 @@ def _credentials_cb(cred_out, url, username_from_url, allowed, data):
|
||||
|
||||
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(
|
||||
url, path, bare=False, ignore_cert_errors=False,
|
||||
remote_name="origin", checkout_branch=None, credentials=None):
|
||||
url, path, bare=False, repository=None, remote=None,
|
||||
checkout_branch=None, credentials=None, certificate=None):
|
||||
"""Clones a new Git repository from *url* in the given *path*.
|
||||
|
||||
Returns a Repository class pointing to the newly cloned repository.
|
||||
@@ -130,7 +189,9 @@ def clone_repository(
|
||||
|
||||
: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
|
||||
clone. The default is to use the remote's default branch.
|
||||
@@ -138,8 +199,22 @@ def clone_repository(
|
||||
:param callable credentials: authentication to use if the remote
|
||||
requires it
|
||||
|
||||
:param callable certificate: callback to verify the host's
|
||||
certificate or fingerprint.
|
||||
|
||||
: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 *')
|
||||
@@ -149,7 +224,10 @@ def clone_repository(
|
||||
|
||||
# Data, let's use a dict as we don't really want much more
|
||||
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)
|
||||
|
||||
# Perform the initialization with the version we compiled
|
||||
@@ -161,48 +239,36 @@ def clone_repository(
|
||||
checkout_branch_ref = ffi.new('char []', to_bytes(branch))
|
||||
opts.checkout_branch = checkout_branch_ref
|
||||
|
||||
remote_name_ref = ffi.new('char []', to_bytes(remote_name))
|
||||
opts.remote_name = remote_name_ref
|
||||
if repository:
|
||||
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
|
||||
if credentials:
|
||||
opts.remote_callbacks.credentials = _credentials_cb
|
||||
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)
|
||||
C.git_repository_free(crepo[0])
|
||||
|
||||
if 'exception' in d:
|
||||
raise d['exception']
|
||||
|
||||
check_error(err)
|
||||
|
||||
return Repository(path)
|
||||
|
||||
|
||||
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)
|
||||
return Repository._from_c(crepo[0], owned=True)
|
||||
|
||||
settings = Settings()
|
||||
|
||||
features = C.git_libgit2_features()
|
||||
GIT_FEATURE_THREADS = C.GIT_FEATURE_THREADS
|
||||
GIT_FEATURE_HTTPS = C.GIT_FEATURE_HTTPS
|
||||
GIT_FEATURE_SSH = C.GIT_FEATURE_SSH
|
||||
|
||||
@@ -43,7 +43,7 @@ import sys
|
||||
#
|
||||
# The version number of pygit2
|
||||
#
|
||||
__version__ = '0.21.4'
|
||||
__version__ = '0.22.0'
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -65,7 +65,8 @@ class Keypair(object):
|
||||
remote server
|
||||
:param str pubkey: the path to the user's public key file
|
||||
:param str privkey: the path to the user's private key file
|
||||
:param str passphrase: the password used to decrypt the private key file
|
||||
:param str passphrase: the password used to decrypt the private key file,
|
||||
or empty string if no passphrase is required.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
133
pygit2/decl.h
133
pygit2/decl.h
@@ -1,7 +1,6 @@
|
||||
typedef ... git_repository;
|
||||
typedef ... git_remote;
|
||||
typedef ... git_refspec;
|
||||
typedef ... git_push;
|
||||
typedef ... git_cred;
|
||||
typedef ... git_object;
|
||||
typedef ... git_tree;
|
||||
@@ -74,6 +73,12 @@ typedef struct git_signature {
|
||||
git_time when;
|
||||
} git_signature;
|
||||
|
||||
#define GIT_FEATURE_THREADS ...
|
||||
#define GIT_FEATURE_HTTPS ...
|
||||
#define GIT_FEATURE_SSH ...
|
||||
|
||||
int git_libgit2_features(void);
|
||||
|
||||
const git_error * giterr_last(void);
|
||||
|
||||
void git_strarray_free(git_strarray *array);
|
||||
@@ -106,9 +111,38 @@ typedef enum {
|
||||
GIT_CREDTYPE_SSH_KEY,
|
||||
GIT_CREDTYPE_SSH_CUSTOM,
|
||||
GIT_CREDTYPE_DEFAULT,
|
||||
GIT_CREDTYPE_SSH_INTERACTIVE,
|
||||
GIT_CREDTYPE_USERNAME,
|
||||
...
|
||||
} 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_cred_acquire_cb)(
|
||||
git_cred **cred,
|
||||
@@ -117,40 +151,59 @@ typedef int (*git_cred_acquire_cb)(
|
||||
unsigned int allowed_types,
|
||||
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 {
|
||||
unsigned int version;
|
||||
git_transport_message_cb sideband_progress;
|
||||
int (*completion)(git_remote_completion_type type, void *data);
|
||||
git_cred_acquire_cb credentials;
|
||||
git_transport_certificate_check_cb certificate_check;
|
||||
git_transfer_progress_cb transfer_progress;
|
||||
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;
|
||||
};
|
||||
|
||||
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_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(
|
||||
git_remote **out,
|
||||
git_repository *repo,
|
||||
const char *name,
|
||||
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);
|
||||
|
||||
const char * git_remote_name(const git_remote *remote);
|
||||
|
||||
int git_remote_rename(
|
||||
git_strarray *problems,
|
||||
git_remote *remote,
|
||||
const char *new_name);
|
||||
int git_remote_rename(git_strarray *problems, git_repository *repo, const char *name, 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, 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);
|
||||
int git_remote_add_push(git_remote *remote, const char *refspec);
|
||||
int git_remote_add_fetch(git_remote *remote, const char *refspec);
|
||||
@@ -167,22 +220,6 @@ int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array);
|
||||
|
||||
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_dst(const git_refspec *refspec);
|
||||
int git_refspec_force(const git_refspec *refspec);
|
||||
@@ -261,14 +298,12 @@ typedef int (*git_diff_notify_cb)(
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
uint32_t flags;
|
||||
|
||||
git_submodule_ignore_t ignore_submodules;
|
||||
git_strarray pathspec;
|
||||
git_diff_notify_cb notify_cb;
|
||||
void *notify_payload;
|
||||
|
||||
uint16_t context_lines;
|
||||
uint16_t interhunk_lines;
|
||||
uint32_t context_lines;
|
||||
uint32_t interhunk_lines;
|
||||
uint16_t id_abbrev;
|
||||
git_off_t max_size;
|
||||
const char *old_prefix;
|
||||
@@ -339,13 +374,6 @@ typedef struct git_checkout_options {
|
||||
const char *their_label;
|
||||
} 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_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);
|
||||
@@ -355,18 +383,38 @@ int git_checkout_index(git_repository *repo, git_index *index, const git_checkou
|
||||
* 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 {
|
||||
unsigned int version;
|
||||
|
||||
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_repository_create_cb repository_cb;
|
||||
void *repository_cb_payload;
|
||||
git_remote_create_cb remote_cb;
|
||||
void *remote_cb_payload;
|
||||
} git_clone_options;
|
||||
|
||||
#define GIT_CLONE_OPTIONS_VERSION ...
|
||||
@@ -377,13 +425,6 @@ int git_clone(git_repository **out,
|
||||
const char *local_path,
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ from .utils import to_bytes
|
||||
|
||||
|
||||
class Refspec(object):
|
||||
"""The constructor is for internal use only"""
|
||||
def __init__(self, owner, ptr):
|
||||
self._owner = owner
|
||||
self._refspec = ptr
|
||||
@@ -95,7 +96,7 @@ class Refspec(object):
|
||||
return self._transform(ref, C.git_refspec_transform)
|
||||
|
||||
def rtransform(self, ref):
|
||||
"""transform(str) -> str
|
||||
"""rtransform(str) -> str
|
||||
|
||||
Transform a reference name according to this refspec from the lhs
|
||||
to the rhs"""
|
||||
|
||||
217
pygit2/remote.py
217
pygit2/remote.py
@@ -121,6 +121,16 @@ class Remote(object):
|
||||
: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):
|
||||
"""The constructor is for internal use only"""
|
||||
|
||||
@@ -137,25 +147,6 @@ class Remote(object):
|
||||
|
||||
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
|
||||
def url(self):
|
||||
"""Url of the remote"""
|
||||
@@ -178,14 +169,6 @@ class Remote(object):
|
||||
err = C.git_remote_set_pushurl(self._remote, to_bytes(value))
|
||||
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):
|
||||
"""save()
|
||||
|
||||
@@ -231,7 +214,7 @@ class Remote(object):
|
||||
self._stored_exception = None
|
||||
|
||||
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:
|
||||
raise self._stored_exception
|
||||
|
||||
@@ -293,7 +276,7 @@ class Remote(object):
|
||||
def add_fetch(self, spec):
|
||||
"""add_fetch(refspec)
|
||||
|
||||
Add a fetch refspec to the remote"""
|
||||
Add a fetch refspec (str) to the remote"""
|
||||
|
||||
err = C.git_remote_add_fetch(self._remote, to_bytes(spec))
|
||||
check_error(err)
|
||||
@@ -301,32 +284,35 @@ class Remote(object):
|
||||
def add_push(self, spec):
|
||||
"""add_push(refspec)
|
||||
|
||||
Add a push refspec to the remote"""
|
||||
Add a push refspec (str) to the remote"""
|
||||
|
||||
err = C.git_remote_add_push(self._remote, to_bytes(spec))
|
||||
check_error(err)
|
||||
|
||||
@ffi.callback("int (*cb)(const char *ref, const char *msg, void *data)")
|
||||
def _push_cb(ref, msg, data):
|
||||
self = ffi.from_handle(data)
|
||||
if msg:
|
||||
self._bad_message = ffi.string(msg).decode()
|
||||
return 0
|
||||
def push(self, specs, signature=None, message=None):
|
||||
"""push(specs, signature, message)
|
||||
|
||||
def push(self, spec, signature=None, message=None):
|
||||
"""push(refspec, signature, message)
|
||||
Push the given refspec to the remote. Raises ``GitError`` on
|
||||
protocol error or unpack failure.
|
||||
|
||||
Push the given refspec to the remote. Raises ``GitError`` on error.
|
||||
|
||||
:param str spec: push refspec to use
|
||||
:param [str] specs: push refspecs to use
|
||||
:param Signature signature: signature to use when updating the tips
|
||||
:param str message: message to use when updating the tips
|
||||
|
||||
"""
|
||||
# Get the default callbacks first
|
||||
defaultcallbacks = ffi.new('git_remote_callbacks *')
|
||||
err = C.git_remote_init_callbacks(defaultcallbacks, 1)
|
||||
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
|
||||
callbacks = ffi.new('git_remote_callbacks *')
|
||||
callbacks.version = 1
|
||||
@@ -334,53 +320,23 @@ class Remote(object):
|
||||
callbacks.transfer_progress = self._transfer_progress_cb
|
||||
callbacks.update_tips = self._update_tips_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
|
||||
self._self_handle = ffi.new_handle(self)
|
||||
callbacks.payload = self._self_handle
|
||||
|
||||
err = C.git_remote_set_callbacks(self._remote, callbacks)
|
||||
|
||||
try:
|
||||
err = C.git_remote_set_callbacks(self._remote, callbacks)
|
||||
check_error(err)
|
||||
except:
|
||||
self._self_handle = None
|
||||
raise
|
||||
|
||||
|
||||
cpush = ffi.new('git_push **')
|
||||
err = C.git_push_new(cpush, self._remote)
|
||||
check_error(err)
|
||||
|
||||
push = cpush[0]
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
self._self_handle = None
|
||||
C.git_push_free(push)
|
||||
|
||||
# These functions exist to be called by the git_remote as
|
||||
# callbacks. They proxy the call to whatever the user set
|
||||
@@ -437,6 +393,23 @@ class Remote(object):
|
||||
|
||||
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,'
|
||||
'const char *username_from_url, unsigned int allowed_types,'
|
||||
'void *data)')
|
||||
@@ -494,3 +467,99 @@ def get_credentials(fn, url, username, allowed):
|
||||
check_error(err)
|
||||
|
||||
return ccred
|
||||
|
||||
class RemoteCollection(object):
|
||||
"""Collection of configured remotes
|
||||
|
||||
You can use this class to look up and manage the remotes configured
|
||||
in a repository. You can access repositories using index
|
||||
access. E.g. to look up the "origin" remote, you can use
|
||||
|
||||
>>> repo.remotes["origin"]
|
||||
"""
|
||||
|
||||
def __init__(self, repo):
|
||||
self._repo = repo;
|
||||
|
||||
def __len__(self):
|
||||
names = ffi.new('git_strarray *')
|
||||
|
||||
try:
|
||||
err = C.git_remote_list(names, self._repo._repo)
|
||||
check_error(err)
|
||||
|
||||
return names.count
|
||||
finally:
|
||||
C.git_strarray_free(names)
|
||||
|
||||
def __iter__(self):
|
||||
names = ffi.new('git_strarray *')
|
||||
|
||||
try:
|
||||
err = C.git_remote_list(names, self._repo._repo)
|
||||
check_error(err)
|
||||
|
||||
cremote = ffi.new('git_remote **')
|
||||
for i in range(names.count):
|
||||
err = C.git_remote_lookup(cremote, self._repo._repo, names.strings[i])
|
||||
check_error(err)
|
||||
|
||||
yield Remote(self._repo, cremote[0])
|
||||
finally:
|
||||
C.git_strarray_free(names)
|
||||
|
||||
def __getitem__(self, name):
|
||||
if isinstance(name, int):
|
||||
return list(self)[name]
|
||||
|
||||
cremote = ffi.new('git_remote **')
|
||||
err = C.git_remote_lookup(cremote, self._repo._repo, to_bytes(name))
|
||||
check_error(err)
|
||||
|
||||
return Remote(self._repo, cremote[0])
|
||||
|
||||
def create(self, name, url):
|
||||
"""create(name, url) -> Remote
|
||||
|
||||
Create a new remote with the given name and url.
|
||||
"""
|
||||
|
||||
cremote = ffi.new('git_remote **')
|
||||
|
||||
err = C.git_remote_create(cremote, self._repo._repo, to_bytes(name), to_bytes(url))
|
||||
check_error(err)
|
||||
|
||||
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)
|
||||
|
||||
@@ -48,7 +48,7 @@ from .config import Config
|
||||
from .errors import check_error
|
||||
from .ffi import ffi, C
|
||||
from .index import Index
|
||||
from .remote import Remote
|
||||
from .remote import RemoteCollection
|
||||
from .blame import Blame
|
||||
from .utils import to_bytes, is_string
|
||||
|
||||
@@ -57,6 +57,19 @@ class Repository(_Repository):
|
||||
|
||||
def __init__(self, *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)
|
||||
|
||||
# Get the pointer as the contents of a buffer and store it for
|
||||
# later access
|
||||
@@ -90,36 +103,11 @@ class Repository(_Repository):
|
||||
"""create_remote(name, url) -> Remote
|
||||
|
||||
Creates a new remote.
|
||||
|
||||
This method is deprecated, please use Remote.remotes.create()
|
||||
"""
|
||||
|
||||
cremote = ffi.new('git_remote **')
|
||||
|
||||
err = C.git_remote_create(cremote, self._repo, to_bytes(name),
|
||||
to_bytes(url))
|
||||
check_error(err)
|
||||
|
||||
return Remote(self, cremote[0])
|
||||
|
||||
@property
|
||||
def remotes(self):
|
||||
"""Returns all configured remotes"""
|
||||
|
||||
names = ffi.new('git_strarray *')
|
||||
|
||||
try:
|
||||
err = C.git_remote_list(names, self._repo)
|
||||
check_error(err)
|
||||
|
||||
l = [None] * names.count
|
||||
cremote = ffi.new('git_remote **')
|
||||
for i in range(names.count):
|
||||
err = C.git_remote_load(cremote, self._repo, names.strings[i])
|
||||
check_error(err)
|
||||
|
||||
l[i] = Remote(self, cremote[0])
|
||||
return l
|
||||
finally:
|
||||
C.git_strarray_free(names)
|
||||
return self.remotes.create(name, url)
|
||||
|
||||
#
|
||||
# Configuration
|
||||
|
||||
35
setup.py
35
setup.py
@@ -37,6 +37,8 @@ from distutils.command.build import build
|
||||
from distutils.command.sdist import sdist
|
||||
from distutils import log
|
||||
import os
|
||||
from os import getenv, listdir, pathsep
|
||||
from os.path import abspath, isfile
|
||||
from setuptools import setup, Extension, Command
|
||||
import shlex
|
||||
from subprocess import Popen, PIPE
|
||||
@@ -58,7 +60,7 @@ else:
|
||||
|
||||
libgit2_bin, libgit2_include, libgit2_lib = get_libgit2_paths()
|
||||
|
||||
pygit2_exts = [os.path.join('src', name) for name in os.listdir('src')
|
||||
pygit2_exts = [os.path.join('src', name) for name in listdir('src')
|
||||
if name.endswith('.c')]
|
||||
|
||||
|
||||
@@ -71,7 +73,6 @@ class TestCommand(Command):
|
||||
|
||||
def initialize_options(self):
|
||||
self.args = ''
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
@@ -80,7 +81,7 @@ class TestCommand(Command):
|
||||
self.run_command('build')
|
||||
bld = self.distribution.get_command_obj('build')
|
||||
# Add build_lib in to sys.path so that unittest can found DLLs and libs
|
||||
sys.path = [os.path.abspath(bld.build_lib)] + sys.path
|
||||
sys.path = [abspath(bld.build_lib)] + sys.path
|
||||
|
||||
test_argv0 = [sys.argv[0] + ' test --args=']
|
||||
# For transfering args to unittest, we have to split args by ourself,
|
||||
@@ -93,6 +94,7 @@ class TestCommand(Command):
|
||||
test_argv = test_argv0 + shlex.split(self.args)
|
||||
unittest.main(None, defaultTest='test.test_suite', argv=test_argv)
|
||||
|
||||
|
||||
class CFFIBuild(build):
|
||||
"""Hack to combat the chicken and egg problem that we need cffi
|
||||
to add cffi as an extension.
|
||||
@@ -116,12 +118,12 @@ class BuildWithDLLs(CFFIBuild):
|
||||
libgit2_dlls.append('git2.dll')
|
||||
elif compiler_type == 'mingw32':
|
||||
libgit2_dlls.append('libgit2.dll')
|
||||
look_dirs = [libgit2_bin] + os.getenv("PATH", "").split(os.pathsep)
|
||||
target = os.path.abspath(self.build_lib)
|
||||
look_dirs = [libgit2_bin] + getenv("PATH", "").split(pathsep)
|
||||
target = abspath(self.build_lib)
|
||||
for bin in libgit2_dlls:
|
||||
for look in look_dirs:
|
||||
f = os.path.join(look, bin)
|
||||
if os.path.isfile(f):
|
||||
if isfile(f):
|
||||
ret.append((f, target))
|
||||
break
|
||||
else:
|
||||
@@ -131,10 +133,9 @@ class BuildWithDLLs(CFFIBuild):
|
||||
|
||||
def run(self):
|
||||
build.run(self)
|
||||
if os.name == 'nt':
|
||||
# On Windows we package up the dlls with the plugin.
|
||||
for s, d in self._get_dlls():
|
||||
self.copy_file(s, d)
|
||||
# On Windows we package up the dlls with the plugin.
|
||||
for s, d in self._get_dlls():
|
||||
self.copy_file(s, d)
|
||||
|
||||
|
||||
class sdist_files_from_git(sdist):
|
||||
@@ -167,16 +168,10 @@ with codecs.open('README.rst', 'r', 'utf-8') as readme:
|
||||
|
||||
|
||||
cmdclass = {
|
||||
'build': BuildWithDLLs if os.name == 'nt' else CFFIBuild,
|
||||
'test': TestCommand,
|
||||
'sdist': sdist_files_from_git}
|
||||
|
||||
if os.name == 'nt':
|
||||
# BuildWithDLLs can copy external DLLs into source directory.
|
||||
cmdclass['build'] = BuildWithDLLs
|
||||
else:
|
||||
# Build cffi
|
||||
cmdclass['build'] = CFFIBuild
|
||||
|
||||
'sdist': sdist_files_from_git,
|
||||
}
|
||||
|
||||
setup(name='pygit2',
|
||||
description='Python bindings for libgit2.',
|
||||
@@ -184,7 +179,7 @@ setup(name='pygit2',
|
||||
version=__version__,
|
||||
url='http://github.com/libgit2/pygit2',
|
||||
classifiers=classifiers,
|
||||
license='GPLv2',
|
||||
license='GPLv2 with linking exception',
|
||||
maintainer=u('J. David Ibáñez'),
|
||||
maintainer_email='jdavid.ibp@gmail.com',
|
||||
long_description=long_description,
|
||||
|
||||
51
src/diff.c
51
src/diff.c
@@ -31,6 +31,7 @@
|
||||
#include "error.h"
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
#include "oid.h"
|
||||
#include "diff.h"
|
||||
|
||||
extern PyObject *GitError;
|
||||
@@ -43,7 +44,7 @@ extern PyTypeObject RepositoryType;
|
||||
|
||||
PyTypeObject PatchType;
|
||||
|
||||
PyObject*
|
||||
PyObject *
|
||||
wrap_diff(git_diff *diff, Repository *repo)
|
||||
{
|
||||
Diff *py_diff;
|
||||
@@ -52,7 +53,7 @@ wrap_diff(git_diff *diff, Repository *repo)
|
||||
if (py_diff) {
|
||||
Py_INCREF(repo);
|
||||
py_diff->repo = repo;
|
||||
py_diff->list = diff;
|
||||
py_diff->diff = diff;
|
||||
}
|
||||
|
||||
return (PyObject*) py_diff;
|
||||
@@ -76,13 +77,13 @@ wrap_patch(git_patch *patch)
|
||||
|
||||
delta = git_patch_get_delta(patch);
|
||||
|
||||
py_patch->old_file_path = delta->old_file.path;
|
||||
py_patch->new_file_path = delta->new_file.path;
|
||||
py_patch->old_file_path = strdup(delta->old_file.path);
|
||||
py_patch->new_file_path = strdup(delta->new_file.path);
|
||||
py_patch->status = git_diff_status_char(delta->status);
|
||||
py_patch->similarity = delta->similarity;
|
||||
py_patch->flags = delta->flags;
|
||||
py_patch->old_id = git_oid_allocfmt(&delta->old_file.id);
|
||||
py_patch->new_id = git_oid_allocfmt(&delta->new_file.id);
|
||||
py_patch->old_id = git_oid_to_python(&delta->old_file.id);
|
||||
py_patch->new_id = git_oid_to_python(&delta->new_file.id);
|
||||
|
||||
git_patch_line_stats(NULL, &additions, &deletions, patch);
|
||||
py_patch->additions = additions;
|
||||
@@ -133,7 +134,7 @@ wrap_patch(git_patch *patch)
|
||||
return (PyObject*) py_patch;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyObject *
|
||||
diff_get_patch_byindex(git_diff *diff, size_t idx)
|
||||
{
|
||||
git_patch *patch = NULL;
|
||||
@@ -150,18 +151,18 @@ static void
|
||||
Patch_dealloc(Patch *self)
|
||||
{
|
||||
Py_CLEAR(self->hunks);
|
||||
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 */
|
||||
Py_CLEAR(self->old_id);
|
||||
Py_CLEAR(self->new_id);
|
||||
free(self->old_file_path);
|
||||
free(self->new_file_path);
|
||||
PyObject_Del(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_id, T_STRING, "old oid"),
|
||||
MEMBER(Patch, new_id, T_STRING, "new oid"),
|
||||
MEMBER(Patch, old_id, T_OBJECT, "old oid"),
|
||||
MEMBER(Patch, new_id, T_OBJECT, "new oid"),
|
||||
MEMBER(Patch, status, T_CHAR, "status"),
|
||||
MEMBER(Patch, similarity, T_INT, "similarity"),
|
||||
MEMBER(Patch, hunks, T_OBJECT, "hunks"),
|
||||
@@ -234,7 +235,7 @@ PyObject *
|
||||
DiffIter_iternext(DiffIter *self)
|
||||
{
|
||||
if (self->i < self->n)
|
||||
return diff_get_patch_byindex(self->diff->list, self->i++);
|
||||
return diff_get_patch_byindex(self->diff->diff, self->i++);
|
||||
|
||||
PyErr_SetNone(PyExc_StopIteration);
|
||||
return NULL;
|
||||
@@ -283,8 +284,8 @@ PyTypeObject DiffIterType = {
|
||||
Py_ssize_t
|
||||
Diff_len(Diff *self)
|
||||
{
|
||||
assert(self->list);
|
||||
return (Py_ssize_t)git_diff_num_deltas(self->list);
|
||||
assert(self->diff);
|
||||
return (Py_ssize_t)git_diff_num_deltas(self->diff);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Diff_patch__doc__, "Patch diff string.");
|
||||
@@ -295,15 +296,15 @@ Diff_patch__get__(Diff *self)
|
||||
git_patch* patch;
|
||||
git_buf buf = {NULL};
|
||||
int err = GIT_ERROR;
|
||||
size_t i, len, num;
|
||||
size_t i, num;
|
||||
PyObject *py_patch = NULL;
|
||||
|
||||
num = git_diff_num_deltas(self->list);
|
||||
num = git_diff_num_deltas(self->diff);
|
||||
if (num == 0)
|
||||
Py_RETURN_NONE;
|
||||
|
||||
for (i = 0, len = 1; i < num ; ++i) {
|
||||
err = git_patch_from_diff(&patch, self->list, i);
|
||||
for (i = 0; i < num ; ++i) {
|
||||
err = git_patch_from_diff(&patch, self->diff, i);
|
||||
if (err < 0)
|
||||
goto cleanup;
|
||||
|
||||
@@ -429,7 +430,7 @@ Diff_merge(Diff *self, PyObject *args)
|
||||
if (py_diff->repo->repo != self->repo->repo)
|
||||
return Error_set(GIT_ERROR);
|
||||
|
||||
err = git_diff_merge(self->list, py_diff->list);
|
||||
err = git_diff_merge(self->diff, py_diff->diff);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
@@ -454,7 +455,7 @@ Diff_find_similar(Diff *self, PyObject *args, PyObject *kwds)
|
||||
&opts.flags, &opts.rename_threshold, &opts.copy_threshold, &opts.rename_from_rewrite_threshold, &opts.break_rewrite_threshold, &opts.rename_limit))
|
||||
return NULL;
|
||||
|
||||
err = git_diff_find_similar(self->list, &opts);
|
||||
err = git_diff_find_similar(self->diff, &opts);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
@@ -471,7 +472,7 @@ Diff_iter(Diff *self)
|
||||
Py_INCREF(self);
|
||||
iter->diff = self;
|
||||
iter->i = 0;
|
||||
iter->n = git_diff_num_deltas(self->list);
|
||||
iter->n = git_diff_num_deltas(self->diff);
|
||||
}
|
||||
return (PyObject*)iter;
|
||||
}
|
||||
@@ -486,14 +487,14 @@ Diff_getitem(Diff *self, PyObject *value)
|
||||
|
||||
i = PyLong_AsUnsignedLong(value);
|
||||
|
||||
return diff_get_patch_byindex(self->list, i);
|
||||
return diff_get_patch_byindex(self->diff, i);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Diff_dealloc(Diff *self)
|
||||
{
|
||||
git_diff_free(self->list);
|
||||
git_diff_free(self->diff);
|
||||
Py_CLEAR(self->repo);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
19
src/note.c
19
src/note.c
@@ -39,13 +39,13 @@ extern PyTypeObject SignatureType;
|
||||
PyDoc_STRVAR(Note_remove__doc__,
|
||||
"Removes a note for an annotated object");
|
||||
|
||||
PyObject*
|
||||
PyObject *
|
||||
Note_remove(Note *self, PyObject* args)
|
||||
{
|
||||
char *ref = "refs/notes/commits";
|
||||
int err = GIT_ERROR;
|
||||
git_oid annotated_id;
|
||||
Signature *py_author, *py_committer;
|
||||
Oid *id;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!O!|s",
|
||||
&SignatureType, &py_author,
|
||||
@@ -53,12 +53,9 @@ Note_remove(Note *self, PyObject* args)
|
||||
&ref))
|
||||
return NULL;
|
||||
|
||||
err = git_oid_fromstr(&annotated_id, self->annotated_id);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
id = (Oid *) self->annotated_id;
|
||||
err = git_note_remove(self->repo->repo, ref, py_author->signature,
|
||||
py_committer->signature, &annotated_id);
|
||||
py_committer->signature, &id->oid);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
@@ -90,7 +87,7 @@ static void
|
||||
Note_dealloc(Note *self)
|
||||
{
|
||||
Py_CLEAR(self->repo);
|
||||
free(self->annotated_id);
|
||||
Py_CLEAR(self->annotated_id);
|
||||
git_note_free(self->note);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
@@ -102,7 +99,7 @@ PyMethodDef Note_methods[] = {
|
||||
};
|
||||
|
||||
PyMemberDef Note_members[] = {
|
||||
MEMBER(Note, annotated_id, T_STRING, "id of the annotated object."),
|
||||
MEMBER(Note, annotated_id, T_OBJECT, "id of the annotated object."),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -211,7 +208,7 @@ PyTypeObject NoteIterType = {
|
||||
};
|
||||
|
||||
|
||||
PyObject*
|
||||
PyObject *
|
||||
wrap_note(Repository* repo, git_oid* annotated_id, const char* ref)
|
||||
{
|
||||
Note* py_note = NULL;
|
||||
@@ -229,7 +226,7 @@ wrap_note(Repository* repo, git_oid* annotated_id, const char* ref)
|
||||
|
||||
py_note->repo = repo;
|
||||
Py_INCREF(repo);
|
||||
py_note->annotated_id = git_oid_allocfmt(annotated_id);
|
||||
py_note->annotated_id = git_oid_to_python(annotated_id);
|
||||
|
||||
return (PyObject*) py_note;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ PyMethodDef module_methods[] = {
|
||||
{NULL}
|
||||
};
|
||||
|
||||
PyObject*
|
||||
PyObject *
|
||||
moduleinit(PyObject* m)
|
||||
{
|
||||
if (m == NULL)
|
||||
@@ -210,7 +210,6 @@ moduleinit(PyObject* m)
|
||||
ADD_CONSTANT_INT(m, GIT_OBJ_BLOB)
|
||||
ADD_CONSTANT_INT(m, GIT_OBJ_TAG)
|
||||
/* 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_BLOB)
|
||||
ADD_CONSTANT_INT(m, GIT_FILEMODE_BLOB_EXECUTABLE)
|
||||
@@ -347,7 +346,7 @@ moduleinit(PyObject* m)
|
||||
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UNBORN)
|
||||
|
||||
/* Global initialization of libgit2 */
|
||||
git_threads_init();
|
||||
git_libgit2_init();
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ RefLogIter_iternext(RefLogIter *self)
|
||||
entry = git_reflog_entry_byindex(self->reflog, self->i);
|
||||
py_entry = PyObject_New(RefLogEntry, &RefLogEntryType);
|
||||
|
||||
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->oid_old = git_oid_to_python(git_reflog_entry_id_old(entry));
|
||||
py_entry->oid_new = git_oid_to_python(git_reflog_entry_id_new(entry));
|
||||
py_entry->message = strdup(git_reflog_entry_message(entry));
|
||||
err = git_signature_dup(&py_entry->signature,
|
||||
git_reflog_entry_committer(entry));
|
||||
@@ -431,16 +431,16 @@ RefLogEntry_init(RefLogEntry *self, PyObject *args, PyObject *kwds)
|
||||
static void
|
||||
RefLogEntry_dealloc(RefLogEntry *self)
|
||||
{
|
||||
free(self->oid_old);
|
||||
free(self->oid_new);
|
||||
Py_CLEAR(self->oid_old);
|
||||
Py_CLEAR(self->oid_new);
|
||||
free(self->message);
|
||||
git_signature_free(self->signature);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
PyMemberDef RefLogEntry_members[] = {
|
||||
MEMBER(RefLogEntry, oid_new, T_STRING, "New oid."),
|
||||
MEMBER(RefLogEntry, oid_old, T_STRING, "Old oid."),
|
||||
MEMBER(RefLogEntry, oid_new, T_OBJECT, "New oid."),
|
||||
MEMBER(RefLogEntry, oid_old, T_OBJECT, "Old oid."),
|
||||
MEMBER(RefLogEntry, message, T_STRING, "Message."),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -55,6 +55,9 @@ extern PyTypeObject ReferenceType;
|
||||
extern PyTypeObject NoteType;
|
||||
extern PyTypeObject NoteIterType;
|
||||
|
||||
/* forward-declaration for Repsository._from_c() */
|
||||
PyTypeObject RepositoryType;
|
||||
|
||||
git_otype
|
||||
int_to_loose_object_type(int type_id)
|
||||
{
|
||||
@@ -88,19 +91,62 @@ Repository_init(Repository *self, PyObject *args, PyObject *kwds)
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->owned = 1;
|
||||
self->config = NULL;
|
||||
self->index = NULL;
|
||||
|
||||
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
|
||||
Repository_dealloc(Repository *self)
|
||||
{
|
||||
PyObject_GC_UnTrack(self);
|
||||
Py_CLEAR(self->index);
|
||||
Py_CLEAR(self->config);
|
||||
git_repository_free(self->repo);
|
||||
|
||||
if (self->owned)
|
||||
git_repository_free(self->repo);
|
||||
|
||||
Py_TYPE(self)->tp_free(self);
|
||||
}
|
||||
|
||||
@@ -526,7 +572,7 @@ Repository_merge_analysis(Repository *self, PyObject *py_id)
|
||||
int err;
|
||||
size_t len;
|
||||
git_oid id;
|
||||
git_merge_head *merge_head;
|
||||
git_annotated_commit *commit;
|
||||
git_merge_analysis_t analysis;
|
||||
git_merge_preference_t preference;
|
||||
|
||||
@@ -534,12 +580,12 @@ Repository_merge_analysis(Repository *self, PyObject *py_id)
|
||||
if (len == 0)
|
||||
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)
|
||||
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);
|
||||
err = git_merge_analysis(&analysis, &preference, self->repo, (const git_annotated_commit **) &commit, 1);
|
||||
git_annotated_commit_free(commit);
|
||||
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
@@ -561,7 +607,7 @@ PyDoc_STRVAR(Repository_merge__doc__,
|
||||
PyObject *
|
||||
Repository_merge(Repository *self, PyObject *py_oid)
|
||||
{
|
||||
git_merge_head *oid_merge_head;
|
||||
git_annotated_commit *commit;
|
||||
git_oid oid;
|
||||
int err;
|
||||
size_t len;
|
||||
@@ -572,16 +618,16 @@ Repository_merge(Repository *self, PyObject *py_oid)
|
||||
if (len == 0)
|
||||
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)
|
||||
return Error_set(err);
|
||||
|
||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||
err = git_merge(self->repo,
|
||||
(const git_merge_head **)&oid_merge_head, 1,
|
||||
(const git_annotated_commit **)&commit, 1,
|
||||
&merge_opts, &checkout_opts);
|
||||
|
||||
git_merge_head_free(oid_merge_head);
|
||||
git_annotated_commit_free(commit);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
@@ -936,10 +982,15 @@ out:
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_listall_branches__doc__,
|
||||
"listall_branches([flags]) -> [str, ...]\n"
|
||||
"listall_branches([flag]) -> [str, ...]\n"
|
||||
"\n"
|
||||
"Return a tuple with all the branches in the repository.\n"
|
||||
"By default, it returns all local branches.");
|
||||
"Return a list with all the branches in the repository.\n"
|
||||
"\n"
|
||||
"The *flag* may be:\n"
|
||||
"\n"
|
||||
"- GIT_BRANCH_LOCAL - return all local branches (set by default)\n"
|
||||
"- GIT_BRANCH_REMOTE - return all remote-tracking branches\n"
|
||||
"- GIT_BRANCH_ALL - return local branches and remote-tracking branches");
|
||||
|
||||
PyObject *
|
||||
Repository_listall_branches(Repository *self, PyObject *args)
|
||||
@@ -1220,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)
|
||||
git_tree_free(must_free);
|
||||
|
||||
@@ -1313,8 +1364,8 @@ Repository_create_note(Repository *self, PyObject* args)
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
err = git_note_create(¬e_id, self->repo, py_author->signature,
|
||||
py_committer->signature, ref,
|
||||
err = git_note_create(¬e_id, self->repo, ref, py_author->signature,
|
||||
py_committer->signature,
|
||||
&annotated_id, message, force);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
@@ -1375,7 +1426,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, NULL, NULL);
|
||||
err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL, NULL, NULL);
|
||||
git_object_free(target);
|
||||
if (err < 0)
|
||||
return Error_set_oid(err, &oid, len);
|
||||
@@ -1410,6 +1461,8 @@ PyMethodDef Repository_methods[] = {
|
||||
METHOD(Repository, listall_branches, METH_VARARGS),
|
||||
METHOD(Repository, create_branch, METH_VARARGS),
|
||||
METHOD(Repository, reset, METH_VARARGS),
|
||||
METHOD(Repository, _from_c, METH_VARARGS),
|
||||
METHOD(Repository, _disown, METH_NOARGS),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ TreeBuilder_write(TreeBuilder *self)
|
||||
int err;
|
||||
git_oid oid;
|
||||
|
||||
err = git_treebuilder_write(&oid, self->repo->repo, self->bld);
|
||||
err = git_treebuilder_write(&oid, self->bld);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
|
||||
25
src/types.h
25
src/types.h
@@ -32,8 +32,8 @@
|
||||
#include <Python.h>
|
||||
#include <git2.h>
|
||||
|
||||
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 21)
|
||||
#error You need a compatible libgit2 version (v0.21.x)
|
||||
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 22)
|
||||
#error You need a compatible libgit2 version (v0.22.x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -47,6 +47,7 @@ typedef struct {
|
||||
git_repository *repo;
|
||||
PyObject *index; /* 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;
|
||||
|
||||
|
||||
@@ -79,7 +80,7 @@ typedef struct {
|
||||
PyObject_HEAD
|
||||
Repository *repo;
|
||||
git_note *note;
|
||||
char* annotated_id;
|
||||
PyObject* annotated_id;
|
||||
} Note;
|
||||
|
||||
typedef struct {
|
||||
@@ -90,12 +91,12 @@ typedef struct {
|
||||
} NoteIter;
|
||||
|
||||
|
||||
/* git _diff */
|
||||
SIMPLE_TYPE(Diff, git_diff, list)
|
||||
/* git_diff */
|
||||
SIMPLE_TYPE(Diff, git_diff, diff)
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
Diff* diff;
|
||||
Diff *diff;
|
||||
size_t i;
|
||||
size_t n;
|
||||
} DiffIter;
|
||||
@@ -103,10 +104,10 @@ typedef struct {
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject* hunks;
|
||||
const char * old_file_path;
|
||||
const char * new_file_path;
|
||||
char* old_id;
|
||||
char* new_id;
|
||||
char * old_file_path;
|
||||
char * new_file_path;
|
||||
PyObject* old_id;
|
||||
PyObject* new_id;
|
||||
char status;
|
||||
unsigned similarity;
|
||||
unsigned additions;
|
||||
@@ -164,8 +165,8 @@ typedef Reference Branch;
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
git_signature *signature;
|
||||
char *oid_old;
|
||||
char *oid_new;
|
||||
PyObject *oid_old;
|
||||
PyObject *oid_new;
|
||||
char *message;
|
||||
} RefLogEntry;
|
||||
|
||||
|
||||
@@ -261,9 +261,9 @@ class DiffTest(utils.BareRepoTestCase):
|
||||
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_id,
|
||||
self.assertEqual(patch.old_id.hex,
|
||||
'7f129fd57e31e935c6d60a0c794efe4e6927664b')
|
||||
self.assertEqual(patch.new_id,
|
||||
self.assertEqual(patch.new_id.hex,
|
||||
'af431f20fc541ed6d5afede3e2dc7160f6f01f16')
|
||||
|
||||
def test_hunk_content(self):
|
||||
|
||||
@@ -70,7 +70,7 @@ class NotesTest(utils.BareRepoTestCase):
|
||||
|
||||
def test_iterate_notes(self):
|
||||
for i, note in enumerate(self.repo.notes()):
|
||||
entry = (note.id.hex, note.message, note.annotated_id)
|
||||
entry = (note.id.hex, note.message, note.annotated_id.hex)
|
||||
self.assertEqual(NOTES[i], entry)
|
||||
|
||||
def test_iterate_non_existing_ref(self):
|
||||
|
||||
@@ -71,19 +71,19 @@ class RepositoryTest(utils.RepoTestCase):
|
||||
remote = self.repo.remotes[1]
|
||||
|
||||
self.assertEqual(name, remote.name)
|
||||
remote.delete()
|
||||
self.repo.remotes.delete(remote.name)
|
||||
self.assertEqual(1, len(self.repo.remotes))
|
||||
|
||||
def test_remote_rename(self):
|
||||
remote = self.repo.remotes[0]
|
||||
|
||||
self.assertEqual(REMOTE_NAME, remote.name)
|
||||
problems = remote.rename('new')
|
||||
problems = self.repo.remotes.rename(remote.name, "new")
|
||||
self.assertEqual([], problems)
|
||||
self.assertEqual('new', remote.name)
|
||||
self.assertNotEqual('new', remote.name)
|
||||
|
||||
self.assertRaises(ValueError, remote.rename, '')
|
||||
self.assertRaises(ValueError, remote.rename, None)
|
||||
self.assertRaises(ValueError, self.repo.remotes.rename, '', '')
|
||||
self.assertRaises(ValueError, self.repo.remotes.rename, None, None)
|
||||
|
||||
|
||||
def test_remote_set_url(self):
|
||||
@@ -167,16 +167,25 @@ class RepositoryTest(utils.RepoTestCase):
|
||||
remote = self.repo.create_remote(name, url)
|
||||
self.assertTrue(remote.name in [x.name for x in self.repo.remotes])
|
||||
|
||||
def test_remote_collection(self):
|
||||
remote = self.repo.remotes['origin']
|
||||
self.assertEqual(REMOTE_NAME, remote.name)
|
||||
self.assertEqual(REMOTE_URL, remote.url)
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.repo.remotes['upstream']
|
||||
|
||||
name = 'upstream'
|
||||
url = 'git://github.com/libgit2/pygit2.git'
|
||||
remote = self.repo.remotes.create(name, url)
|
||||
self.assertTrue(remote.name in [x.name for x in self.repo.remotes])
|
||||
|
||||
|
||||
def test_remote_save(self):
|
||||
remote = self.repo.remotes[0]
|
||||
|
||||
remote.rename('new-name')
|
||||
remote.url = 'http://example.com/test.git'
|
||||
|
||||
remote.save()
|
||||
|
||||
self.assertEqual('new-name', self.repo.remotes[0].name)
|
||||
self.assertEqual('http://example.com/test.git',
|
||||
self.repo.remotes[0].url)
|
||||
|
||||
@@ -265,11 +274,11 @@ class PushTestCase(unittest.TestCase):
|
||||
'refs/heads/master', tip.author, tip.author, 'empty commit',
|
||||
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)
|
||||
|
||||
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
|
||||
clone_tip = self.clone[self.clone.head.target].id
|
||||
self.assertEqual(origin_tip, clone_tip)
|
||||
@@ -285,7 +294,8 @@ class PushTestCase(unittest.TestCase):
|
||||
'refs/heads/master', tip.author, tip.author, 'other commit',
|
||||
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__':
|
||||
unittest.main()
|
||||
|
||||
@@ -41,7 +41,7 @@ import sys
|
||||
|
||||
# Import from pygit2
|
||||
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
|
||||
import pygit2
|
||||
from . import utils
|
||||
@@ -440,19 +440,22 @@ class CloneRepositoryTest(utils.NoRepoTestCase):
|
||||
self.assertFalse(repo.is_empty)
|
||||
self.assertTrue(repo.is_bare)
|
||||
|
||||
def test_clone_remote_name(self):
|
||||
repo_path = "./test/data/testrepo.git/"
|
||||
repo = clone_repository(
|
||||
repo_path, self._temp_dir, remote_name="custom_remote")
|
||||
self.assertFalse(repo.is_empty)
|
||||
self.assertEqual(repo.remotes[0].name, "custom_remote")
|
||||
def test_clone_repository_and_remote_callbacks(self):
|
||||
src_repo_relpath = "./test/data/testrepo.git/"
|
||||
repo_path = os.path.join(self._temp_dir, "clone-into")
|
||||
url = 'file://' + os.path.realpath(src_repo_relpath)
|
||||
|
||||
def test_clone_into(self):
|
||||
repo_path = "./test/data/testrepo.git/"
|
||||
repo = init_repository(os.path.join(self._temp_dir, "clone-into"))
|
||||
remote = repo.create_remote("origin", 'file://' + os.path.realpath(repo_path))
|
||||
clone_into(repo, remote)
|
||||
self.assertTrue('refs/remotes/origin/master' in repo.listall_references())
|
||||
def create_repository(path, bare):
|
||||
return init_repository(path, bare)
|
||||
|
||||
# here we override the name
|
||||
def create_remote(repo, name, url):
|
||||
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):
|
||||
credentials = pygit2.UserPass("libgit2", "libgit2")
|
||||
|
||||
Reference in New Issue
Block a user