Merge tag '0.23.3' into debian/unstable
This commit is contained in:
136
README.rst
136
README.rst
@@ -6,8 +6,8 @@ pygit2 - libgit2 bindings in Python
|
||||
:target: http://travis-ci.org/libgit2/pygit2
|
||||
|
||||
Pygit2 is a set of Python bindings to the libgit2 shared library, libgit2
|
||||
implements the core of Git. Pygit2 works with Python 2.7, 3.2, 3.3, 3.4 and
|
||||
pypy.
|
||||
implements Git plumbing. Pygit2 works with Python 2.7, 3.2, 3.3, 3.4 and
|
||||
PyPy 2.6
|
||||
|
||||
Links:
|
||||
|
||||
@@ -25,6 +25,91 @@ How to install
|
||||
Changelog
|
||||
==============
|
||||
|
||||
0.23.3 (2016-01-01)
|
||||
-------------------------
|
||||
|
||||
- New ``Repository.create_blob_fromiobase(...)``
|
||||
`#490 <https://github.com/libgit2/pygit2/pull/490>`_
|
||||
`#577 <https://github.com/libgit2/pygit2/pull/577>`_
|
||||
|
||||
- New ``Repository.describe(...)``
|
||||
`#585 <https://github.com/libgit2/pygit2/pull/585>`_
|
||||
|
||||
- Fix ``Signature`` default encoding, UTF-8 now
|
||||
`#581 <https://github.com/libgit2/pygit2/issues/581>`_
|
||||
|
||||
- Fixing ``pip install pygit2``, should install cffi first
|
||||
|
||||
- Unit tests, fix binary diff test
|
||||
`#586 <https://github.com/libgit2/pygit2/pull/586>`_
|
||||
|
||||
- Document that ``Diff.patch`` can be ``None``
|
||||
`#587 <https://github.com/libgit2/pygit2/pull/587>`_
|
||||
|
||||
|
||||
0.23.2 (2015-10-11)
|
||||
-------------------------
|
||||
|
||||
- Unify callbacks system for remotes and clone
|
||||
`#568 <https://github.com/libgit2/pygit2/pull/568>`_
|
||||
|
||||
- New ``TreeEntry._name``
|
||||
`#570 <https://github.com/libgit2/pygit2/pull/570>`_
|
||||
|
||||
- Fix segfault in ``Tag._message``
|
||||
`#572 <https://github.com/libgit2/pygit2/pull/572>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#569 <https://github.com/libgit2/pygit2/pull/569>`_
|
||||
`#574 <https://github.com/libgit2/pygit2/pull/574>`_
|
||||
|
||||
API changes to clone::
|
||||
|
||||
# Before
|
||||
clone_repository(..., credentials, certificate)
|
||||
|
||||
# Now
|
||||
callbacks = RemoteCallbacks(credentials, certificate)
|
||||
clone_repository(..., callbacks)
|
||||
|
||||
API changes to remote::
|
||||
|
||||
# Before
|
||||
def transfer_progress(stats):
|
||||
...
|
||||
|
||||
remote.credentials = credentials
|
||||
remote.transfer_progress = transfer_progress
|
||||
remote.fetch()
|
||||
remote.push(specs)
|
||||
|
||||
# Now
|
||||
class MyCallbacks(RemoteCallbacks):
|
||||
def transfer_progress(self, stats):
|
||||
...
|
||||
|
||||
callbacks = MyCallbacks(credentials)
|
||||
remote.fetch(callbacks=callbacks)
|
||||
remote.push(specs, callbacks=callbacks)
|
||||
|
||||
|
||||
0.23.1 (2015-09-26)
|
||||
-------------------------
|
||||
|
||||
- Improve support for cffi 1.0+
|
||||
`#529 <https://github.com/libgit2/pygit2/pull/529>`_
|
||||
`#561 <https://github.com/libgit2/pygit2/pull/561>`_
|
||||
|
||||
- Fix ``Remote.push``
|
||||
`#557 <https://github.com/libgit2/pygit2/pull/557>`_
|
||||
|
||||
- New ``TreeEntry.type``
|
||||
`#560 <https://github.com/libgit2/pygit2/pull/560>`_
|
||||
|
||||
- New ``pygit2.GIT_DIFF_SHOW_BINARY``
|
||||
`#566 <https://github.com/libgit2/pygit2/pull/566>`_
|
||||
|
||||
|
||||
0.23.0 (2015-08-14)
|
||||
-------------------------
|
||||
|
||||
@@ -326,7 +411,7 @@ Other changes:
|
||||
`#380 <https://github.com/libgit2/pygit2/issues/380>`_
|
||||
`#407 <https://github.com/libgit2/pygit2/pull/407>`_
|
||||
|
||||
- Add support for pypy3
|
||||
- Add support for PyPy3
|
||||
`#422 <https://github.com/libgit2/pygit2/pull/422>`_
|
||||
|
||||
- Documentation improvements
|
||||
@@ -490,7 +575,7 @@ Other:
|
||||
0.20.2 (2014-02-04)
|
||||
-------------------
|
||||
|
||||
- Support pypy
|
||||
- Support PyPy
|
||||
`#209 <https://github.com/libgit2/pygit2/issues/209>`_
|
||||
`#327 <https://github.com/libgit2/pygit2/pull/327>`_
|
||||
`#333 <https://github.com/libgit2/pygit2/pull/333>`_
|
||||
@@ -663,38 +748,41 @@ Other: `#331 <https://github.com/libgit2/pygit2/pull/331>`_
|
||||
Authors
|
||||
==============
|
||||
|
||||
93 developers have contributed at least 1 commit to pygit2::
|
||||
102 developers have contributed at least 1 commit to pygit2::
|
||||
|
||||
J. David Ibáñez Carlos Martín Nieto Nico von Geyso
|
||||
W. Trevor King Dave Borowitz Daniel Rodríguez Troitiño
|
||||
W. Trevor King Dave Borowitz Daniel Rodríguez Troitiño
|
||||
Richo Healey Christian Boos Julien Miotte
|
||||
Richard Möhn Xu Tao Jose Plana
|
||||
Matthew Duggan Matthew Gamble Martin Lenders
|
||||
Petr Hosek Victor Garcia Xavier Delannoy
|
||||
Yonggang Luo Patrick Steinhardt Valentin Haenel
|
||||
Michael Jones Bernardo Heynemann John Szakmeister
|
||||
Vlad Temian Brodie Rao David Versmisse
|
||||
Rémi Duraffort Sebastian Thiel Alok Singhal
|
||||
Fraser Tweedale Han-Wen Nienhuys Leonardo Rhodes
|
||||
Petr Viktorin Ron Cohen Santiago Perez De Rosso
|
||||
Thomas Kluyver Alex Chamberlain Alexander Bayandin
|
||||
Amit Bakshi Andrey Devyatkin Arno van Lumig
|
||||
Ben Davis Eric Schrijver Greg Fitzgerald
|
||||
Hervé Cauwelier Huang Huang Ian P. McCullough
|
||||
Jack O'Connor Jared Flatow Jiunn Haur Lim
|
||||
Jun Omae Kaarel Kitsemets Kevin KIN-FOO
|
||||
Vlad Temian Brodie Rao Nicolas Dandrimont
|
||||
David Versmisse Rémi Duraffort Santiago Perez De Rosso
|
||||
Sebastian Thiel Alok Singhal Fraser Tweedale
|
||||
Han-Wen Nienhuys Leonardo Rhodes Petr Viktorin
|
||||
Ron Cohen Thomas Kluyver Alex Chamberlain
|
||||
Alexander Bayandin Amit Bakshi Andrey Devyatkin
|
||||
Arno van Lumig Ben Davis Eric Schrijver
|
||||
Greg Fitzgerald Hervé Cauwelier Huang Huang
|
||||
Ian P. McCullough Jack O'Connor Jared Flatow
|
||||
Jiunn Haur Lim Jun Omae Kaarel Kitsemets
|
||||
Kevin KIN-FOO Masud Rahman Michael Sondergaard
|
||||
Sarath Lakshman Vicent Marti Zoran Zaric
|
||||
Adam Spiers Andrew Chin András Veres-Szentkirályi
|
||||
Ash Berlin Benjamin Kircher Benjamin Pollack
|
||||
Bryan O'Sullivan Colin Watson Daniel Bruce
|
||||
David Fischer David Sanders Devaev Maxim
|
||||
Bryan O'Sullivan Chason Chaffin Chris Rebert
|
||||
Colin Watson Daniel Bruce David Fischer
|
||||
David Sanders David Six Devaev Maxim
|
||||
Eric Davis Erik Meusel Erik van Zijst
|
||||
Ferengee Gustavo Di Pietro Holger Frey
|
||||
Hugh Cole-Baker Jasper Lievisse Josh Bleecher Snyder
|
||||
Justin Clift Kyriakos Oikonomakos Lukas Fleischer
|
||||
Mathieu Bridon Michael Sondergaard Óscar San José
|
||||
Peter Dave Hello Philippe Ombredanne Ridge Kennedy
|
||||
Ross Nicoll Rui Abreu Ferreira Soasme
|
||||
Ferengee Guille -bisho- Gustavo Di Pietro
|
||||
Holger Frey Hugh Cole-Baker Jasper Lievisse Adriaanse
|
||||
Josh Bleecher Snyder Justin Clift Kyriakos Oikonomakos
|
||||
Lukas Fleischer Mathieu Bridon Nicolás Sanguinetti
|
||||
Noah Fontes Óscar San José Peter Dave Hello
|
||||
Philippe Ombredanne Ridge Kennedy Ross Nicoll
|
||||
Rui Abreu Ferreira Sheeo Soasme
|
||||
Vladimir Rutsky chengyuhang earl
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'pygit2'
|
||||
copyright = u'2010-2014 The pygit2 contributors'
|
||||
copyright = u'2010-2015 The pygit2 contributors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -52,7 +52,7 @@ copyright = u'2010-2014 The pygit2 contributors'
|
||||
# The short X.Y version.
|
||||
version = '0.23'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.23.0'
|
||||
release = '0.23.3'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -83,6 +83,9 @@ Attributes:
|
||||
|
||||
.. autoattribute:: pygit2.DiffFile.path
|
||||
.. autoattribute:: pygit2.DiffFile.id
|
||||
.. autoattribute:: pygit2.DiffFile.size
|
||||
.. autoattribute:: pygit2.DiffFile.flags
|
||||
.. autoattribute:: pygit2.DiffFile.mode
|
||||
|
||||
|
||||
The DiffHunk type
|
||||
|
||||
@@ -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.23.0``::
|
||||
``0.23.3``::
|
||||
|
||||
>>> 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.23.0``::
|
||||
``0.23.3``::
|
||||
|
||||
>>> print LIBGIT2_VER_MINOR
|
||||
22
|
||||
23
|
||||
|
||||
.. py:data:: LIBGIT2_VER_REVISION
|
||||
|
||||
Integer value of the revision version number. For example, for the version
|
||||
``0.23.0``::
|
||||
``0.23.3``::
|
||||
|
||||
>>> print LIBGIT2_VER_REVISION
|
||||
0
|
||||
3
|
||||
|
||||
.. py:data:: LIBGIT2_VERSION
|
||||
|
||||
The libgit2 version number as a string::
|
||||
|
||||
>>> print LIBGIT2_VERSION
|
||||
'0.23.0'
|
||||
'0.23.3'
|
||||
|
||||
Errors
|
||||
======
|
||||
|
||||
@@ -13,11 +13,17 @@ Installation
|
||||
Requirements
|
||||
============
|
||||
|
||||
- Python 2.7, 3.2+ or pypy (including the development headers)
|
||||
- Python 2.7, 3.2+ or PyPy 2.6+ (including the development headers)
|
||||
- Libgit2 v0.23.x
|
||||
- cffi 0.8.1+
|
||||
- Libssh2, optional, used for SSH network operations.
|
||||
- pkg-config, optional, used for SSH network operations.
|
||||
- cffi 1.0+
|
||||
|
||||
Optional libgit2 dependecies to support ssh and https:
|
||||
|
||||
- https: WinHTTP (Windows), SecureTransport (OS X) or OpenSSL.
|
||||
- ssh: libssh2, pkg-config
|
||||
|
||||
It should work with older versions of cffi and PyPy, but using cffi 1.0+
|
||||
(and PyPy 2.6+) is strongly encouraged.
|
||||
|
||||
.. warning::
|
||||
|
||||
@@ -35,11 +41,11 @@ while the last number |lq| *.micro* |rq| auto-increments independently.
|
||||
|
||||
As illustration see this table of compatible releases:
|
||||
|
||||
+-----------+--------+----------------+----------------------------------------+
|
||||
|**libgit2**| 0.23.0 | 0.22.0, 0.22.1 | 0.21.1, 0.21.2 |
|
||||
+-----------+--------+----------------+----------------------------------------+
|
||||
|**pygit2** | 0.23.0 | 0.22.0 | 0.21.0, 0.21.1, 0.21.2, 0.21.3, 0.21.4 |
|
||||
+-----------+--------+----------------+----------------------------------------+
|
||||
+-----------+----------------------------------------+--------------------------------+
|
||||
|**libgit2**| 0.23.0, 0.23.1, 0.23.2, 0.23.3, 0.23.4 | 0.22.0, 0.22.1, 0.22.2, 0.22.3 |
|
||||
+-----------+----------------------------------------+--------------------------------+
|
||||
|**pygit2** | 0.23.0, 0.23.1, 0.23.2, 0.23.3 | 0.22.0, 0.22.1 |
|
||||
+-----------+----------------------------------------+--------------------------------+
|
||||
|
||||
.. warning::
|
||||
|
||||
@@ -56,9 +62,9 @@ directory, do:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.0.tar.gz
|
||||
$ tar xzf v0.23.0.tar.gz
|
||||
$ cd libgit2-0.23.0/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.4.tar.gz
|
||||
$ tar xzf v0.23.4.tar.gz
|
||||
$ cd libgit2-0.23.4/
|
||||
$ cmake .
|
||||
$ make
|
||||
$ sudo make install
|
||||
@@ -140,9 +146,9 @@ Install libgit2 (see we define the installation prefix):
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.0.tar.gz
|
||||
$ tar xzf v0.23.0.tar.gz
|
||||
$ cd libgit2-0.23.0/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.4.tar.gz
|
||||
$ tar xzf v0.23.4.tar.gz
|
||||
$ cd libgit2-0.23.4/
|
||||
$ cmake . -DCMAKE_INSTALL_PREFIX=$LIBGIT2
|
||||
$ make
|
||||
$ make install
|
||||
@@ -195,9 +201,9 @@ from a bash shell:
|
||||
.. code-block:: sh
|
||||
|
||||
$ export LIBGIT2=C:/Dev/libgit2
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.0.tar.gz
|
||||
$ tar xzf v0.23.0.tar.gz
|
||||
$ cd libgit2-0.23.0/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.4.tar.gz
|
||||
$ tar xzf v0.23.4.tar.gz
|
||||
$ cd libgit2-0.23.4/
|
||||
$ cmake . -DSTDCALL=OFF -DCMAKE_INSTALL_PREFIX=$LIBGIT2 -G "Visual Studio 9 2008"
|
||||
$ cmake --build . --config release --target install
|
||||
$ ctest -v
|
||||
|
||||
@@ -132,6 +132,7 @@ them to the Git object database:
|
||||
|
||||
.. automethod:: pygit2.Repository.create_blob_fromworkdir
|
||||
.. automethod:: pygit2.Repository.create_blob_fromdisk
|
||||
.. automethod:: pygit2.Repository.create_blob_fromiobase
|
||||
|
||||
There are also some functions to calculate the id for a byte string without
|
||||
creating the blob object:
|
||||
@@ -176,6 +177,7 @@ Tree entries
|
||||
.. autoattribute:: pygit2.TreeEntry.id
|
||||
.. autoattribute:: pygit2.TreeEntry.hex
|
||||
.. autoattribute:: pygit2.TreeEntry.filemode
|
||||
.. autoattribute:: pygit2.TreeEntry.type
|
||||
|
||||
.. method:: TreeEntry.__cmp__(TreeEntry)
|
||||
|
||||
@@ -188,14 +190,14 @@ Example::
|
||||
6
|
||||
|
||||
>>> for entry in tree: # Iteration
|
||||
... print(entry.id, entry.name)
|
||||
... print(entry.id, entry.type, entry.name)
|
||||
...
|
||||
7151ca7cd3e59f3eab19c485cfbf3cb30928d7fa .gitignore
|
||||
c36f4cf1e38ec1bb9d9ad146ed572b89ecfc9f18 COPYING
|
||||
32b30b90b062f66957d6790c3c155c289c34424e README.md
|
||||
c87dae4094b3a6d10e08bc6c5ef1f55a7e448659 pygit2.c
|
||||
85a67270a49ef16cdd3d328f06a3e4b459f09b27 setup.py
|
||||
3d8985bbec338eb4d47c5b01b863ee89d044bd53 test
|
||||
7151ca7cd3e59f3eab19c485cfbf3cb30928d7fa blob .gitignore
|
||||
c36f4cf1e38ec1bb9d9ad146ed572b89ecfc9f18 blob COPYING
|
||||
32b30b90b062f66957d6790c3c155c289c34424e blob README.md
|
||||
c87dae4094b3a6d10e08bc6c5ef1f55a7e448659 blob pygit2.c
|
||||
85a67270a49ef16cdd3d328f06a3e4b459f09b27 blob setup.py
|
||||
3d8985bbec338eb4d47c5b01b863ee89d044bd53 tree test
|
||||
|
||||
>>> entry = tree['pygit2.c'] # Get an entry by name
|
||||
>>> entry
|
||||
|
||||
@@ -21,6 +21,12 @@ The Remote type
|
||||
.. autoclass:: pygit2.Remote
|
||||
:members:
|
||||
|
||||
The RemoteCallbacks type
|
||||
========================
|
||||
|
||||
.. autoclass:: pygit2.RemoteCallbacks
|
||||
:members:
|
||||
|
||||
The TransferProgress type
|
||||
===========================
|
||||
|
||||
@@ -42,8 +48,6 @@ Refspecs objects are not constructed directly, but returned by
|
||||
Credentials
|
||||
================
|
||||
|
||||
.. automethod:: pygit2.Remote.credentials
|
||||
|
||||
There are two types of credentials: username/password and SSH key
|
||||
pairs. Both :py:class:`pygit2.UserPass` and :py:class:`pygit2.Keypair`
|
||||
are callable objects, with the appropriate signature for the
|
||||
|
||||
@@ -71,3 +71,4 @@ Below there are some general attributes and methods:
|
||||
.. automethod:: pygit2.Repository.state_cleanup
|
||||
.. automethod:: pygit2.Repository.write_archive
|
||||
.. automethod:: pygit2.Repository.ahead_behind
|
||||
.. automethod:: pygit2.Repository.describe
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -35,15 +35,15 @@ from _pygit2 import *
|
||||
from .blame import Blame, BlameHunk
|
||||
from .config import Config
|
||||
from .credentials import *
|
||||
from .errors import check_error
|
||||
from .errors import check_error, Passthrough
|
||||
from .ffi import ffi, C
|
||||
from .index import Index, IndexEntry
|
||||
from .remote import Remote, get_credentials
|
||||
from .remote import Remote, RemoteCallbacks, get_credentials
|
||||
from .repository import Repository
|
||||
from .settings import Settings
|
||||
from .submodule import Submodule
|
||||
from .utils import to_bytes, to_str
|
||||
from ._utils import __version__
|
||||
from ._build import __version__
|
||||
|
||||
|
||||
# Features
|
||||
@@ -143,22 +143,6 @@ def init_repository(path, bare=False,
|
||||
# Ok
|
||||
return Repository(to_str(path))
|
||||
|
||||
|
||||
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
||||
'const char *username_from_url, unsigned int allowed_types,'
|
||||
'void *data)')
|
||||
def _credentials_cb(cred_out, url, username_from_url, allowed, data):
|
||||
d = ffi.from_handle(data)
|
||||
|
||||
try:
|
||||
ccred = get_credentials(d['credentials_cb'], url, username_from_url, allowed)
|
||||
cred_out[0] = ccred[0]
|
||||
except Exception as e:
|
||||
d['exception'] = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
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):
|
||||
@@ -189,24 +173,9 @@ def _remote_create_cb(remote_out, repo, name, url, data):
|
||||
|
||||
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, repository=None, remote=None,
|
||||
checkout_branch=None, credentials=None, certificate=None):
|
||||
checkout_branch=None, callbacks=None):
|
||||
"""Clones a new Git repository from *url* in the given *path*.
|
||||
|
||||
Returns a Repository class pointing to the newly cloned repository.
|
||||
@@ -224,11 +193,8 @@ def clone_repository(
|
||||
:param str checkout_branch: Branch to checkout after the
|
||||
clone. The default is to use the remote's default branch.
|
||||
|
||||
:param callable credentials: authentication to use if the remote
|
||||
requires it
|
||||
|
||||
:param callable certificate: callback to verify the host's
|
||||
certificate or fingerprint.
|
||||
:param RemoteCallbacks callbacks: object which implements the
|
||||
callbacks as methods.
|
||||
|
||||
:rtype: Repository
|
||||
|
||||
@@ -240,8 +206,8 @@ def clone_repository(
|
||||
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.
|
||||
The callbacks should be an object which inherits from
|
||||
`pyclass:RemoteCallbacks`.
|
||||
|
||||
"""
|
||||
|
||||
@@ -252,10 +218,8 @@ def clone_repository(
|
||||
|
||||
# Data, let's use a dict as we don't really want much more
|
||||
d = {}
|
||||
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
|
||||
@@ -277,13 +241,11 @@ def clone_repository(
|
||||
|
||||
|
||||
opts.bare = bare
|
||||
if credentials:
|
||||
opts.fetch_opts.callbacks.credentials = _credentials_cb
|
||||
opts.fetch_opts.callbacks.payload = d_handle
|
||||
|
||||
if certificate:
|
||||
opts.fetch_opts.callbacks.certificate_check = _certificate_cb
|
||||
opts.fetch_opts.callbacks.payload = d_handle
|
||||
if callbacks is None:
|
||||
callbacks = RemoteCallbacks()
|
||||
|
||||
callbacks._fill_fetch_options(opts.fetch_opts)
|
||||
|
||||
err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -26,23 +26,18 @@
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""
|
||||
This is an special module, it provides stuff used by setup.py and by
|
||||
pygit2 at run-time.
|
||||
This is an special module, it provides stuff used by setup.py at build time.
|
||||
But also used by pygit2 at run time.
|
||||
"""
|
||||
|
||||
# Import from the Standard Library
|
||||
from binascii import crc32
|
||||
import codecs
|
||||
import os
|
||||
from os import getenv
|
||||
from os.path import abspath, dirname
|
||||
import sys
|
||||
|
||||
|
||||
#
|
||||
# The version number of pygit2
|
||||
#
|
||||
__version__ = '0.23.0'
|
||||
__version__ = '0.23.3'
|
||||
|
||||
|
||||
#
|
||||
@@ -67,44 +62,3 @@ def get_libgit2_paths():
|
||||
os.path.join(libgit2_path, 'include'),
|
||||
getenv('LIBGIT2_LIB', os.path.join(libgit2_path, 'lib')),
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Loads the cffi extension
|
||||
#
|
||||
def get_ffi():
|
||||
import cffi
|
||||
|
||||
ffi = cffi.FFI()
|
||||
|
||||
# Load C definitions
|
||||
if getattr(sys, 'frozen', False):
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
dir_path = sys._MEIPASS
|
||||
else:
|
||||
dir_path = dirname(abspath(sys.executable))
|
||||
else:
|
||||
dir_path = dirname(abspath(__file__))
|
||||
|
||||
decl_path = os.path.join(dir_path, 'decl.h')
|
||||
with codecs.open(decl_path, 'r', 'utf-8') as header:
|
||||
ffi.cdef(header.read())
|
||||
|
||||
# The modulename
|
||||
# Simplified version of what cffi does: remove kwargs and vengine
|
||||
preamble = "#include <git2.h>"
|
||||
key = [sys.version[:3], cffi.__version__, preamble] + ffi._cdefsources
|
||||
key = '\x00'.join(key)
|
||||
if sys.version_info >= (3,):
|
||||
key = key.encode('utf-8')
|
||||
k1 = hex(crc32(key[0::2]) & 0xffffffff).lstrip('0x').rstrip('L')
|
||||
k2 = hex(crc32(key[1::2]) & 0xffffffff).lstrip('0').rstrip('L')
|
||||
modulename = 'pygit2_cffi_%s%s' % (k1, k2)
|
||||
|
||||
# Load extension module
|
||||
libgit2_bin, libgit2_include, libgit2_lib = get_libgit2_paths()
|
||||
C = ffi.verify(preamble, modulename=modulename, libraries=["git2"],
|
||||
include_dirs=[libgit2_include], library_dirs=[libgit2_lib])
|
||||
|
||||
# Ok
|
||||
return ffi, C
|
||||
76
pygit2/_run.py
Normal file
76
pygit2/_run.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# In addition to the permissions in the GNU General Public License,
|
||||
# the authors give you unlimited permission to link the compiled
|
||||
# version of this file into combinations with other programs,
|
||||
# and to distribute those combinations without any restriction
|
||||
# coming from the use of this file. (The General Public License
|
||||
# restrictions do apply in other respects; for example, they cover
|
||||
# modification of the file, and distribution when not linked into
|
||||
# a combined executable.)
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""
|
||||
This is an special module, it provides stuff used by by pygit2 at run-time.
|
||||
"""
|
||||
|
||||
# Import from the Standard Library
|
||||
import codecs
|
||||
import os
|
||||
from os.path import abspath, dirname
|
||||
import sys
|
||||
|
||||
# Import from cffi
|
||||
from cffi import FFI
|
||||
|
||||
# Import from pygit2
|
||||
from _build import get_libgit2_paths
|
||||
|
||||
|
||||
# C_HEADER_SRC
|
||||
if getattr(sys, 'frozen', False):
|
||||
dir_path = getattr(sys, '_MEIPASS', None)
|
||||
if dir_path is None:
|
||||
dir_path = dirname(abspath(sys.executable))
|
||||
else:
|
||||
dir_path = dirname(abspath(__file__))
|
||||
|
||||
decl_path = os.path.join(dir_path, 'decl.h')
|
||||
with codecs.open(decl_path, 'r', 'utf-8') as header:
|
||||
C_HEADER_SRC = header.read()
|
||||
|
||||
# C_KEYWORDS
|
||||
libgit2_bin, libgit2_include, libgit2_lib = get_libgit2_paths()
|
||||
C_KEYWORDS = dict(libraries=['git2'],
|
||||
library_dirs=[libgit2_lib],
|
||||
include_dirs=[libgit2_include])
|
||||
|
||||
# preamble
|
||||
preamble = "#include <git2.h>"
|
||||
|
||||
# ffi
|
||||
ffi = FFI()
|
||||
set_source = getattr(ffi, 'set_source', None)
|
||||
if set_source is not None:
|
||||
set_source("pygit2._libgit2", preamble, **C_KEYWORDS)
|
||||
|
||||
ffi.cdef(C_HEADER_SRC)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ffi.compile()
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -756,6 +756,47 @@ int git_merge_trees(git_index **out, git_repository *repo, const git_tree *ances
|
||||
int git_merge_file_from_index(git_merge_file_result *out, git_repository *repo, const git_index_entry *ancestor, const git_index_entry *ours, const git_index_entry *theirs, const git_merge_file_options *opts);
|
||||
void git_merge_file_result_free(git_merge_file_result *result);
|
||||
|
||||
/*
|
||||
* Describe
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
GIT_DESCRIBE_DEFAULT,
|
||||
GIT_DESCRIBE_TAGS,
|
||||
GIT_DESCRIBE_ALL,
|
||||
} git_describe_strategy_t;
|
||||
|
||||
typedef struct git_describe_options {
|
||||
unsigned int version;
|
||||
unsigned int max_candidates_tags;
|
||||
unsigned int describe_strategy;
|
||||
const char *pattern;
|
||||
int only_follow_first_parent;
|
||||
int show_commit_oid_as_fallback;
|
||||
} git_describe_options;
|
||||
|
||||
#define GIT_DESCRIBE_OPTIONS_VERSION ...
|
||||
|
||||
int git_describe_init_options(git_describe_options *opts, unsigned int version);
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
unsigned int abbreviated_size;
|
||||
int always_use_long_format;
|
||||
const char *dirty_suffix;
|
||||
} git_describe_format_options;
|
||||
|
||||
#define GIT_DESCRIBE_FORMAT_OPTIONS_VERSION ...
|
||||
|
||||
int git_describe_init_format_options(git_describe_format_options *opts, unsigned int version);
|
||||
|
||||
typedef ... git_describe_result;
|
||||
|
||||
int git_describe_commit(git_describe_result **result, git_object *committish, git_describe_options *opts);
|
||||
int git_describe_workdir(git_describe_result **out, git_repository *repo, git_describe_options *opts);
|
||||
int git_describe_format(git_buf *out, const git_describe_result *result, const git_describe_format_options *opts);
|
||||
void git_describe_result_free(git_describe_result *result);
|
||||
|
||||
#define GIT_ATTR_CHECK_FILE_THEN_INDEX ...
|
||||
#define GIT_ATTR_CHECK_INDEX_THEN_FILE ...
|
||||
#define GIT_ATTR_CHECK_INDEX_ONLY ...
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -62,3 +62,6 @@ def check_error(err, io=False):
|
||||
|
||||
# Generic Git error
|
||||
raise GitError(message)
|
||||
|
||||
# Indicate that we want libgit2 to pretend a function was not set
|
||||
Passthrough = Exception("The function asked for pass-through")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -29,7 +29,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import from pygit2
|
||||
from ._utils import get_ffi
|
||||
|
||||
|
||||
ffi, C = get_ffi()
|
||||
try:
|
||||
from ._libgit2 import ffi, lib as C
|
||||
except ImportError:
|
||||
from ._run import ffi, preamble, C_KEYWORDS
|
||||
C = ffi.verify(preamble, **C_KEYWORDS)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -48,6 +48,7 @@ class Index(object):
|
||||
err = C.git_index_open(cindex, to_bytes(path))
|
||||
check_error(err)
|
||||
|
||||
self._repo = None
|
||||
self._index = cindex[0]
|
||||
self._cindex = cindex
|
||||
|
||||
@@ -125,14 +126,15 @@ class Index(object):
|
||||
The tree will be read recursively and all its children will also be
|
||||
inserted into the Index.
|
||||
"""
|
||||
repo = self._repo
|
||||
if is_string(tree):
|
||||
tree = self._repo[tree]
|
||||
tree = repo[tree]
|
||||
|
||||
if isinstance(tree, Oid):
|
||||
if not hasattr(self, '_repo'):
|
||||
if repo is None:
|
||||
raise TypeError("id given but no associated repository")
|
||||
|
||||
tree = self._repo[tree]
|
||||
tree = repo[tree]
|
||||
elif not isinstance(tree, Tree):
|
||||
raise TypeError("argument must be Oid or Tree")
|
||||
|
||||
@@ -214,7 +216,8 @@ class Index(object):
|
||||
interhunk_lines: the maximum number of unchanged lines between hunk
|
||||
boundaries before the hunks will be merged into a one
|
||||
"""
|
||||
if not hasattr(self, '_repo'):
|
||||
repo = self._repo
|
||||
if repo is None:
|
||||
raise ValueError('diff needs an associated repository')
|
||||
|
||||
copts = ffi.new('git_diff_options *')
|
||||
@@ -226,11 +229,11 @@ class Index(object):
|
||||
copts.interhunk_lines = interhunk_lines
|
||||
|
||||
cdiff = ffi.new('git_diff **')
|
||||
err = C.git_diff_index_to_workdir(cdiff, self._repo._repo,
|
||||
self._index, copts)
|
||||
err = C.git_diff_index_to_workdir(cdiff, repo._repo, self._index,
|
||||
copts)
|
||||
check_error(err)
|
||||
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), self._repo)
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), repo)
|
||||
|
||||
def diff_to_tree(self, tree, flags=0, context_lines=3, interhunk_lines=0):
|
||||
"""Diff the index against a tree. Return a <Diff> object with the
|
||||
@@ -248,8 +251,8 @@ class Index(object):
|
||||
interhunk_lines: the maximum number of unchanged lines between hunk
|
||||
boundaries before the hunks will be merged into a one.
|
||||
"""
|
||||
|
||||
if not hasattr(self, '_repo'):
|
||||
repo = self._repo
|
||||
if repo is None:
|
||||
raise ValueError('diff needs an associated repository')
|
||||
|
||||
if not isinstance(tree, Tree):
|
||||
@@ -267,11 +270,11 @@ class Index(object):
|
||||
ffi.buffer(ctree)[:] = tree._pointer[:]
|
||||
|
||||
cdiff = ffi.new('git_diff **')
|
||||
err = C.git_diff_tree_to_index(cdiff, self._repo._repo, ctree[0],
|
||||
err = C.git_diff_tree_to_index(cdiff, repo._repo, ctree[0],
|
||||
self._index, copts)
|
||||
check_error(err)
|
||||
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), self._repo)
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), repo)
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
346
pygit2/remote.py
346
pygit2/remote.py
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -30,9 +30,8 @@ from __future__ import absolute_import
|
||||
|
||||
# Import from pygit2
|
||||
from _pygit2 import Oid
|
||||
from .errors import check_error, GitError
|
||||
from .errors import check_error, Passthrough
|
||||
from .ffi import ffi, C
|
||||
from .credentials import KeypairFromAgent
|
||||
from .refspec import Refspec
|
||||
from .utils import to_bytes, strarray_to_strings, StrArray
|
||||
|
||||
@@ -71,7 +70,27 @@ class TransferProgress(object):
|
||||
""""Number of bytes received up to now"""
|
||||
|
||||
|
||||
class Remote(object):
|
||||
class RemoteCallbacks(object):
|
||||
"""Base class for pygit2 remote callbacks.
|
||||
|
||||
Inherit from this class and override the callbacks which you want to use
|
||||
in your class, which you can then pass to the network operations.
|
||||
"""
|
||||
|
||||
def __init__(self, credentials=None, certificate=None):
|
||||
"""Initialize some callbacks in-line
|
||||
|
||||
Use this constructor to provide credentials and certificate
|
||||
callbacks in-line, instead of defining your own class for these ones.
|
||||
|
||||
You can e.g. also pass in one of the credential objects as 'credentials'
|
||||
instead of creating a function which returns a hard-coded object.
|
||||
"""
|
||||
|
||||
if credentials is not None:
|
||||
self.credentials = credentials
|
||||
if certificate is not None:
|
||||
self.certificate = certificate
|
||||
|
||||
def sideband_progress(self, string):
|
||||
"""Progress output callback
|
||||
@@ -80,7 +99,6 @@ class Remote(object):
|
||||
|
||||
:param str string: Progress output from the remote
|
||||
"""
|
||||
pass
|
||||
|
||||
def credentials(self, url, username_from_url, allowed_types):
|
||||
"""Credentials callback
|
||||
@@ -100,7 +118,26 @@ class Remote(object):
|
||||
|
||||
Return value: credential
|
||||
"""
|
||||
pass
|
||||
raise Passthrough
|
||||
|
||||
def certificate_check(self, certificate, valid, host):
|
||||
"""Certificate callback
|
||||
|
||||
Override with your own function to determine whether the accept
|
||||
the server's certificate.
|
||||
|
||||
:param None certificate: The certificate. It is currently always None
|
||||
while we figure out how to represent it cross-platform
|
||||
|
||||
:param bool valid: Whether the TLS/SSH library thinks the certificate
|
||||
is valid
|
||||
|
||||
:param str host: The hostname we want to connect to
|
||||
|
||||
Return value: True to connect, False to abort
|
||||
"""
|
||||
|
||||
raise Passthrough
|
||||
|
||||
def transfer_progress(self, stats):
|
||||
"""Transfer progress callback
|
||||
@@ -109,7 +146,6 @@ class Remote(object):
|
||||
|
||||
:param TransferProgress stats: The progress up to now
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_tips(self, refname, old, new):
|
||||
"""Update tips callabck
|
||||
@@ -131,6 +167,162 @@ class Remote(object):
|
||||
:param str messsage: rejection message from the remote. If None, the update was accepted.
|
||||
"""
|
||||
|
||||
def _fill_fetch_options(self, fetch_opts):
|
||||
fetch_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
fetch_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
fetch_opts.callbacks.update_tips = self._update_tips_cb
|
||||
fetch_opts.callbacks.credentials = self._credentials_cb
|
||||
fetch_opts.callbacks.certificate_check = self._certificate_cb
|
||||
# We need to make sure that this handle stays alive
|
||||
self._self_handle = ffi.new_handle(self)
|
||||
fetch_opts.callbacks.payload = self._self_handle
|
||||
|
||||
self._stored_exception = None
|
||||
|
||||
def _fill_push_options(self, push_opts):
|
||||
push_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
push_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
push_opts.callbacks.update_tips = self._update_tips_cb
|
||||
push_opts.callbacks.credentials = self._credentials_cb
|
||||
push_opts.callbacks.certificate_check = self._certificate_cb
|
||||
push_opts.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)
|
||||
push_opts.callbacks.payload = self._self_handle
|
||||
|
||||
# These functions exist to be called by the git_remote as
|
||||
# callbacks. They proxy the call to whatever the user set
|
||||
|
||||
@ffi.callback('git_transfer_progress_cb')
|
||||
def _transfer_progress_cb(stats_ptr, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
transfer_progress = getattr(self, 'transfer_progress', None)
|
||||
if not transfer_progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
transfer_progress(TransferProgress(stats_ptr))
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('git_transport_message_cb')
|
||||
def _sideband_progress_cb(string, length, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
progress = getattr(self, 'progress', None)
|
||||
if not progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = ffi.string(string, length).decode()
|
||||
progress(s)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*update_tips)(const char *refname, const git_oid *a,'
|
||||
'const git_oid *b, void *data)')
|
||||
def _update_tips_cb(refname, a, b, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
update_tips = getattr(self, 'update_tips', None)
|
||||
if not update_tips:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = maybe_string(refname)
|
||||
a = Oid(raw=bytes(ffi.buffer(a)[:]))
|
||||
b = Oid(raw=bytes(ffi.buffer(b)[:]))
|
||||
|
||||
update_tips(s, a, b)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
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)
|
||||
|
||||
push_update_reference = getattr(self, 'push_update_reference', None)
|
||||
if not push_update_reference:
|
||||
return 0
|
||||
|
||||
try:
|
||||
refname = ffi.string(ref)
|
||||
message = maybe_string(msg)
|
||||
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)')
|
||||
def _credentials_cb(cred_out, url, username, allowed, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
credentials = getattr(self, 'credentials', None)
|
||||
if not credentials:
|
||||
return 0
|
||||
|
||||
try:
|
||||
ccred = get_credentials(credentials, url, username, allowed)
|
||||
cred_out[0] = ccred[0]
|
||||
|
||||
except Exception as e:
|
||||
if e is Passthrough:
|
||||
return C.GIT_PASSTHROUGH
|
||||
|
||||
self._stored_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):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
# We want to simulate what should happen if libgit2 supported pass-through for
|
||||
# this callback. For SSH, 'valid' is always False, because it doesn't look
|
||||
# at known_hosts, but we do want to let it through in order to do what libgit2 would
|
||||
# if the callback were not set.
|
||||
try:
|
||||
is_ssh = cert_i.cert_type == C.GIT_CERT_HOSTKEY_LIBSSH2
|
||||
|
||||
certificate_check = getattr(self, 'certificate_check', None)
|
||||
if not certificate_check:
|
||||
raise Passthrough
|
||||
|
||||
# python's parsing is deep in the libraries and assumes an OpenSSL-owned cert
|
||||
val = certificate_check(None, bool(valid), ffi.string(host))
|
||||
if not val:
|
||||
return C.GIT_ECERTIFICATE
|
||||
except Exception as e:
|
||||
if e is Passthrough:
|
||||
if is_ssh:
|
||||
return 0
|
||||
elif valid:
|
||||
return 0
|
||||
else:
|
||||
return C.GIT_ECERTIFICATE
|
||||
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
class Remote(object):
|
||||
def __init__(self, repo, ptr):
|
||||
"""The constructor is for internal use only"""
|
||||
|
||||
@@ -165,7 +357,7 @@ class Remote(object):
|
||||
err = C.git_remote_save(self._remote)
|
||||
check_error(err)
|
||||
|
||||
def fetch(self, refspecs=None, message=None):
|
||||
def fetch(self, refspecs=None, message=None, callbacks=None):
|
||||
"""Perform a fetch against this remote. Returns a <TransferProgress>
|
||||
object.
|
||||
"""
|
||||
@@ -173,24 +365,19 @@ class Remote(object):
|
||||
fetch_opts = ffi.new('git_fetch_options *')
|
||||
err = C.git_fetch_init_options(fetch_opts, C.GIT_FETCH_OPTIONS_VERSION)
|
||||
|
||||
fetch_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
fetch_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
fetch_opts.callbacks.update_tips = self._update_tips_cb
|
||||
fetch_opts.callbacks.credentials = self._credentials_cb
|
||||
# We need to make sure that this handle stays alive
|
||||
self._self_handle = ffi.new_handle(self)
|
||||
fetch_opts.callbacks.payload = self._self_handle
|
||||
if callbacks is None:
|
||||
callbacks = RemoteCallbacks()
|
||||
|
||||
self._stored_exception = None
|
||||
callbacks._fill_fetch_options(fetch_opts)
|
||||
|
||||
try:
|
||||
with StrArray(refspecs) as arr:
|
||||
err = C.git_remote_fetch(self._remote, arr, fetch_opts, to_bytes(message))
|
||||
if self._stored_exception:
|
||||
raise self._stored_exception
|
||||
if callbacks._stored_exception:
|
||||
raise callbacks._stored_exception
|
||||
check_error(err)
|
||||
finally:
|
||||
self._self_handle = None
|
||||
callbacks._self_handle = None
|
||||
|
||||
return TransferProgress(C.git_remote_stats(self._remote))
|
||||
|
||||
@@ -225,7 +412,7 @@ class Remote(object):
|
||||
|
||||
return strarray_to_strings(specs)
|
||||
|
||||
def push(self, specs):
|
||||
def push(self, specs, callbacks=None):
|
||||
"""Push the given refspec to the remote. Raises ``GitError`` on
|
||||
protocol error or unpack failure.
|
||||
|
||||
@@ -234,114 +421,18 @@ class Remote(object):
|
||||
push_opts = ffi.new('git_push_options *')
|
||||
err = C.git_push_init_options(push_opts, C.GIT_PUSH_OPTIONS_VERSION)
|
||||
|
||||
if callbacks is None:
|
||||
callbacks = RemoteCallbacks()
|
||||
|
||||
callbacks._fill_push_options(push_opts)
|
||||
# Build custom callback structure
|
||||
push_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
push_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
push_opts.callbacks.update_tips = self._update_tips_cb
|
||||
push_opts.callbacks.credentials = self._credentials_cb
|
||||
push_opts.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)
|
||||
push_opts.callbacks.payload = self._self_handle
|
||||
|
||||
try:
|
||||
with StrArray(specs) as refspecs:
|
||||
err = C.git_remote_push(self._remote, refspecs, ffi.NULL)
|
||||
err = C.git_remote_push(self._remote, refspecs, push_opts)
|
||||
check_error(err)
|
||||
finally:
|
||||
self._self_handle = None
|
||||
|
||||
# These functions exist to be called by the git_remote as
|
||||
# callbacks. They proxy the call to whatever the user set
|
||||
|
||||
@ffi.callback('git_transfer_progress_cb')
|
||||
def _transfer_progress_cb(stats_ptr, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'transfer_progress') \
|
||||
or not self.transfer_progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
self.transfer_progress(TransferProgress(stats_ptr))
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('git_transport_message_cb')
|
||||
def _sideband_progress_cb(string, length, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'progress') or not self.progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = ffi.string(string, length).decode()
|
||||
self.progress(s)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*update_tips)(const char *refname, const git_oid *a,'
|
||||
'const git_oid *b, void *data)')
|
||||
def _update_tips_cb(refname, a, b, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'update_tips') or not self.update_tips:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = maybe_string(refname)
|
||||
a = Oid(raw=bytes(ffi.buffer(a)[:]))
|
||||
b = Oid(raw=bytes(ffi.buffer(b)[:]))
|
||||
|
||||
self.update_tips(s, a, b)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
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)')
|
||||
def _credentials_cb(cred_out, url, username, allowed, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'credentials') or not self.credentials:
|
||||
return 0
|
||||
|
||||
try:
|
||||
ccred = get_credentials(self.credentials, url, username, allowed)
|
||||
cred_out[0] = ccred[0]
|
||||
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
callbacks._self_handle = None
|
||||
|
||||
def get_credentials(fn, url, username, allowed):
|
||||
"""Call fn and return the credentials object"""
|
||||
@@ -351,23 +442,24 @@ def get_credentials(fn, url, username, allowed):
|
||||
|
||||
creds = fn(url_str, username_str, allowed)
|
||||
|
||||
if not hasattr(creds, 'credential_type') \
|
||||
or not hasattr(creds, 'credential_tuple'):
|
||||
credential_type = getattr(creds, 'credential_type', None)
|
||||
credential_tuple = getattr(creds, 'credential_tuple', None)
|
||||
if not credential_type or not credential_tuple:
|
||||
raise TypeError("credential does not implement interface")
|
||||
|
||||
cred_type = creds.credential_type
|
||||
cred_type = credential_type
|
||||
|
||||
if not (allowed & cred_type):
|
||||
raise TypeError("invalid credential type")
|
||||
|
||||
ccred = ffi.new('git_cred **')
|
||||
if cred_type == C.GIT_CREDTYPE_USERPASS_PLAINTEXT:
|
||||
name, passwd = creds.credential_tuple
|
||||
name, passwd = credential_tuple
|
||||
err = C.git_cred_userpass_plaintext_new(ccred, to_bytes(name),
|
||||
to_bytes(passwd))
|
||||
|
||||
elif cred_type == C.GIT_CREDTYPE_SSH_KEY:
|
||||
name, pubkey, privkey, passphrase = creds.credential_tuple
|
||||
name, pubkey, privkey, passphrase = credential_tuple
|
||||
if pubkey is None and privkey is None:
|
||||
err = C.git_cred_ssh_key_from_agent(ccred, to_bytes(name))
|
||||
else:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -637,6 +637,100 @@ class Repository(_Repository):
|
||||
|
||||
return Index.from_c(self, cindex)
|
||||
|
||||
#
|
||||
# Describe
|
||||
#
|
||||
def describe(self, committish=None, max_candidates_tags=None,
|
||||
describe_strategy=None, pattern=None,
|
||||
only_follow_first_parent=None,
|
||||
show_commit_oid_as_fallback=None, abbreviated_size=None,
|
||||
always_use_long_format=None, dirty_suffix=None):
|
||||
"""Describe a commit-ish or the current working tree.
|
||||
|
||||
:param committish: Commit-ish object or object name to describe, or
|
||||
`None` to describe the current working tree.
|
||||
:type committish: `str`, :class:`~.Reference`, or :class:`~.Commit`
|
||||
|
||||
:param int max_candidates_tags: The number of candidate tags to
|
||||
consider. Increasing above 10 will take slightly longer but may
|
||||
produce a more accurate result. A value of 0 will cause only exact
|
||||
matches to be output.
|
||||
:param int describe_strategy: A GIT_DESCRIBE_* constant.
|
||||
:param str pattern: Only consider tags matching the given `glob(7)`
|
||||
pattern, excluding the "refs/tags/" prefix.
|
||||
:param bool only_follow_first_parent: Follow only the first parent
|
||||
commit upon seeing a merge commit.
|
||||
:param bool show_commit_oid_as_fallback: Show uniquely abbreviated
|
||||
commit object as fallback.
|
||||
:param int abbreviated_size: The minimum number of hexadecimal digits
|
||||
to show for abbreviated object names. A value of 0 will suppress
|
||||
long format, only showing the closest tag.
|
||||
:param bool always_use_long_format: Always output the long format (the
|
||||
nearest tag, the number of commits, and the abbrevated commit name)
|
||||
even when the committish matches a tag.
|
||||
:param str dirty_suffix: A string to append if the working tree is
|
||||
dirty.
|
||||
|
||||
:returns: The description.
|
||||
:rtype: `str`
|
||||
|
||||
Example::
|
||||
|
||||
repo.describe(pattern='public/*', dirty_suffix='-dirty')
|
||||
"""
|
||||
|
||||
options = ffi.new('git_describe_options *')
|
||||
C.git_describe_init_options(options, C.GIT_DESCRIBE_OPTIONS_VERSION)
|
||||
|
||||
if max_candidates_tags is not None:
|
||||
options.max_candidates_tags = max_candidates_tags
|
||||
if describe_strategy is not None:
|
||||
options.describe_strategy = describe_strategy
|
||||
if pattern:
|
||||
options.pattern = ffi.new('char[]', to_bytes(pattern))
|
||||
if only_follow_first_parent is not None:
|
||||
options.only_follow_first_parent = only_follow_first_parent
|
||||
if show_commit_oid_as_fallback is not None:
|
||||
options.show_commit_oid_as_fallback = show_commit_oid_as_fallback
|
||||
|
||||
result = ffi.new('git_describe_result **')
|
||||
if committish:
|
||||
if is_string(committish):
|
||||
committish = self.revparse_single(committish)
|
||||
|
||||
commit = committish.peel(Commit)
|
||||
|
||||
cptr = ffi.new('git_object **')
|
||||
ffi.buffer(cptr)[:] = commit._pointer[:]
|
||||
|
||||
err = C.git_describe_commit(result, cptr[0], options)
|
||||
else:
|
||||
err = C.git_describe_workdir(result, self._repo, options)
|
||||
check_error(err)
|
||||
|
||||
try:
|
||||
format_options = ffi.new('git_describe_format_options *')
|
||||
C.git_describe_init_format_options(format_options, C.GIT_DESCRIBE_FORMAT_OPTIONS_VERSION)
|
||||
|
||||
if abbreviated_size is not None:
|
||||
format_options.abbreviated_size = abbreviated_size
|
||||
if always_use_long_format is not None:
|
||||
format_options.always_use_long_format = always_use_long_format
|
||||
if dirty_suffix:
|
||||
format_options.dirty_suffix = ffi.new('char[]', to_bytes(dirty_suffix))
|
||||
|
||||
buf = ffi.new('git_buf *', (ffi.NULL, 0))
|
||||
|
||||
err = C.git_describe_format(buf, result[0], format_options)
|
||||
check_error(err)
|
||||
|
||||
try:
|
||||
return ffi.string(buf.ptr).decode('utf-8')
|
||||
finally:
|
||||
C.git_buf_free(buf)
|
||||
finally:
|
||||
C.git_describe_result_free(result[0])
|
||||
|
||||
#
|
||||
# Utility for writing a tree into an archive
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
115
setup.py
115
setup.py
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# coding: UTF-8
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -45,9 +45,20 @@ from subprocess import Popen, PIPE
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Get cffi major version
|
||||
try:
|
||||
import cffi
|
||||
except ImportError:
|
||||
cffi_major_version = None
|
||||
else:
|
||||
cffi_major_version = cffi.__version_info__[0]
|
||||
|
||||
# Import stuff from pygit2/_utils.py without loading the whole pygit2 package
|
||||
sys.path.insert(0, 'pygit2')
|
||||
from _utils import __version__, get_libgit2_paths, get_ffi
|
||||
from _build import __version__, get_libgit2_paths
|
||||
if cffi_major_version == 0:
|
||||
from _run import ffi, preamble, C_KEYWORDS
|
||||
ffi.verify(preamble, **C_KEYWORDS)
|
||||
del sys.path[0]
|
||||
|
||||
# Python 2 support
|
||||
@@ -95,19 +106,42 @@ class TestCommand(Command):
|
||||
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.
|
||||
"""
|
||||
def finalize_options(self):
|
||||
ffi, C = get_ffi()
|
||||
self.distribution.ext_modules.append(ffi.verifier.get_extension())
|
||||
build.finalize_options(self)
|
||||
class sdist_files_from_git(sdist):
|
||||
def get_file_list(self):
|
||||
popen = Popen(['git', 'ls-files'], stdout=PIPE, stderr=PIPE)
|
||||
stdoutdata, stderrdata = popen.communicate()
|
||||
if popen.returncode != 0:
|
||||
print(stderrdata)
|
||||
sys.exit()
|
||||
|
||||
for line in stdoutdata.splitlines():
|
||||
# Skip hidden files at the root
|
||||
if line[0] == '.':
|
||||
continue
|
||||
self.filelist.append(line)
|
||||
|
||||
# Ok
|
||||
self.filelist.sort()
|
||||
self.filelist.remove_duplicates()
|
||||
self.write_manifest()
|
||||
|
||||
|
||||
class BuildWithDLLs(CFFIBuild):
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Version Control"]
|
||||
|
||||
# On Windows, we install the git2.dll too.
|
||||
with codecs.open('README.rst', 'r', 'utf-8') as readme:
|
||||
long_description = readme.read()
|
||||
|
||||
cmdclass = {
|
||||
'test': TestCommand,
|
||||
'sdist': sdist_files_from_git,
|
||||
}
|
||||
|
||||
|
||||
# On Windows, we install the git2.dll too.
|
||||
class BuildWithDLLs(build):
|
||||
def _get_dlls(self):
|
||||
# return a list of (FQ-in-name, relative-out-name) tuples.
|
||||
ret = []
|
||||
@@ -133,45 +167,27 @@ class BuildWithDLLs(CFFIBuild):
|
||||
|
||||
def run(self):
|
||||
build.run(self)
|
||||
# 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.
|
||||
if os.name == 'nt':
|
||||
cmdclass['build'] = BuildWithDLLs
|
||||
|
||||
class sdist_files_from_git(sdist):
|
||||
def get_file_list(self):
|
||||
popen = Popen(['git', 'ls-files'], stdout=PIPE, stderr=PIPE)
|
||||
stdoutdata, stderrdata = popen.communicate()
|
||||
if popen.returncode != 0:
|
||||
print(stderrdata)
|
||||
sys.exit()
|
||||
extra_args = {
|
||||
'ext_modules': [
|
||||
Extension('_pygit2', pygit2_exts, libraries=['git2'],
|
||||
include_dirs=[libgit2_include],
|
||||
library_dirs=[libgit2_lib]),
|
||||
# FFI is added in the build step
|
||||
],
|
||||
}
|
||||
|
||||
for line in stdoutdata.splitlines():
|
||||
# Skip hidden files at the root
|
||||
if line[0] == '.':
|
||||
continue
|
||||
self.filelist.append(line)
|
||||
if cffi_major_version == 0:
|
||||
extra_args['ext_modules'].append(ffi.verifier.get_extension())
|
||||
else:
|
||||
extra_args['cffi_modules']=['pygit2/_run.py:ffi']
|
||||
|
||||
# Ok
|
||||
self.filelist.sort()
|
||||
self.filelist.remove_duplicates()
|
||||
self.write_manifest()
|
||||
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Version Control"]
|
||||
|
||||
|
||||
with codecs.open('README.rst', 'r', 'utf-8') as readme:
|
||||
long_description = readme.read()
|
||||
|
||||
|
||||
cmdclass = {
|
||||
'build': BuildWithDLLs if os.name == 'nt' else CFFIBuild,
|
||||
'test': TestCommand,
|
||||
'sdist': sdist_files_from_git,
|
||||
}
|
||||
|
||||
setup(name='pygit2',
|
||||
description='Python bindings for libgit2.',
|
||||
@@ -188,10 +204,5 @@ setup(name='pygit2',
|
||||
setup_requires=['cffi'],
|
||||
install_requires=['cffi'],
|
||||
zip_safe=False,
|
||||
ext_modules=[
|
||||
Extension('_pygit2', pygit2_exts, libraries=['git2'],
|
||||
include_dirs=[libgit2_include],
|
||||
library_dirs=[libgit2_lib]),
|
||||
# FFI is added in the build step
|
||||
],
|
||||
cmdclass=cmdclass)
|
||||
cmdclass=cmdclass,
|
||||
**extra_args)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@@ -482,7 +482,8 @@ Diff_len(Diff *self)
|
||||
return (Py_ssize_t)git_diff_num_deltas(self->diff);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Diff_patch__doc__, "Patch diff string.");
|
||||
PyDoc_STRVAR(Diff_patch__doc__,
|
||||
"Patch diff string. Can be None in some cases, such as empty commits.");
|
||||
|
||||
PyObject *
|
||||
Diff_patch__get__(Diff *self)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@@ -323,6 +323,7 @@ moduleinit(PyObject* m)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_IGNORE_CASE)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_SHOW_UNTRACKED_CONTENT)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_SKIP_BINARY_CHECK)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_SHOW_BINARY)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE_TREES)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_IGNORED_DIRS)
|
||||
@@ -380,6 +381,11 @@ moduleinit(PyObject* m)
|
||||
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_FASTFORWARD)
|
||||
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UNBORN)
|
||||
|
||||
/* Describe */
|
||||
ADD_CONSTANT_INT(m, GIT_DESCRIBE_DEFAULT);
|
||||
ADD_CONSTANT_INT(m, GIT_DESCRIBE_TAGS);
|
||||
ADD_CONSTANT_INT(m, GIT_DESCRIBE_ALL);
|
||||
|
||||
/* Global initialization of libgit2 */
|
||||
git_libgit2_init();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@@ -842,6 +842,68 @@ Repository_create_blob_fromdisk(Repository *self, PyObject *args)
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_create_blob_fromiobase__doc__,
|
||||
"create_blob_fromiobase(io.IOBase) -> Oid\n"
|
||||
"\n"
|
||||
"Create a new blob from an IOBase object.");
|
||||
|
||||
|
||||
int read_chunk(char *content, size_t max_length, void *payload)
|
||||
{
|
||||
PyObject *py_file;
|
||||
PyObject *py_bytes;
|
||||
char *bytes;
|
||||
Py_ssize_t size;
|
||||
|
||||
py_file = (PyObject *)payload;
|
||||
py_bytes = PyObject_CallMethod(py_file, "read", "i", max_length);
|
||||
if (!py_bytes)
|
||||
return -1;
|
||||
|
||||
size = 0;
|
||||
if (py_bytes != Py_None) {
|
||||
bytes = PyBytes_AsString(py_bytes);
|
||||
size = PyBytes_Size(py_bytes);
|
||||
memcpy(content, bytes, size);
|
||||
}
|
||||
|
||||
Py_DECREF(py_bytes);
|
||||
return size;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
Repository_create_blob_fromiobase(Repository *self, PyObject *py_file)
|
||||
{
|
||||
git_oid oid;
|
||||
PyObject *py_is_readable;
|
||||
int is_readable;
|
||||
int err;
|
||||
|
||||
py_is_readable = PyObject_CallMethod(py_file, "readable", NULL);
|
||||
if (!py_is_readable) {
|
||||
if (PyErr_ExceptionMatches(PyExc_AttributeError))
|
||||
PyErr_SetObject(PyExc_TypeError, py_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
is_readable = PyObject_IsTrue(py_is_readable);
|
||||
Py_DECREF(py_is_readable);
|
||||
|
||||
if (!is_readable) {
|
||||
Py_DECREF(py_file);
|
||||
PyErr_SetString(PyExc_TypeError, "expected readable IO type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = git_blob_create_fromchunks(&oid, self->repo, NULL, &read_chunk,
|
||||
py_file);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
return git_oid_to_python(&oid);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_create_commit__doc__,
|
||||
"create_commit(reference_name, author, committer, message, tree, parents[, encoding]) -> Oid\n"
|
||||
"\n"
|
||||
@@ -1547,6 +1609,7 @@ PyMethodDef Repository_methods[] = {
|
||||
METHOD(Repository, create_blob, METH_VARARGS),
|
||||
METHOD(Repository, create_blob_fromworkdir, METH_VARARGS),
|
||||
METHOD(Repository, create_blob_fromdisk, METH_VARARGS),
|
||||
METHOD(Repository, create_blob_fromiobase, METH_O),
|
||||
METHOD(Repository, create_commit, METH_VARARGS),
|
||||
METHOD(Repository, create_tag, METH_VARARGS),
|
||||
METHOD(Repository, TreeBuilder, METH_VARARGS),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@@ -38,7 +38,7 @@ Signature_init(Signature *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
char *keywords[] = {"name", "email", "time", "offset", "encoding", NULL};
|
||||
PyObject *py_name, *tname;
|
||||
char *email, *encoding = "ascii";
|
||||
char *email, *encoding = "utf-8";
|
||||
const char *name;
|
||||
long long time = -1;
|
||||
int offset = 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@@ -111,7 +111,11 @@ PyDoc_STRVAR(Tag__message__doc__, "Tag message (bytes).");
|
||||
PyObject *
|
||||
Tag__message__get__(Tag *self)
|
||||
{
|
||||
return PyBytes_FromString(git_tag_message(self->tag));
|
||||
const char *message;
|
||||
message = git_tag_message(self->tag);
|
||||
if (!message)
|
||||
Py_RETURN_NONE;
|
||||
return PyBytes_FromString(message);
|
||||
}
|
||||
|
||||
PyMethodDef Tag_methods[] = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
22
src/tree.c
22
src/tree.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@@ -67,6 +67,24 @@ TreeEntry_name__get__(TreeEntry *self)
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(TreeEntry__name__doc__, "Name (bytes).");
|
||||
|
||||
PyObject *
|
||||
TreeEntry__name__get__(TreeEntry *self)
|
||||
{
|
||||
return PyBytes_FromString(git_tree_entry_name(self->entry));
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(TreeEntry_type__doc__, "Type.");
|
||||
|
||||
PyObject *
|
||||
TreeEntry_type__get__(TreeEntry *self)
|
||||
{
|
||||
return to_path(git_object_type2string(git_tree_entry_type(self->entry)));
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(TreeEntry_id__doc__, "Object id.");
|
||||
|
||||
PyObject *
|
||||
@@ -168,9 +186,11 @@ TreeEntry_repr(TreeEntry *self)
|
||||
PyGetSetDef TreeEntry_getseters[] = {
|
||||
GETTER(TreeEntry, filemode),
|
||||
GETTER(TreeEntry, name),
|
||||
GETTER(TreeEntry, _name),
|
||||
GETTER(TreeEntry, oid),
|
||||
GETTER(TreeEntry, id),
|
||||
GETTER(TreeEntry, hex),
|
||||
GETTER(TreeEntry, type),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2015 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
BIN
test/data/binaryfilerepo.tar
Normal file
BIN
test/data/binaryfilerepo.tar
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -30,6 +30,7 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
from os.path import dirname, join
|
||||
import io
|
||||
import unittest
|
||||
|
||||
import pygit2
|
||||
@@ -112,6 +113,19 @@ class BlobTest(utils.RepoTestCase):
|
||||
self.assertTrue(isinstance(blob, pygit2.Blob))
|
||||
self.assertEqual(pygit2.GIT_OBJ_BLOB, blob.type)
|
||||
|
||||
def test_create_blob_fromiobase(self):
|
||||
self.assertRaises(TypeError, self.repo.create_blob_fromiobase, 'bad type')
|
||||
|
||||
f = io.BytesIO(BLOB_CONTENT)
|
||||
blob_oid = self.repo.create_blob_fromiobase(f)
|
||||
blob = self.repo[blob_oid]
|
||||
|
||||
self.assertTrue(isinstance(blob, pygit2.Blob))
|
||||
self.assertEqual(pygit2.GIT_OBJ_BLOB, blob.type)
|
||||
|
||||
self.assertEqual(blob_oid, blob.id)
|
||||
self.assertEqual(BLOB_SHA, blob_oid.hex)
|
||||
|
||||
def test_diff_blob(self):
|
||||
blob = self.repo[BLOB_SHA]
|
||||
old_blob = self.repo['3b18e512dba79e4c8300dd08aeb37f8e728b8dad']
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -70,32 +70,37 @@ class CredentialCreateTest(utils.NoRepoTestCase):
|
||||
|
||||
class CredentialCallback(utils.RepoTestCase):
|
||||
def test_callback(self):
|
||||
def credentials_cb(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
raise Exception("I don't know the password")
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
@staticmethod
|
||||
def credentials(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
raise Exception("I don't know the password")
|
||||
|
||||
remote = self.repo.create_remote("github", "https://github.com/github/github")
|
||||
remote.credentials = credentials_cb
|
||||
url = "https://github.com/github/github"
|
||||
remote = self.repo.create_remote("github", url)
|
||||
|
||||
self.assertRaises(Exception, remote.fetch)
|
||||
self.assertRaises(Exception, lambda: remote.fetch(callbacks=MyCallbacks()))
|
||||
|
||||
def test_bad_cred_type(self):
|
||||
def credentials_cb(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
return Keypair("git", "foo.pub", "foo", "sekkrit")
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
@staticmethod
|
||||
def credentials(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
return Keypair("git", "foo.pub", "foo", "sekkrit")
|
||||
|
||||
remote = self.repo.create_remote("github", "https://github.com/github/github")
|
||||
remote.credentials = credentials_cb
|
||||
|
||||
self.assertRaises(TypeError, remote.fetch)
|
||||
url = "https://github.com/github/github"
|
||||
remote = self.repo.create_remote("github", url)
|
||||
self.assertRaises(TypeError, lambda: remote.fetch(callbacks=MyCallbacks()))
|
||||
|
||||
class CallableCredentialTest(utils.RepoTestCase):
|
||||
|
||||
def test_user_pass(self):
|
||||
remote = self.repo.create_remote("bb", "https://bitbucket.org/libgit2/testgitrepository.git")
|
||||
remote.credentials = UserPass("libgit2", "libgit2")
|
||||
credentials = UserPass("libgit2", "libgit2")
|
||||
callbacks = pygit2.RemoteCallbacks(credentials=credentials)
|
||||
|
||||
remote.fetch()
|
||||
url = "https://bitbucket.org/libgit2/testgitrepository.git"
|
||||
remote = self.repo.create_remote("bb", url)
|
||||
remote.fetch(callbacks=callbacks)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
106
test/test_describe.py
Normal file
106
test/test_describe.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# In addition to the permissions in the GNU General Public License,
|
||||
# the authors give you unlimited permission to link the compiled
|
||||
# version of this file into combinations with other programs,
|
||||
# and to distribute those combinations without any restriction
|
||||
# coming from the use of this file. (The General Public License
|
||||
# restrictions do apply in other respects; for example, they cover
|
||||
# modification of the file, and distribution when not linked into
|
||||
# a combined executable.)
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""Tests for describing commits."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
|
||||
from pygit2 import GIT_DESCRIBE_DEFAULT, GIT_DESCRIBE_TAGS, GIT_DESCRIBE_ALL
|
||||
import pygit2
|
||||
from . import utils
|
||||
|
||||
|
||||
def add_tag(repo, name, target):
|
||||
message = 'Example tag.\n'
|
||||
tagger = pygit2.Signature('John Doe', 'jdoe@example.com', 12347, 0)
|
||||
|
||||
sha = repo.create_tag(name, target, pygit2.GIT_OBJ_COMMIT, tagger, message)
|
||||
return sha
|
||||
|
||||
|
||||
class DescribeTest(utils.RepoTestCase):
|
||||
|
||||
def test_describe(self):
|
||||
add_tag(self.repo, 'thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertEqual('thetag-2-g2be5719', self.repo.describe())
|
||||
|
||||
def test_describe_without_ref(self):
|
||||
self.assertRaises(pygit2.GitError, self.repo.describe)
|
||||
|
||||
def test_describe_default_oid(self):
|
||||
self.assertEqual('2be5719', self.repo.describe(show_commit_oid_as_fallback=True))
|
||||
|
||||
def test_describe_strategies(self):
|
||||
self.assertEqual('heads/master', self.repo.describe(describe_strategy=GIT_DESCRIBE_ALL))
|
||||
|
||||
self.repo.create_reference('refs/tags/thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertRaises(KeyError, self.repo.describe)
|
||||
self.assertEqual('thetag-2-g2be5719', self.repo.describe(describe_strategy=GIT_DESCRIBE_TAGS))
|
||||
|
||||
def test_describe_pattern(self):
|
||||
add_tag(self.repo, 'private/tag1', '5ebeeebb320790caf276b9fc8b24546d63316533')
|
||||
add_tag(self.repo, 'public/tag2', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
|
||||
self.assertEqual('public/tag2-2-g2be5719', self.repo.describe(pattern='public/*'))
|
||||
|
||||
def test_describe_committish(self):
|
||||
add_tag(self.repo, 'thetag', 'acecd5ea2924a4b900e7e149496e1f4b57976e51')
|
||||
self.assertEqual('thetag-4-g2be5719', self.repo.describe(committish='HEAD'))
|
||||
self.assertEqual('thetag-1-g5ebeeeb', self.repo.describe(committish='HEAD^'))
|
||||
|
||||
self.assertEqual('thetag-4-g2be5719', self.repo.describe(committish=self.repo.head))
|
||||
|
||||
self.assertEqual('thetag-1-g6aaa262', self.repo.describe(committish='6aaa262e655dd54252e5813c8e5acd7780ed097d'))
|
||||
self.assertEqual('thetag-1-g6aaa262', self.repo.describe(committish='6aaa262'))
|
||||
|
||||
def test_describe_follows_first_branch_only(self):
|
||||
add_tag(self.repo, 'thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertRaises(KeyError, self.repo.describe, only_follow_first_parent=True)
|
||||
|
||||
def test_describe_abbreviated_size(self):
|
||||
add_tag(self.repo, 'thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertEqual('thetag-2-g2be5719152d4f82c', self.repo.describe(abbreviated_size=16))
|
||||
self.assertEqual('thetag', self.repo.describe(abbreviated_size=0))
|
||||
|
||||
def test_describe_long_format(self):
|
||||
add_tag(self.repo, 'thetag', '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98')
|
||||
self.assertEqual('thetag-0-g2be5719', self.repo.describe(always_use_long_format=True))
|
||||
|
||||
|
||||
class DescribeDirtyWorkdirTest(utils.DirtyRepoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(utils.DirtyRepoTestCase, self).setUp()
|
||||
add_tag(self.repo, 'thetag', 'a763aa560953e7cfb87ccbc2f536d665aa4dff22')
|
||||
|
||||
def test_describe(self):
|
||||
self.assertEqual('thetag', self.repo.describe())
|
||||
|
||||
def test_describe_with_dirty_suffix(self):
|
||||
self.assertEqual('thetag-dirty', self.repo.describe(dirty_suffix='-dirty'))
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -33,6 +33,7 @@ import unittest
|
||||
import pygit2
|
||||
from pygit2 import GIT_DIFF_INCLUDE_UNMODIFIED
|
||||
from pygit2 import GIT_DIFF_IGNORE_WHITESPACE, GIT_DIFF_IGNORE_WHITESPACE_EOL
|
||||
from pygit2 import GIT_DIFF_SHOW_BINARY
|
||||
from pygit2 import GIT_DELTA_RENAMED
|
||||
from . import utils
|
||||
from itertools import chain
|
||||
@@ -63,6 +64,22 @@ index 297efb8..0000000
|
||||
-c/d contents
|
||||
"""
|
||||
|
||||
PATCH_BINARY = """diff --git a/binary_file b/binary_file
|
||||
index 86e5c10..b835d73 100644
|
||||
Binary files a/binary_file and b/binary_file differ
|
||||
"""
|
||||
|
||||
PATCH_BINARY_SHOW = """diff --git a/binary_file b/binary_file
|
||||
index 86e5c1008b5ce635d3e3fffa4434c5eccd8f00b6..b835d73543244b6694f36a8c5dfdffb71b153db7 100644
|
||||
GIT binary patch
|
||||
literal 8
|
||||
Pc${NM%FIhFs^kIy3n&7R
|
||||
|
||||
literal 8
|
||||
Pc${NM&PdElPvrst3ey5{
|
||||
|
||||
"""
|
||||
|
||||
DIFF_HEAD_TO_INDEX_EXPECTED = [
|
||||
'staged_changes',
|
||||
'staged_changes_file_deleted',
|
||||
@@ -308,5 +325,15 @@ class DiffTest(utils.BareRepoTestCase):
|
||||
width=80)
|
||||
self.assertEqual(STATS_EXPECTED, formatted)
|
||||
|
||||
|
||||
class BinaryDiffTest(utils.BinaryFileRepoTestCase):
|
||||
def test_binary_diff(self):
|
||||
repo = self.repo
|
||||
diff = repo.diff('HEAD', 'HEAD^')
|
||||
self.assertEqual(PATCH_BINARY, diff.patch)
|
||||
diff = repo.diff('HEAD', 'HEAD^', flags=GIT_DIFF_SHOW_BINARY)
|
||||
self.assertEqual(PATCH_BINARY_SHOW, diff.patch)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -212,31 +212,37 @@ class EmptyRepositoryTest(utils.EmptyRepoTestCase):
|
||||
self.assertEqual(stats.received_objects, REMOTE_REPO_OBJECTS)
|
||||
|
||||
def test_transfer_progress(self):
|
||||
self.tp = None
|
||||
def tp_cb(stats):
|
||||
self.tp = stats
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
def transfer_progress(self, stats):
|
||||
self.tp = stats
|
||||
|
||||
callbacks = MyCallbacks()
|
||||
remote = self.repo.remotes[0]
|
||||
remote.transfer_progress = tp_cb
|
||||
stats = remote.fetch()
|
||||
self.assertEqual(stats.received_bytes, self.tp.received_bytes)
|
||||
self.assertEqual(stats.indexed_objects, self.tp.indexed_objects)
|
||||
self.assertEqual(stats.received_objects, self.tp.received_objects)
|
||||
stats = remote.fetch(callbacks=callbacks)
|
||||
self.assertEqual(stats.received_bytes, callbacks.tp.received_bytes)
|
||||
self.assertEqual(stats.indexed_objects, callbacks.tp.indexed_objects)
|
||||
self.assertEqual(stats.received_objects, callbacks.tp.received_objects)
|
||||
|
||||
def test_update_tips(self):
|
||||
remote = self.repo.remotes[0]
|
||||
self.i = 0
|
||||
self.tips = [('refs/remotes/origin/master', Oid(hex='0'*40),
|
||||
Oid(hex='784855caf26449a1914d2cf62d12b9374d76ae78')),
|
||||
('refs/tags/root', Oid(hex='0'*40),
|
||||
Oid(hex='3d2962987c695a29f1f80b6c3aa4ec046ef44369'))]
|
||||
tips = [('refs/remotes/origin/master', Oid(hex='0'*40),
|
||||
Oid(hex='784855caf26449a1914d2cf62d12b9374d76ae78')),
|
||||
('refs/tags/root', Oid(hex='0'*40),
|
||||
Oid(hex='3d2962987c695a29f1f80b6c3aa4ec046ef44369'))]
|
||||
|
||||
def ut_cb(name, old, new):
|
||||
self.assertEqual(self.tips[self.i], (name, old, new))
|
||||
self.i += 1
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
def __init__(self, test_self, tips):
|
||||
self.test = test_self
|
||||
self.tips = tips
|
||||
self.i = 0
|
||||
|
||||
remote.update_tips = ut_cb
|
||||
remote.fetch()
|
||||
def update_tips(self, name, old, new):
|
||||
self.test.assertEqual(self.tips[self.i], (name, old, new))
|
||||
self.i += 1
|
||||
|
||||
callbacks = MyCallbacks(self, tips)
|
||||
remote.fetch(callbacks=callbacks)
|
||||
self.assertTrue(callbacks.i > 0)
|
||||
|
||||
class PushTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -514,10 +514,9 @@ class CloneRepositoryTest(utils.NoRepoTestCase):
|
||||
self.assertIsNotNone(repo.remotes["custom_remote"])
|
||||
|
||||
def test_clone_with_credentials(self):
|
||||
credentials = pygit2.UserPass("libgit2", "libgit2")
|
||||
repo = clone_repository(
|
||||
"https://bitbucket.org/libgit2/testgitrepository.git",
|
||||
self._temp_dir, credentials=credentials)
|
||||
self._temp_dir, callbacks=pygit2.RemoteCallbacks(credentials=pygit2.UserPass("libgit2", "libgit2")))
|
||||
|
||||
self.assertFalse(repo.is_empty)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -38,9 +38,9 @@ class SignatureTest(NoRepoTestCase):
|
||||
|
||||
def test_default(self):
|
||||
signature = Signature(
|
||||
'Foo', 'foo@example.com', 1322174594, 60)
|
||||
'Foo Ibáñez', 'foo@example.com', 1322174594, 60)
|
||||
encoding = signature._encoding
|
||||
self.assertEqual(encoding, 'ascii')
|
||||
self.assertEqual(encoding, 'utf-8')
|
||||
self.assertEqual(signature.name, signature.raw_name.decode(encoding))
|
||||
self.assertEqual(signature.name.encode(encoding), signature.raw_name)
|
||||
self.assertEqual(signature.email,
|
||||
@@ -50,7 +50,7 @@ class SignatureTest(NoRepoTestCase):
|
||||
|
||||
def test_ascii(self):
|
||||
self.assertRaises(UnicodeEncodeError,
|
||||
Signature, 'Foo Ibáñez', 'foo@example.com')
|
||||
Signature, 'Foo Ibáñez', 'foo@example.com', encoding='ascii')
|
||||
|
||||
def test_latin1(self):
|
||||
encoding = 'iso-8859-1'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -32,7 +32,7 @@ from __future__ import unicode_literals
|
||||
import operator
|
||||
import unittest
|
||||
|
||||
from pygit2 import TreeEntry
|
||||
from pygit2 import TreeEntry, GIT_FILEMODE_TREE
|
||||
from . import utils
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ class TreeTest(utils.BareRepoTestCase):
|
||||
def assertTreeEntryEqual(self, entry, sha, name, filemode):
|
||||
self.assertEqual(entry.hex, sha)
|
||||
self.assertEqual(entry.name, name)
|
||||
self.assertEqual(entry._name, name.encode('utf-8'))
|
||||
self.assertEqual(entry.filemode, filemode,
|
||||
'0%o != 0%o' % (entry.filemode, filemode))
|
||||
|
||||
@@ -89,6 +90,7 @@ class TreeTest(utils.BareRepoTestCase):
|
||||
tree = self.repo[TREE_SHA]
|
||||
subtree_entry = tree['c']
|
||||
self.assertTreeEntryEqual(subtree_entry, SUBTREE_SHA, 'c', 0o0040000)
|
||||
self.assertEqual(subtree_entry.type, 'tree')
|
||||
|
||||
subtree = self.repo[subtree_entry.id]
|
||||
self.assertEqual(1, len(subtree))
|
||||
@@ -100,21 +102,34 @@ class TreeTest(utils.BareRepoTestCase):
|
||||
repo = self.repo
|
||||
b0 = repo.create_blob('1')
|
||||
b1 = repo.create_blob('2')
|
||||
st = repo.TreeBuilder()
|
||||
st.insert('a', b0, 0o0100644)
|
||||
subtree = repo[st.write()]
|
||||
|
||||
t = repo.TreeBuilder()
|
||||
t.insert('x', b0, 0o0100644)
|
||||
t.insert('y', b1, 0o0100755)
|
||||
t.insert('z', subtree.id, GIT_FILEMODE_TREE)
|
||||
tree = repo[t.write()]
|
||||
|
||||
self.assertTrue('x' in tree)
|
||||
self.assertTrue('y' in tree)
|
||||
self.assertTrue('z' in tree)
|
||||
|
||||
x = tree['x']
|
||||
y = tree['y']
|
||||
z = tree['z']
|
||||
self.assertEqual(x.filemode, 0o0100644)
|
||||
self.assertEqual(y.filemode, 0o0100755)
|
||||
self.assertEqual(z.filemode, GIT_FILEMODE_TREE)
|
||||
|
||||
self.assertEqual(repo[x.id].id, b0)
|
||||
self.assertEqual(repo[y.id].id, b1)
|
||||
self.assertEqual(repo[z.id].id, subtree.id)
|
||||
|
||||
self.assertEqual(x.type, 'blob')
|
||||
self.assertEqual(y.type, 'blob')
|
||||
self.assertEqual(z.type, 'tree')
|
||||
|
||||
|
||||
def test_modify_tree(self):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2015 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@@ -160,6 +160,12 @@ class EmptyRepoTestCase(AutoRepoTestCase):
|
||||
|
||||
repo_spec = 'tar', 'emptyrepo'
|
||||
|
||||
|
||||
class SubmoduleRepoTestCase(AutoRepoTestCase):
|
||||
|
||||
repo_spec = 'tar', 'submodulerepo'
|
||||
|
||||
|
||||
class BinaryFileRepoTestCase(AutoRepoTestCase):
|
||||
|
||||
repo_spec = 'tar', 'binaryfilerepo'
|
||||
|
||||
Reference in New Issue
Block a user