Merge remote-tracking branch 'upstream/master' into features/diff_refactoring

Conflicts:
	src/tree.c
This commit is contained in:
Nico von Geyso
2013-05-18 15:48:27 +02:00
26 changed files with 694 additions and 379 deletions

View File

@@ -20,9 +20,9 @@ Pygit2 links:
Quick install guide
===================
1. Checkout libgi2 v0.18.0::
1. Checkout the libgit2 stable branch::
$ git clone git://github.com/libgit2/libgit2.git -b v0.18.0
$ git clone git://github.com/libgit2/libgit2.git -b master
2. Build and install libgit2
https://github.com/libgit2/libgit2/#building-libgit2---using-cmake

24
docs/general.rst Normal file
View File

@@ -0,0 +1,24 @@
**********************************************************************
General
**********************************************************************
.. contents:: Contents
:local:
Constants
=========
.. py:data:: LIBGIT2_VER_MAJOR
.. py:data:: LIBGIT2_VER_MINOR
.. py:data:: LIBGIT2_VER_REVISION
.. py:data:: LIBGIT2_VER_VERSION
Errors
======
.. autoexception:: pygit2.GitError
:members:
:show-inheritance:
:undoc-members:

View File

@@ -22,32 +22,27 @@ Pygit2 links:
Start:
.. toctree::
:maxdepth: 2
:maxdepth: 1
install
Usage guide:
.. toctree::
:maxdepth: 2
:maxdepth: 1
general
repository
oid
objects
references
revparse
log
working-copy
diff
merge
config
remotes
errors
More:
.. toctree::
:maxdepth: 1
utils
Indices and tables

View File

@@ -6,8 +6,10 @@ How to Install
.. contents::
First you need to install the latest version of libgit2. You can find
platform-specific instructions to build the library in the libgit2 website:
First you need to install the latest release of libgit2. If you clone
the repository, make sure to use the ``master`` branch. You can find
platform-specific instructions to build the library in the libgit2
website:
http://libgit2.github.com
@@ -55,7 +57,7 @@ instructions in the libgit2 ``README.md``):
.. code-block:: sh
$ git clone git://github.com/libgit2/libgit2.git
$ git clone -b master git://github.com/libgit2/libgit2.git
$ mkdir libgit2/build
$ cd libgit2/build
$ cmake ..
@@ -105,7 +107,7 @@ from a bash shell:
.. code-block:: sh
$ export LIBGIT2=C:/Dev/libgit2
$ git clone git://github.com/libgit2/libgit2.git
$ git clone -b master git://github.com/libgit2/libgit2.git
$ cd libgit2
$ mkdir build
$ cd build

View File

@@ -1,8 +1,5 @@
**********************************************************************
Errors
Merge
**********************************************************************
.. autoexception:: pygit2.GitError
:members:
:show-inheritance:
:undoc-members:
.. automethod:: pygit2.Repository.merge_base

View File

