These are only needed in C code. With Python files the signatures are
automatically generated. The only drawback is the return value is not
included in the signature, so document it in the body of the docstring.
IndexEntry._to_c requires its caller to hold a reference to the path it
returns until it no longer needs the C structure.
Repository.merge_file_from_index was not doing so, causing the merge
text to contain garbage from freed memory in some cases.
The submodule type has been implemented as a C type. When opening
a submodule's repository this leads to the bug that instead of an
actual pygit2.Repository being instantiated we only create an
object of the C Repository type.
As this is not trivially fixed within the C code, reimplement the
submodule type as a Python interface with CFFI. As submodules
provide no functionality that is usually accessed repeatedly the
code paths should not prove performance critical. In addition,
maintainability is improved by this reimplementation.
When merging index entries where the corresponding files contain Unicode
codepoints an error is thrown. Decode the C string using UTF-8 to fix the issue
and adjust the test case for merging files to contain umlauts to catch such
errors.
This allows us to generate a textual diff of conflicting files in
bare repositories by performing a merge on the index followed by
repo.merge_file_from_index on the resulting index entries.
This is the function which does the work for Repository.merge_commits()
and allows us more direct control over which trees we want to merge,
including trees which do not belong to commits.
Apart from the usual API changes, we now need to introduce the concept
of whether we still own the C object underneath our Repository and
Remote objects.
When using the custom callbacks for repository and remote creation
during clone, we pass the pointer and thus ownership of the object back
to the library. We will then get the repository back at the end.
We return the object which was handed to us rather than opening the
repository again with the local path as there is now a much higher
chance that the cloned repository does not use the standard backends.
This lets us look up remotes by name, which is not possible by just
returning the list of remotes.
Move remote creation to Repostiory.remotes.create() and keep the old
Repository.create_remote() for compatibility, delegating to this new
way.
Existing code should keep working, but this moves us towards what we'd
need for a better interface in 0.22 which makes remote renaming and
deleting work with a name rather than an instance and would make sense
to exist as part of an Remote.remotes object.
I've gone with taking a string and converting it because the depth of
the namespacing in the libgit2 name is rather large and we don't care
about the global namespace that C has; and this also lets us pass the
same as the '-X' option to git-merge.
Add Repository.write_archive() to write a given tree to an archive. As
there are many customisation options, we only provide a method to write
to an archive which is created by the user.
Following from the previous commits, make 'head' read-only and provide a
method to update head while providing a message.
The checkout() codepath which switches branches has been updated to
provide a reflog entry which mimics git's.
This requires fairly little work on the pygit2 side to kick off all the
searching on the libgit2 side, so it's a fairly good candidate.
This changes the return value for the commit ids to Oid instead of
strings, which is what we generally try to return.
This halves the amount of code we have to take into account for dealing
with the config.
There is a slight change in the API. Config.get_multivar() returns an
iterator instead of a list, which lets us reuse code from the general
iterator and is closer to libgit2's API.
Casting a pointer to a non-pointer type is something which you should
never do. Instead, do something a bit more convoluted, but which is
guaranteed to give us the right pointer, as well as making sure that the
memory we exchange between python/cffi and the C extension is of the
right pointer size.
While we're touching this code, fix which object we pass to the Remote
constructor to keep alive. We need to pass the Repository object to
stop it from becoming unreferenced (and thus freeing memory the remote
needs) instead of the git_repository pointer.