@@ -1,92 +1,80 @@
**********************************************************************
Git objects
Git Objects
**********************************************************************
There are four types of Git objects: blobs, trees, commits and tags. For each
one pygit2 has a type, and all four types inherit from the base ``Object``
type.
.. contents:: Contents
:local:
In the first place Git is a key-value storage system. The keys are called
OIDs, for Object id, and the values stored are called Objects.
Oids
Object lookup
=================
The oid is the `SHA-1 <http://en.wikipedia.org/wiki/SHA-1>`_ hash of an
object. It is 20 bytes long:
In the previous chapter we learnt about Object IDs. With an oid we can ask the
repository to get the associated object. To do that the ``Repository`` class
implementes a subset of the mapping interface.
- When we represent an oid as a 20 bytes Python string, we say it is a raw
oid.
.. method:: Repository.get(oid, default=None)
- When we represent an oid as a 40 chars Python string, we sayt it is a hex
oid.
Return the Git object for the given *oid*, returns the *default* value if
there's no object in the repository with that oid. The oid can be an Oid
object, or an hexadecimal string.
However, most of the time we will use the Oid type. We can explicetly create
an Oid object from its raw or hexadecimal form::
Example::
>>> hex = "cff3ceaefc955f0dbe1957017db181bc49913781"
>>> oid1 = Oid(hex=hex)
>>> from pygit2 import Repository
>>> repo = Repository('path/to/pygit2')
>>> obj = repo.get("101715bf37440d32291bde4f58c3142bcf7d8adb")
>>> obj
<_pygit2.Commit object at 0x7ff27a6b60f0>
>>> from binascii import unhexlify
>>> raw = unhexlify(hex)
>>> oid2 = Oid(raw=raw)
.. method:: Repository[oid]
>>> print oid1 == oid2
Return the Git object for the given oid, raise ``KeyError`` if there's no
object in the repository with that oid. The oid can be an Oid object, or
an hexadecimal string.
.. method:: oid in Repository
Returns True if there is an object in the Repository with that oid, False
if there is not. The oid can be an Oid object, or an hexadecimal string.
The Object base type
====================
The Object type is a base type, it is not possible to make instances of it, in
any way.
It is the base type of the ``Blob``, ``Tree``, ``Commit`` and ``Tag`` types, so
it is possible to check whether a Python value is an Object or not::
>>> from pygit2 import Object
>>> commit = repository.revparse_single('HEAD')
>>> print isinstance(commit, Object)
True
And in the opposite direction, we can get the raw or hexadecimal form from
an Oid object:
All Objects are immutable, they cannot be modified once they are created::
.. autoattribute:: pygit2.Oid.raw
.. autoattribute:: pygit2.Oid.hex
>>> commit.message = u"foobar"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: attribute 'message' of '_pygit2.Commit' objects is not writable
The Oid type supports:
Derived types (blobs, trees, etc.) don't have a constructor, this means they
cannot be created with the common idiom::
- rich comparisons, not just for equality, also: lesser-than, lesser-or-equal,
etc.
>>> from pygit2 import Blob
>>> blob = Blob("data")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create '_pygit2.Blob' instances
- hashing, so Oid objects can be used as keys in a dictionary
Python 2 and Python 3
---------------------
There is a difference on how the library handles hex oids, depending on
whether we are using Python 2 or 3.
- In Python 2, we can represent an hexadecimal oid using a bytes string
(``str``) or a text string (``unicode``)
- In Python 3, hexadecimal oids can only be represented using unicode
strings.
Objects
=================
There are four types (commits, trees, blobs and tags), for each type pygit2
has a Python class::
>>> # Show commits and trees
>>> commit
<pygit2.Commit object at 0x7f9d2f3000b0>
>>> commit.tree
<pygit2.Tree object at 0x7f9d2f3000f0>
These four classes (``Commit``, ``Tree``, ``Blob`` and ``Tag``) inherit from
the ``Object`` base class, which provides shared behaviour. A Git object is
identified by a unique *object id*, which is a binary byte string; this is
often represented as an hexadecimal text string::
>>> commit.oid
b'x\xde\xb5W\x8d\x01<\xdb\xdf\x08o\xa1\xd1\xa3\xe7\xd9\x82\xe8\x88\x8f'
>>> commit.hex
'78deb5578d013cdbdf086fa1d1a3e7d982e8888f'
The API of pygit2 accepts both the raw object id and its hexadecimal
representation, the difference is done based on its type (a byte or a text
string).
Objects can not be modified once they have been created.
New objects are created using an specific API we will see later.
This is the common interface for all Git objects:
@@ -96,6 +84,126 @@ This is the common interface for all Git objects:
.. automethod:: pygit2.Object.read_raw
Blobs
=================
A blob is just a raw byte string. They are the Git equivalent to files in
a filesytem.
This is their API:
.. autoattribute:: pygit2.Blob.data
Example, print the contents of the ``.gitignore`` file::
>>> blob = repo["d8022420bf6db02e906175f64f66676df539f2fd"]
>>> print blob.data
MANIFEST
build
dist
.. autoattribute:: pygit2.Blob.size
Example::
>>> print blob.size
130
Creating blobs
--------------
There are a number of methods in the repository to create new blobs, and add
them to the Git object database:
.. automethod:: pygit2.Repository.create_blob
Example:
>>> oid = repo.create_blob('foo bar') # Creates blob from bytes string
>>> blob = repo[oid]
>>> blob.data
'foo bar'
.. automethod:: pygit2.Repository.create_blob_fromworkdir
.. automethod:: pygit2.Repository.create_blob_fromdisk
There are also some functions to calculate the oid for a byte string without
creating the blob object:
.. autofunction:: pygit2.hash
.. autofunction:: pygit2.hashfile
Trees
=================
A tree is a sorted collection of tree entries. It is similar to a folder or
directory in a file system. Each entry points to another tree or a blob. A
tree can be iterated, and partially implements the sequence and mapping
interfaces.
.. method:: Tree[name]
Return the TreeEntry object for the given *name*. Raise ``KeyError`` if
there is not a tree entry with that name.
.. method:: name in Tree
Return True if there is a tree entry with the given name, False otherwise.
.. method:: len(Tree)
Return the number of entries in the tree.
.. method:: iter(Tree)
Return an iterator over the entries of the tree.
.. automethod:: pygit2.Tree.diff
Tree entries
------------
.. autoattribute:: pygit2.TreeEntry.name
.. autoattribute:: pygit2.TreeEntry.oid
.. autoattribute:: pygit2.TreeEntry.hex
.. autoattribute:: pygit2.TreeEntry.filemode
Example::
>>> tree = commit.tree
>>> len(tree) # Number of entries
6
>>> for entry in tree: # Iteration
... print(entry.hex, entry.name)
...
7151ca7cd3e59f3eab19c485cfbf3cb30928d7fa .gitignore
c36f4cf1e38ec1bb9d9ad146ed572b89ecfc9f18 COPYING
32b30b90b062f66957d6790c3c155c289c34424e README.md
c87dae4094b3a6d10e08bc6c5ef1f55a7e448659 pygit2.c
85a67270a49ef16cdd3d328f06a3e4b459f09b27 setup.py
3d8985bbec338eb4d47c5b01b863ee89d044bd53 test
>>> entry = tree['pygit2.c'] # Get an entry by name
>>> entry
<pygit2.TreeEntry object at 0xcc10f0>
>>> blob = repo[entry.oid] # Get the object the entry points to
>>> blob
<pygit2.Blob object at 0xcc12d0>
Creating trees
--------------------
.. automethod:: pygit2.Repository.TreeBuilder
.. automethod:: pygit2.TreeBuilder.insert
.. automethod:: pygit2.TreeBuilder.remove
.. automethod:: pygit2.TreeBuilder.clear
.. automethod:: pygit2.TreeBuilder.write
Commits
=================
@@ -147,82 +255,6 @@ repository with the following parameters::
'#\xe4<u\xfe\xd6\x17\xa0\xe6\xa2\x8b\xb6\xdc35$\xcf-\x8b~'
Trees
=================
A tree is a sorted collection of tree entries. It is similar to a folder or
directory in a file system. Each entry points to another tree or a blob. A
tree can be iterated, and partially implements the sequence and mapping
interfaces::
>>> # Number of entries
>>> tree = commit.tree
>>> len(tree)
6
>>> # Iteration
>>> for entry in tree:
... print(entry.hex, entry.name)
...
7151ca7cd3e59f3eab19c485cfbf3cb30928d7fa .gitignore
c36f4cf1e38ec1bb9d9ad146ed572b89ecfc9f18 COPYING
32b30b90b062f66957d6790c3c155c289c34424e README.md
c87dae4094b3a6d10e08bc6c5ef1f55a7e448659 pygit2.c
85a67270a49ef16cdd3d328f06a3e4b459f09b27 setup.py
3d8985bbec338eb4d47c5b01b863ee89d044bd53 test
>>> # Get an entry by name
>>> entry = tree['pygit2.c']
>>> entry
<pygit2.TreeEntry object at 0xcc10f0>
>>> # Get the object the entry points to
>>> blob = repo[entry.oid]
>>> blob
<pygit2.Blob object at 0xcc12d0>
.. automethod:: pygit2.Tree.diff
.. autoattribute:: pygit2.TreeEntry.name
.. autoattribute:: pygit2.TreeEntry.oid
.. autoattribute:: pygit2.TreeEntry.hex
.. autoattribute:: pygit2.TreeEntry.filemode
Creating trees
--------------------
.. automethod:: pygit2.Repository.TreeBuilder
.. automethod:: pygit2.TreeBuilder.insert
.. automethod:: pygit2.TreeBuilder.remove
.. automethod:: pygit2.TreeBuilder.clear
.. automethod:: pygit2.TreeBuilder.write
Blobs
=================
A blob is equivalent to a file in a file system.::
>>> # create a blob out of memory
>>> oid = repo.create_blob('foo bar')
>>> blob = repo[oid]
>>> blob.data
'foo bar'
>>> oid
'\x96\xc9\x06um{\x91\xc4S"a|\x92\x95\xe4\xa8\rR\xd1\xc5'
.. autoattribute:: pygit2.Blob.data
.. autoattribute:: pygit2.Blob.size
Creating blobs
--------------------
.. automethod:: pygit2.Repository.create_blob
.. automethod:: pygit2.Repository.create_blob_fromworkdir
.. automethod:: pygit2.Repository.create_blob_fromdisk
Tags
=================

84
docs/oid.rst Normal file
View File

@@ -0,0 +1,84 @@
**********************************************************************
Object IDs
**********************************************************************
In the first place Git is a key-value storage system. The keys are called
OIDs, for Object ID, and the values stored are called Objects.
.. contents:: Contents
:local:
The three forms of an object id
===============================
The oid is the `SHA-1 <http://en.wikipedia.org/wiki/SHA-1>`_ hash of an
object. It is 20 bytes long.
These are the three forms of an oid in pygit2:
Raw oid
A raw oid is represented as a Python byte string of 20 bytes length.
This form can only be used to create an Oid object.
Hex oid
A hex oid is represented as a Python string of 40 hexadecimal chars. This
form can be used to create Oid objects, just like raw oids. Also, the pygit2
API directly accepts hex oids everywhere.
.. note::
In Python 3 hexadecimal oids are represented using the ``str`` type.
In Python 2 both ``str`` and ``unicode`` are accepted.
Oid object
An ``Oid`` object can be built from the raw or hexadecimal representations
(see below). The pygit2 API always returns, and accepts, ``Oid`` objects.
This is the preferred way to represent an Oid, with the hexadecimal form
being used for interaction with the user.
The Oid type
============
.. c:type:: pygit2.Oid(raw=None, hex=None)
The constructor expects either a raw or a hex oid, but not both.
An Oid object is created from the hexadecimal form this way::
>>> from pygit2 import Oid
>>> hex = "cff3ceaefc955f0dbe1957017db181bc49913781"
>>> oid1 = Oid(hex=hex)
An Oid object is created from the raw form this way::
>>> from binascii import unhexlify
>>> from pygit2 import Oid
>>> raw = unhexlify("cff3ceaefc955f0dbe1957017db181bc49913781")
>>> oid2 = Oid(raw=raw)
An the other way around, from an Oid object we can get the hexadecimal and raw
forms.
.. autoattribute:: pygit2.Oid.hex
.. autoattribute:: pygit2.Oid.raw
The Oid type supports:
- rich comparisons, not just for equality, also: lesser-than, lesser-or-equal,
etc.
- hashing, so Oid objects can be used as keys in a dictionary.
Constants
=========
.. py:data:: GIT_OID_RAWSZ
.. py:data:: GIT_OID_HEXSZ
.. py:data:: GIT_OID_HEX_ZERO
.. py:data:: GIT_OID_MINPREFIXLEN

View File

@@ -5,35 +5,55 @@ The repository
Everything starts either by creating a new repository, or by opening an
existing one.
.. contents:: Contents
:local:
Creating a repository
Functions
===================================
.. autofunction:: pygit2.init_repository
This is how to create non-bare repository::
Example::
>>> from pygit2 import init_repository
>>> repo = init_repository('test')
>>> from pygit2 import init_repository
>>> repo = init_repository('test') # Creates a non-bare repository
>>> repo = init_repository('test', bare=True) # Creates a bare repository
And this is how to create a bare repository::
.. autofunction:: pygit2.clone_repository
>>> from pygit2 import init_repository
>>> repo = init_repository('test', bare=True)
Example::
But one can also do::
>>> from pygit2 import clone_repository
>>> repo_url = 'git://github.com/libgit2/pygit2.git'
>>> repo_path = '/path/to/create/repository'
>>> repo = clone_repository(repo_url, repo_path) # Clones a non-bare repository
>>> repo = clone_repository(repo_url, repo_path, bare=True) # Clones a bare repository
.. autofunction:: pygit2.discover_repository
>>> from pygit2 import init_repository
>>> repo = init_repository('test', True)
The Repository class
===================================
To open an existing repository::
.. py:class:: pygit2.Repository(path)
>>> from pygit2 import Repository
>>> repo = Repository('pygit2/.git')
The Repository constructor only takes one argument, the path of the
repository to open.
Example::
>>> from pygit2 import Repository
>>> repo = Repository('pygit2/.git')
The API of the Repository class is quite large. Since this documentation is
orgaized by features, the related bits are explained in the related chapters,
for instance the :py:meth:`pygit2.Repository.checkout` method are explained in
the Checkout section.
Below there are some general attributes and methods:
.. autoattribute:: pygit2.Repository.path
.. autoattribute:: pygit2.Repository.workdir
@@ -41,4 +61,3 @@ To open an existing repository::
.. autoattribute:: pygit2.Repository.is_empty
.. automethod:: pygit2.Repository.read
.. automethod:: pygit2.Repository.write
.. automethod:: pygit2.Repository.merge_base

View File

@@ -1,14 +0,0 @@
**********************************************************************
Utilities
**********************************************************************
.. autofunction:: pygit2.discover_repository
.. autofunction:: pygit2.hash
.. autofunction:: pygit2.hashfile
.. automodule:: pygit2.utils
:members:
:show-inheritance:
:undoc-members:

View File

@@ -40,15 +40,50 @@ import pygit2.utils
def init_repository(path, bare=False):
"""
Creates a new Git repository in the given path.
Creates a new Git repository in the given *path*.
Arguments:
path
Path where to create the repository.
bare
Whether the repository will be bare or not.
If *bare* is True the repository will be bare, i.e. it will not have a
working copy.
"""
_pygit2.init_repository(path, bare)
return Repository(path)
def clone_repository(
url, path, bare=False, remote_name="origin",
push_url=None, fetch_spec=None,
push_spec=None, checkout_branch=None):
"""
Clones a new Git repository from *url* in the given *path*.
**bare** indicates whether a bare git repository should be created.
**remote_name** is the name given to the "origin" remote.
The default is "origin".
**push_url** is a URL to be used for pushing.
None means use the *url* parameter.
**fetch_spec** defines the the default fetch spec.
None results in the same behavior as *GIT_REMOTE_DEFAULT_FETCH*.
**push_spec** is the fetch specification to be used for pushing.
None means use the same spec as for *fetch_spec*.
**checkout_branch** gives the name of the branch to checkout.
None means use the remote's *HEAD*.
Returns a Repository class pointing to the newly cloned repository.
If you wish to use the repo, you need to do a checkout for one of
the available branches, like this:
>>> repo = repo.clone_repository("url", "path")
>>> repo.checkout(branch) # i.e.: refs/heads/master
"""
_pygit2.clone_repository(
url, path, bare, remote_name, push_url,
fetch_spec, push_spec, checkout_branch)
return Repository(path)

View File

@@ -42,7 +42,8 @@ Blob_size__get__(Blob *self)
PyDoc_STRVAR(Blob_data__doc__,
"Raw data. This is the same as Blob.read_raw()");
"The contents of the blob, a bytes string. This is the same as\n"
"Blob.read_raw()");
PyGetSetDef Blob_getseters[] = {
GETTER(Blob, size),

View File

@@ -31,6 +31,7 @@
#include "utils.h"
#include "signature.h"
#include "commit.h"
#include "object.h"
extern PyTypeObject TreeType;
@@ -149,32 +150,43 @@ Commit_tree__get__(Commit *commit)
PyDoc_STRVAR(Commit_parents__doc__, "The list of parent commits.");
PyObject *
Commit_parents__get__(Commit *commit)
Commit_parents__get__(Commit *self)
{
git_repository *repo;
unsigned int i, parent_count;
const git_oid *parent_oid;
PyObject *obj;
git_commit *parent;
int err;
PyObject *py_parent;
PyObject *list;
parent_count = git_commit_parentcount(commit->commit);
parent_count = git_commit_parentcount(self->commit);
list = PyList_New(parent_count);
if (!list)
return NULL;
repo = git_object_owner((git_object*)self->commit);
for (i=0; i < parent_count; i++) {
parent_oid = git_commit_parent_id(commit->commit, i);
parent_oid = git_commit_parent_id(self->commit, i);
if (parent_oid == NULL) {
Py_DECREF(list);
Error_set(GIT_ENOTFOUND);
return NULL;
}
obj = lookup_object(commit->repo, parent_oid, GIT_OBJ_COMMIT);
if (obj == NULL) {
err = git_commit_lookup(&parent, repo, parent_oid);
if (err < 0) {
Py_DECREF(list);
return Error_set_oid(err, parent_oid, GIT_OID_HEXSZ);
}
py_parent = wrap_object((git_object*)parent, self->repo);
if (py_parent == NULL) {
Py_DECREF(list);
return NULL;
}
PyList_SET_ITEM(list, i, obj);
PyList_SET_ITEM(list, i, py_parent);
}
return list;

View File

@@ -358,10 +358,10 @@ Index_read_tree(Index *self, PyObject *value)
git_oid oid;
git_tree *tree;
int err;
Py_ssize_t len;
size_t len;
len = py_str_to_git_oid(value, &oid);
if (len < 0)
len = py_oid_to_git_oid(value, &oid);
if (len == 0)
return NULL;
err = git_tree_lookup_prefix(&tree, self->repo->repo, &oid, len);
@@ -378,7 +378,7 @@ Index_read_tree(Index *self, PyObject *value)
PyDoc_STRVAR(Index_write_tree__doc__,
"write_tree() -> str\n"
"write_tree() -> Oid\n"
"\n"
"Create a tree object from the index file, return its oid.");

View File

@@ -50,7 +50,7 @@ Object_dealloc(Object* self)
PyDoc_STRVAR(Object_oid__doc__,
"The object id, a byte string 20 bytes long.");
"The object id, an instance of the Oid type.");
PyObject *
Object_oid__get__(Object *self)
@@ -65,7 +65,8 @@ Object_oid__get__(Object *self)
PyDoc_STRVAR(Object_hex__doc__,
"Hexadecimal representation of the object id, a text string 40 chars long.");
"Hexadecimal representation of the object id. This is a shortcut for\n"
"Object.oid.hex");
PyObject *
Object_hex__get__(Object *self)
@@ -80,8 +81,8 @@ Object_hex__get__(Object *self)
PyDoc_STRVAR(Object_type__doc__,
"One of the GIT_OBJ_COMMIT, GIT_OBJ_TREE, GIT_OBJ_BLOB or GIT_OBJ_TAG\n"
"constants.");
"One of the GIT_OBJ_COMMIT, GIT_OBJ_TREE, GIT_OBJ_BLOB or GIT_OBJ_TAG\n"
"constants.");
PyObject *
Object_type__get__(Object *self)
@@ -91,19 +92,22 @@ Object_type__get__(Object *self)
PyDoc_STRVAR(Object_read_raw__doc__,
"read_raw()\n"
"\n"
"Returns the byte string with the raw contents of the of the object.");
PyObject *
Object_read_raw(Object *self)
{
git_repository *repo;
const git_oid *oid;
git_odb_object *obj;
PyObject *aux;
repo = git_object_owner(self->obj);
oid = git_object_id(self->obj);
assert(oid);
obj = Repository_read_raw(self->repo->repo, oid, GIT_OID_HEXSZ);
obj = Repository_read_raw(repo, oid, GIT_OID_HEXSZ);
if (obj == NULL)
return NULL;

View File

@@ -45,8 +45,8 @@ git_oid_to_python(const git_oid *oid)
return (PyObject*)py_oid;
}
Py_ssize_t
_oid_from_hex(PyObject *py_oid, git_oid *oid)
size_t
py_hex_to_git_oid (PyObject *py_oid, git_oid *oid)
{
PyObject *py_hex;
int err;
@@ -58,15 +58,15 @@ _oid_from_hex(PyObject *py_oid, git_oid *oid)
if (PyBytes_Check(py_oid)) {
err = PyBytes_AsStringAndSize(py_oid, &hex, &len);
if (err)
return -1;
return 0;
err = git_oid_fromstrn(oid, hex, len);
if (err < 0) {
PyErr_SetObject(Error_type(err), py_oid);
return -1;
return 0;
}
return len;
return (size_t)len;
}
#endif
@@ -74,31 +74,31 @@ _oid_from_hex(PyObject *py_oid, git_oid *oid)
if (PyUnicode_Check(py_oid)) {
py_hex = PyUnicode_AsASCIIString(py_oid);
if (py_hex == NULL)
return -1;
return 0;
err = PyBytes_AsStringAndSize(py_hex, &hex, &len);
if (err) {
Py_DECREF(py_hex);
return -1;
return 0;
}
err = git_oid_fromstrn(oid, hex, len);
Py_DECREF(py_hex);
if (err < 0) {
PyErr_SetObject(Error_type(err), py_oid);
return -1;
return 0;
}
return len;
return (size_t)len;
}
/* Type error */
PyErr_SetObject(PyExc_TypeError, py_oid);
return -1;
return 0;
}
Py_ssize_t
py_str_to_git_oid(PyObject *py_oid, git_oid *oid)
size_t
py_oid_to_git_oid(PyObject *py_oid, git_oid *oid)
{
/* Oid */
if (PyObject_TypeCheck(py_oid, (PyTypeObject*)&OidType)) {
@@ -107,41 +107,43 @@ py_str_to_git_oid(PyObject *py_oid, git_oid *oid)
}
/* Hex */
return _oid_from_hex(py_oid, oid);
return py_hex_to_git_oid(py_oid, oid);
}
Py_ssize_t
py_str_to_git_oid_expand(git_repository *repo, PyObject *py_str, git_oid *oid)
int
py_oid_to_git_oid_expand(git_repository *repo, PyObject *py_str, git_oid *oid)
{
int err;
Py_ssize_t len;
git_odb *odb;
git_odb_object *obj;
size_t len;
git_odb *odb = NULL;
git_odb_object *obj = NULL;
len = py_str_to_git_oid(py_str, oid);
if (len == GIT_OID_HEXSZ || len < 0)
return len;
err = git_repository_odb(&odb, repo);
if (err < 0) {
Error_set(err);
len = py_oid_to_git_oid(py_str, oid);
if (len == 0)
return -1;
}
if (len == GIT_OID_HEXSZ)
return 0;
/* Short oid */
err = git_repository_odb(&odb, repo);
if (err < 0)
goto error;
err = git_odb_read_prefix(&obj, odb, oid, len);
if (err < 0) {
git_odb_free(odb);
Error_set(err);
return err;
}
if (err < 0)
goto error;
git_oid_cpy(oid, git_odb_object_id(obj));
git_odb_object_free(obj);
git_odb_free(odb);
return 0;
error:
git_odb_object_free(obj);
git_odb_free(odb);
Error_set(err);
return -1;
}
PyObject *
@@ -197,8 +199,8 @@ Oid_init(Oid *self, PyObject *args, PyObject *kw)
}
/* Case 2: hex */
len = _oid_from_hex(hex, &self->oid);
if (len < 0)
len = py_hex_to_git_oid(hex, &self->oid);
if (len == 0)
return -1;
return 0;
@@ -246,6 +248,9 @@ Oid_richcompare(PyObject *o1, PyObject *o2, int op)
case Py_GE:
res = (cmp >= 0) ? Py_True: Py_False;
break;
default:
PyErr_Format(PyExc_RuntimeError, "Unexpected '%d' op", op);
return NULL;
}
Py_INCREF(res);
@@ -253,7 +258,7 @@ Oid_richcompare(PyObject *o1, PyObject *o2, int op)
}
PyDoc_STRVAR(Oid_raw__doc__, "Raw oid.");
PyDoc_STRVAR(Oid_raw__doc__, "Raw oid, a 20 bytes string.");
PyObject *
Oid_raw__get__(Oid *self)
@@ -262,7 +267,7 @@ Oid_raw__get__(Oid *self)
}
PyDoc_STRVAR(Oid_hex__doc__, "Hex oid.");
PyDoc_STRVAR(Oid_hex__doc__, "Hex oid, a 40 chars long string (type str).");
PyObject *
Oid_hex__get__(Oid *self)

View File

@@ -32,9 +32,9 @@
#include <Python.h>
#include <git2.h>
Py_ssize_t py_str_to_git_oid(PyObject *py_str, git_oid *oid);
Py_ssize_t py_str_to_git_oid_expand(git_repository *repo, PyObject *py_str,
git_oid *oid);
size_t py_oid_to_git_oid(PyObject *py_str, git_oid *oid);
int py_oid_to_git_oid_expand(git_repository *repo, PyObject *py_str,
git_oid *oid);
PyObject* git_oid_to_python(const git_oid *oid);
PyObject* git_oid_to_py_str(const git_oid *oid);

View File

@@ -97,6 +97,69 @@ init_repository(PyObject *self, PyObject *args) {
Py_RETURN_NONE;
};
PyDoc_STRVAR(clone_repository__doc__,
"clone_repository(url, path, bare, remote_name, push_url,"
"fetch_spec, push_spec, checkout_branch)\n"
"\n"
"Clones a Git repository in the given url to the given path "
"with the specified options.\n"
"\n"
"Arguments:\n"
"\n"
"url\n"
" Git repository remote url.\n"
"path\n"
" Path where to create the repository.\n"
"bare\n"
" If 'bare' is not 0, then a bare git repository will be created.\n"
"remote_name\n"
" The name given to the 'origin' remote. The default is 'origin'.\n"
"push_url\n"
" URL to be used for pushing.\n"
"fetch_spec\n"
" The fetch specification to be used for fetching. None results in "
"the same behavior as GIT_REMOTE_DEFAULT_FETCH.\n"
"push_spec\n"
" The fetch specification to be used for pushing. None means use the "
"same spec as for 'fetch_spec'\n"
"checkout_branch\n"
" The name of the branch to checkout. None means use the remote's "
"HEAD.\n");
PyObject *
clone_repository(PyObject *self, PyObject *args) {
git_repository *repo;
const char *url;
const char *path;
unsigned int bare;
const char *remote_name, *push_url, *fetch_spec;
const char *push_spec, *checkout_branch;
int err;
if (!PyArg_ParseTuple(args, "zzIzzzzz",
&url, &path, &bare, &remote_name, &push_url,
&fetch_spec, &push_spec, &checkout_branch))
return NULL;
git_clone_options opts = {
.version=1,
.bare=bare,
.remote_name=remote_name,
.pushurl=push_url,
.fetch_spec=fetch_spec,
.push_spec=push_spec,
.checkout_branch=checkout_branch
};
err = git_clone(&repo, url, path, &opts);
if (err < 0)
return Error_set_str(err, path);
git_repository_free(repo);
Py_RETURN_NONE;
};
PyDoc_STRVAR(discover_repository__doc__,
"discover_repository(path[, across_fs[, ceiling_dirs]]) -> str\n"
@@ -124,10 +187,10 @@ discover_repository(PyObject *self, PyObject *args)
};
PyDoc_STRVAR(hashfile__doc__,
"hashfile(path) -> bytes\n"
"\n"
"Returns the oid of a new blob from a file path without actually writing \n"
"to the odb.");
"hashfile(path) -> Oid\n"
"\n"
"Returns the oid of a new blob from a file path without actually writing\n"
"to the odb.");
PyObject *
hashfile(PyObject *self, PyObject *args)
{
@@ -146,10 +209,10 @@ hashfile(PyObject *self, PyObject *args)
}
PyDoc_STRVAR(hash__doc__,
"hash(data) -> bytes\n"
"\n"
"Returns the oid of a new blob from a string without actually writing to \n"
"the odb.");
"hash(data) -> Oid\n"
"\n"
"Returns the oid of a new blob from a string without actually writing to\n"
"the odb.");
PyObject *
hash(PyObject *self, PyObject *args)
{
@@ -172,6 +235,8 @@ hash(PyObject *self, PyObject *args)
PyMethodDef module_methods[] = {
{"init_repository", init_repository, METH_VARARGS, init_repository__doc__},
{"clone_repository", clone_repository, METH_VARARGS,
clone_repository__doc__},
{"discover_repository", discover_repository, METH_VARARGS,
discover_repository__doc__},
{"hashfile", hashfile, METH_VARARGS, hashfile__doc__},

View File

@@ -107,6 +107,7 @@ PyTypeObject RefLogIterType = {
void
Reference_dealloc(Reference *self)
{
Py_CLEAR(self->repo);
git_reference_free(self->reference);
PyObject_Del(self);
}
@@ -191,7 +192,7 @@ Reference_resolve(Reference *self, PyObject *args)
if (err < 0)
return Error_set(err);
return wrap_reference(c_reference);
return wrap_reference(c_reference, self->repo);
}
@@ -226,7 +227,6 @@ Reference_target__set__(Reference *self, PyObject *py_target)
git_oid oid;
char *c_name;
int err;
Py_ssize_t len;
git_reference *new_ref;
git_repository *repo;
@@ -235,11 +235,9 @@ Reference_target__set__(Reference *self, PyObject *py_target)
/* Case 1: Direct */
if (GIT_REF_OID == git_reference_type(self->reference)) {
repo = git_reference_owner(self->reference);
len = py_str_to_git_oid_expand(repo, py_target, &oid);
if (len < 0) {
err = (int)len;
goto error;
}
err = py_oid_to_git_oid_expand(repo, py_target, &oid);
if (err < 0)
return err;
err = git_reference_set_target(&new_ref, self->reference, &oid);
if (err < 0)
@@ -464,13 +462,18 @@ PyTypeObject ReferenceType = {
PyObject *
wrap_reference(git_reference * c_reference)
wrap_reference(git_reference * c_reference, Repository *repo)
{
Reference *py_reference=NULL;
py_reference = PyObject_New(Reference, &ReferenceType);
if (py_reference)
if (py_reference) {
py_reference->reference = c_reference;
if (repo) {
py_reference->repo = repo;
Py_INCREF(repo);
}
}
return (PyObject *)py_reference;
}

View File

@@ -41,6 +41,6 @@ PyObject* Reference_get_name(Reference *self);
PyObject* Reference_get_oid(Reference *self);
PyObject* Reference_get_hex(Reference *self);
PyObject* Reference_get_type(Reference *self);
PyObject* wrap_reference(git_reference * c_reference);
PyObject* wrap_reference(git_reference *c_reference, Repository *repo);
#endif

View File

@@ -65,20 +65,6 @@ int_to_loose_object_type(int type_id)
}
}
PyObject *
lookup_object(Repository *repo, const git_oid *oid, git_otype type)
{
int err;
git_object *obj;
err = git_object_lookup_prefix(&obj, repo->repo, oid, GIT_OID_HEXSZ,
type);
if (err < 0)
return Error_set_oid(err, oid, GIT_OID_HEXSZ);
return wrap_object(obj, repo);
}
int
Repository_init(Repository *self, PyObject *args, PyObject *kwds)
{
@@ -182,7 +168,7 @@ Repository_head__get__(Repository *self)
return NULL;
}
return wrap_reference(head);
return wrap_reference(head, self);
}
int
@@ -268,12 +254,12 @@ PyObject *
Repository_git_object_lookup_prefix(Repository *self, PyObject *key)
{
int err;
Py_ssize_t len;
size_t len;
git_oid oid;
git_object *obj;
len = py_str_to_git_oid(key, &oid);
if (len < 0)
len = py_oid_to_git_oid(key, &oid);
if (len == 0)
return NULL;
err = git_object_lookup_prefix(&obj, self->repo, &oid, len, GIT_OBJ_ANY);
@@ -353,11 +339,11 @@ Repository_read(Repository *self, PyObject *py_hex)
{
git_oid oid;
git_odb_object *obj;
Py_ssize_t len;
size_t len;
PyObject* tuple;
len = py_str_to_git_oid(py_hex, &oid);
if (len < 0)
len = py_oid_to_git_oid(py_hex, &oid);
if (len == 0)
return NULL;
obj = Repository_read_raw(self->repo, &oid, len);
@@ -380,11 +366,11 @@ Repository_read(Repository *self, PyObject *py_hex)
PyDoc_STRVAR(Repository_write__doc__,
"write(type, data) -> oid\n"
"\n"
"Write raw object data into the repository. First arg is the object type,\n"
"the second one a buffer with data. Return the object id (sha) of of the\n"
"created object.");
"write(type, data) -> Oid\n"
"\n"
"Write raw object data into the repository. First arg is the object\n"
"type, the second one a buffer with data. Return the Oid of the created\n"
"object.");
PyObject *
Repository_write(Repository *self, PyObject *args)
@@ -519,7 +505,7 @@ Repository_config__get__(Repository *self)
}
PyDoc_STRVAR(Repository_merge_base__doc__,
"merge_base(oid, oid) -> commit\n"
"merge_base(oid, oid) -> Oid\n"
"\n"
"Find as good common ancestors as possible for a merge.");
@@ -536,11 +522,11 @@ Repository_merge_base(Repository *self, PyObject *args)
if (!PyArg_ParseTuple(args, "OO", &value1, &value2))
return NULL;
err = py_str_to_git_oid_expand(self->repo, value1, &oid1);
err = py_oid_to_git_oid_expand(self->repo, value1, &oid1);
if (err < 0)
return NULL;
err = py_str_to_git_oid_expand(self->repo, value2, &oid2);
err = py_oid_to_git_oid_expand(self->repo, value2, &oid2);
if (err < 0)
return NULL;
@@ -562,7 +548,6 @@ Repository_walk(Repository *self, PyObject *args)
PyObject *value;
unsigned int sort;
int err;
Py_ssize_t len;
git_oid oid;
git_revwalk *walk;
Walker *py_walker;
@@ -579,10 +564,10 @@ Repository_walk(Repository *self, PyObject *args)
/* Push */
if (value != Py_None) {
len = py_str_to_git_oid_expand(self->repo, value, &oid);
if (len < 0) {
err = py_oid_to_git_oid_expand(self->repo, value, &oid);
if (err < 0) {
git_revwalk_free(walk);
return Error_set((int)len);
return NULL;
}
err = git_revwalk_push(walk, &oid);
@@ -606,9 +591,10 @@ Repository_walk(Repository *self, PyObject *args)
PyDoc_STRVAR(Repository_create_blob__doc__,
"create_blob(data) -> bytes\n"
"\n"
"Create a new blob from memory.");
"create_blob(data) -> Oid\n"
"\n"
"Create a new blob from a bytes string. The blob is added to the Git\n"
"object database. Returns the oid of the blob.");
PyObject *
Repository_create_blob(Repository *self, PyObject *args)
@@ -630,9 +616,11 @@ Repository_create_blob(Repository *self, PyObject *args)
PyDoc_STRVAR(Repository_create_blob_fromworkdir__doc__,
"create_blob_fromworkdir(path) -> bytes\n"
"\n"
"Create a new blob from a file within the working directory (raise an error otherwise).");
"create_blob_fromworkdir(path) -> Oid\n"
"\n"
"Create a new blob from a file within the working directory. The given\n"
"path must be relative to the working directory, if it is not an error\n"
"is raised.");
PyObject *
Repository_create_blob_fromworkdir(Repository *self, PyObject *args)
@@ -653,9 +641,9 @@ Repository_create_blob_fromworkdir(Repository *self, PyObject *args)
PyDoc_STRVAR(Repository_create_blob_fromdisk__doc__,
"create_blob_fromdisk(path) -> bytes\n"
"\n"
"Create a new blob from a file anywhere (no working directory check).");
"create_blob_fromdisk(path) -> Oid\n"
"\n"
"Create a new blob from a file anywhere (no working directory check).");
PyObject *
Repository_create_blob_fromdisk(Repository *self, PyObject *args)
@@ -676,9 +664,9 @@ Repository_create_blob_fromdisk(Repository *self, PyObject *args)
PyDoc_STRVAR(Repository_create_commit__doc__,
"create_commit(reference, author, committer, message, tree, parents[, encoding]) -> bytes\n"
"create_commit(reference, author, committer, message, tree, parents[, encoding]) -> Oid\n"
"\n"
"Create a new commit object, return its SHA.");
"Create a new commit object, return its oid.");
PyObject *
Repository_create_commit(Repository *self, PyObject *args)
@@ -694,7 +682,7 @@ Repository_create_commit(Repository *self, PyObject *args)
int parent_count;
git_commit **parents = NULL;
int err = 0, i = 0;
Py_ssize_t len;
size_t len;
if (!PyArg_ParseTuple(args, "zO!O!OOO!|s",
&update_ref,
@@ -706,8 +694,8 @@ Repository_create_commit(Repository *self, PyObject *args)
&encoding))
return NULL;
len = py_str_to_git_oid(py_oid, &oid);
if (len < 0)
len = py_oid_to_git_oid(py_oid, &oid);
if (len == 0)
goto out;
message = py_str_to_c_str(py_message, encoding);
@@ -728,12 +716,14 @@ Repository_create_commit(Repository *self, PyObject *args)
}
for (; i < parent_count; i++) {
py_parent = PyList_GET_ITEM(py_parents, i);
len = py_str_to_git_oid(py_parent, &oid);
if (len < 0)
len = py_oid_to_git_oid(py_parent, &oid);
if (len == 0)
goto out;
if (git_commit_lookup_prefix(&parents[i], self->repo, &oid,
(unsigned int)len))
err = git_commit_lookup_prefix(&parents[i], self->repo, &oid, len);
if (err < 0) {
Error_set(err);
goto out;
}
}
err = git_commit_create(&oid, self->repo, update_ref,
@@ -760,9 +750,9 @@ out:
PyDoc_STRVAR(Repository_create_tag__doc__,
"create_tag(name, oid, type, tagger, message) -> bytes\n"
"create_tag(name, oid, type, tagger, message) -> Oid\n"
"\n"
"Create a new tag object, return its SHA.");
"Create a new tag object, return its oid.");
PyObject *
Repository_create_tag(Repository *self, PyObject *args)
@@ -773,7 +763,7 @@ Repository_create_tag(Repository *self, PyObject *args)
git_oid oid;
git_object *target = NULL;
int err, target_type;
Py_ssize_t len;
size_t len;
if (!PyArg_ParseTuple(args, "sOiO!s",
&tag_name,
@@ -783,12 +773,12 @@ Repository_create_tag(Repository *self, PyObject *args)
&message))
return NULL;
len = py_str_to_git_oid(py_oid, &oid);
if (len < 0)
len = py_oid_to_git_oid(py_oid, &oid);
if (len == 0)
return NULL;
err = git_object_lookup_prefix(&target, self->repo, &oid,
(unsigned int)len, target_type);
err = git_object_lookup_prefix(&target, self->repo, &oid, len,
target_type);
err = err < 0 ? err : git_tag_create(&oid, self->repo, tag_name, target,
py_tagger->signature, message, 0);
git_object_free(target);
@@ -869,7 +859,7 @@ Repository_lookup_reference(Repository *self, PyObject *py_name)
free(c_name);
/* 3- Make an instance of Reference and return it */
return wrap_reference(c_reference);
return wrap_reference(c_reference, self);
}
PyDoc_STRVAR(Repository_create_reference_direct__doc__,
@@ -896,20 +886,19 @@ Repository_create_reference_direct(Repository *self, PyObject *args,
char *c_name;
git_oid oid;
int err, force;
Py_ssize_t len;
if (!PyArg_ParseTuple(args, "sOi", &c_name, &py_obj, &force))
return NULL;
len = py_str_to_git_oid_expand(self->repo, py_obj, &oid);
if (len < 0)
return Error_set((int)len);
err = py_oid_to_git_oid_expand(self->repo, py_obj, &oid);
if (err < 0)
return NULL;
err = git_reference_create(&c_reference, self->repo, c_name, &oid, force);
if (err < 0)
return Error_set(err);
return wrap_reference(c_reference);
return wrap_reference(c_reference, self);
}
PyDoc_STRVAR(Repository_create_reference_symbolic__doc__,
@@ -943,7 +932,7 @@ Repository_create_reference_symbolic(Repository *self, PyObject *args,
if (err < 0)
return Error_set(err);
return wrap_reference(c_reference);
return wrap_reference(c_reference, self);
}
@@ -1024,7 +1013,6 @@ Repository_TreeBuilder(Repository *self, PyObject *args)
git_tree *tree = NULL;
git_tree *must_free = NULL;
int err;
Py_ssize_t len;
if (!PyArg_ParseTuple(args, "|O", &py_src))
return NULL;
@@ -1038,8 +1026,8 @@ Repository_TreeBuilder(Repository *self, PyObject *args)
}
tree = py_tree->tree;
} else {
len = py_str_to_git_oid_expand(self->repo, py_src, &oid);
if (len < 0)
err = py_oid_to_git_oid_expand(self->repo, py_src, &oid);
if (err < 0)
return NULL;
err = git_tree_lookup(&tree, self->repo, &oid);
@@ -1220,12 +1208,11 @@ Repository_notes(Repository *self, PyObject *args)
}
return Error_set(err);
}
PyDoc_STRVAR(Repository_create_note__doc__,
"create_note(message, author, committer, annotated_id [,ref, force]) -> ID\n"
"create_note(message, author, committer, annotated_id [,ref, force]) -> Oid\n"
"\n"
"Create a new note for an object, return its SHA-ID."
"If no ref is given 'refs/notes/commits' will be used.");

View File

@@ -290,7 +290,7 @@ Tree_diff_to_workdir(Tree *self, PyObject *args)
if (!PyArg_ParseTuple(args, "|i", &opts.flags))
return NULL;
repo = self->repo->repo;
repo = git_tree_owner(self->tree);
err = git_diff_tree_to_workdir(&diff, repo, self->tree, &opts);
if (err < 0)
@@ -321,7 +321,7 @@ Tree_diff_to_index(Tree *self, PyObject *args, PyObject *kwds)
if (!PyArg_ParseTuple(args, "O!|i", &IndexType, &py_idx, &opts.flags))
return NULL;
repo = self->repo->repo;
repo = git_tree_owner(self->tree);
err = git_diff_tree_to_index(&diff, repo, self->tree, py_idx->index, &opts);
if (err < 0)
return Error_set(err);
@@ -354,7 +354,7 @@ Tree_diff_to_tree(Tree *self, PyObject *args, PyObject *kwds)
&swap))
return NULL;
repo = self->repo->repo;
repo = git_tree_owner(self->tree);
to = (py_tree == NULL) ? NULL : py_tree->tree;
from = self->tree;
if (swap > 0) {

View File

@@ -53,7 +53,7 @@ PyObject *
TreeBuilder_insert(TreeBuilder *self, PyObject *args)
{
PyObject *py_oid;
Py_ssize_t len;
size_t len;
int err, attr;
git_oid oid;
const char *fname;
@@ -61,8 +61,8 @@ TreeBuilder_insert(TreeBuilder *self, PyObject *args)
if (!PyArg_ParseTuple(args, "sOi", &fname, &py_oid, &attr))
return NULL;
len = py_str_to_git_oid(py_oid, &oid);
if (len < 0)
len = py_oid_to_git_oid(py_oid, &oid);
if (len == 0)
return NULL;
err = git_treebuilder_insert(NULL, self->bld, fname, &oid, attr);
@@ -74,7 +74,7 @@ TreeBuilder_insert(TreeBuilder *self, PyObject *args)
PyDoc_STRVAR(TreeBuilder_write__doc__,
"write() -> bytes\n"
"write() -> Oid\n"
"\n"
"Write the tree to the given repository.");

View File

@@ -158,10 +158,7 @@ typedef struct {
/* git_reference, git_reflog */
SIMPLE_TYPE(Walker, git_revwalk, walk)
typedef struct {
PyObject_HEAD
git_reference *reference;
} Reference;
SIMPLE_TYPE(Reference, git_reference, reference)
typedef struct {
PyObject_HEAD
@@ -192,6 +189,4 @@ typedef struct {
SIMPLE_TYPE(Remote, git_remote, remote)
PyObject* lookup_object(Repository *repo, const git_oid *oid, git_otype type);
#endif

View File

@@ -79,7 +79,8 @@
/* Utilities */
#define to_unicode(x, encoding, errors) to_unicode_n(x, strlen(x), encoding, errors)
#define to_unicode(x, encoding, errors)\
to_unicode_n(x, strlen(x), encoding, errors)
PYGIT2_FN_UNUSED
Py_LOCAL_INLINE(PyObject*)
@@ -150,8 +151,8 @@ char * py_str_to_c_str(PyObject *value, const char *encoding);
/* Helpers to make type init shorter. */
#define INIT_TYPE(type, base, new) \
if (base != NULL) type.tp_base = base; \
if (new != NULL) type.tp_new = new; \
type.tp_base = base; \
type.tp_new = new; \
if (PyType_Ready(&type) < 0) return NULL;
#define ADD_TYPE(module, type) \

View File

@@ -53,12 +53,11 @@ PyObject *
Walker_hide(Walker *self, PyObject *py_hex)
{
int err;
Py_ssize_t len;
git_oid oid;
len = py_str_to_git_oid_expand(self->repo->repo, py_hex, &oid);
if (len < 0)
return Error_set((int)len);
err = py_oid_to_git_oid_expand(self->repo->repo, py_hex, &oid);
if (err < 0)
return NULL;
err = git_revwalk_hide(self->walk, &oid);
if (err < 0)
@@ -77,12 +76,11 @@ PyObject *
Walker_push(Walker *self, PyObject *py_hex)
{
int err;
Py_ssize_t len;
git_oid oid;
len = py_str_to_git_oid_expand(self->repo->repo, py_hex, &oid);
if (len < 0)
return Error_set((int)len);
err = py_oid_to_git_oid_expand(self->repo->repo, py_hex, &oid);
if (err < 0)
return NULL;
err = git_revwalk_push(self->walk, &oid);
if (err < 0)

View File

@@ -40,7 +40,10 @@ from os.path import join, realpath
# Import from pygit2
from pygit2 import GIT_OBJ_ANY, GIT_OBJ_BLOB, GIT_OBJ_COMMIT
from pygit2 import init_repository, discover_repository, Reference, hashfile
from pygit2 import (
init_repository, clone_repository, discover_repository,
Reference, hashfile
)
from pygit2 import Oid
import pygit2
from . import utils
@@ -101,7 +104,7 @@ class RepositoryTest(utils.BareRepoTestCase):
self.assertFalse('a' * 20 in self.repo)
def test_iterable(self):
l = [ obj for obj in self.repo ]
l = [obj for obj in self.repo]
oid = Oid(hex=BLOB_HEX)
self.assertTrue(oid in l)
@@ -135,9 +138,10 @@ class RepositoryTest(utils.BareRepoTestCase):
commit = self.repo[commit_sha_prefix]
self.assertEqual(commit_sha, commit.hex)
self.assertEqual(GIT_OBJ_COMMIT, commit.type)
self.assertEqual(('Second test data commit.\n\n'
'This commit has some additional text.\n'),
commit.message)
self.assertEqual(
('Second test data commit.\n\n'
'This commit has some additional text.\n'),
commit.message)
self.assertRaises(ValueError, self.repo.__getitem__, too_short_prefix)
def test_get_path(self):
@@ -208,7 +212,7 @@ class RepositoryTest_II(utils.RepoTestCase):
def test_checkout_index(self):
# some changes to working dir
with open(os.path.join(self.repo.workdir, 'hello.txt'), 'w') as f:
f.write('new content')
f.write('new content')
# checkout index
self.assertTrue('hello.txt' in self.repo.status())
@@ -218,7 +222,7 @@ class RepositoryTest_II(utils.RepoTestCase):
def test_checkout_head(self):
# some changes to the index
with open(os.path.join(self.repo.workdir, 'bye.txt'), 'w') as f:
f.write('new content')
f.write('new content')
self.repo.index.add('bye.txt')
# checkout from index should not change anything
@@ -272,6 +276,7 @@ class InitRepositoryTest(utils.NoRepoTestCase):
repo = init_repository(self._temp_dir, bare=True)
self.assertTrue(repo.is_bare)
class DiscoverRepositoryTest(utils.NoRepoTestCase):
def test_discover_repo(self):
repo = init_repository(self._temp_dir, False)
@@ -279,6 +284,7 @@ class DiscoverRepositoryTest(utils.NoRepoTestCase):
os.makedirs(subdir)
self.assertEqual(repo.path, discover_repository(subdir))
class EmptyRepositoryTest(utils.EmptyRepoTestCase):
def test_is_empty(self):
@@ -292,5 +298,69 @@ class EmptyRepositoryTest(utils.EmptyRepoTestCase):
self.assertFalse(self.repo.head_is_detached)
class CloneRepositoryTest(utils.NoRepoTestCase):
def test_clone_repository(self):
repo_path = "./test/data/testrepo.git/"
repo = clone_repository(repo_path, self._temp_dir)
self.assertFalse(repo.is_empty)
self.assertFalse(repo.is_bare)
def test_clone_bare_repository(self):
repo_path = "./test/data/testrepo.git/"
repo = clone_repository(repo_path, self._temp_dir, bare=True)
self.assertFalse(repo.is_empty)
self.assertTrue(repo.is_bare)
def test_clone_remote_name(self):
repo_path = "./test/data/testrepo.git/"
repo = clone_repository(
repo_path, self._temp_dir, remote_name="custom_remote"
)
self.assertFalse(repo.is_empty)
self.assertEqual(repo.remotes[0].name, "custom_remote")
def test_clone_push_url(self):
repo_path = "./test/data/testrepo.git/"
repo = clone_repository(
repo_path, self._temp_dir, push_url="custom_push_url"
)
self.assertFalse(repo.is_empty)
# FIXME: When pygit2 supports retrieving the pushurl parameter,
# enable this test
# self.assertEqual(repo.remotes[0].pushurl, "custom_push_url")
def test_clone_fetch_spec(self):
repo_path = "./test/data/testrepo.git/"
repo = clone_repository(
repo_path, self._temp_dir, fetch_spec="refs/heads/test"
)
self.assertFalse(repo.is_empty)
# FIXME: When pygit2 retrieve the fetchspec we passed to git clone.
# fetchspec seems to be going through, but the Repository class is
# not getting it.
# self.assertEqual(repo.remotes[0].fetchspec, "refs/heads/test")
def test_clone_push_spec(self):
repo_path = "./test/data/testrepo.git/"
repo = clone_repository(
repo_path, self._temp_dir, push_spec="refs/heads/test"
)
self.assertFalse(repo.is_empty)
# FIXME: When pygit2 supports retrieving the pushspec parameter,
# enable this test
# not sure how to test this either... couldn't find pushspec
# self.assertEqual(repo.remotes[0].fetchspec, "refs/heads/test")
def test_clone_checkout_branch(self):
repo_path = "./test/data/testrepo.git/"
repo = clone_repository(
repo_path, self._temp_dir, checkout_branch="test"
)
self.assertFalse(repo.is_empty)
# FIXME: When pygit2 supports retrieving the current branch,
# enable this test
# self.assertEqual(repo.remotes[0].current_branch, "test")
if __name__ == '__main__':
unittest.main()