revert: Add support for git_revert_commit via Repository.revert_commit()

This change adds `Repository.revert_commit()` which wraps around
`git_revert_commit` which will return an `Index` with the appropriate
changes to revert the specified commit.

Fixes #710
This commit is contained in:
Mark Adams 2017-06-05 16:06:05 -05:00
parent 87beb76dcc
commit c6305a062b
4 changed files with 60 additions and 3 deletions

View File

@ -68,7 +68,7 @@ Authors
Peter Dave Hello Philippe Ombredanne Ridge Kennedy
Ross Nicoll Rui Abreu Ferreira Sheeo
Soasme Vladimir Rutsky Yu Jianjian
chengyuhang earl
chengyuhang earl Mark Adams
License
==============

View File

@ -922,3 +922,5 @@ typedef enum {
int git_attr_get(const char **value_out, git_repository *repo, uint32_t flags, const char *path, const char *name);
git_attr_t git_attr_value(const char *attr);
int git_revert_commit(git_index **out, git_repository *repo, git_commit *revert_commit, git_commit *our_commit, unsigned int mainline, const git_merge_options *merge_options);

View File

@ -1001,6 +1001,39 @@ class BaseRepository(_Repository):
err = C.git_repository_set_ident(self._repo, to_bytes(name), to_bytes(email))
check_error(err)
def revert_commit(self, revert_commit, our_commit, mainline=0):
"""Reverts the given Commit against the given "our" Commit,
producing an Index that reflects the result of the revert.
Arguments
revert_commit
The Commit to revert
our_commit
The Commit to revert against (eg, HEAD)
mainline
The parent of the revert Commit, if it is a merge (i.e. 1, 2)
Returns an Index with the result of the revert.
"""
cindex = ffi.new('git_index **')
revert_commit_ptr = ffi.new('git_commit **')
our_commit_ptr = ffi.new('git_commit **')
ffi.buffer(revert_commit_ptr)[:] = revert_commit._pointer[:]
ffi.buffer(our_commit_ptr)[:] = our_commit._pointer[:]
opts = ffi.new('git_merge_options *')
err = C.git_merge_init_options(opts, C.GIT_MERGE_OPTIONS_VERSION)
check_error(err)
err = C.git_revert_commit(
cindex, self._repo, revert_commit_ptr[0], our_commit_ptr[0], mainline, opts
)
check_error(err)
return Index.from_c(self, cindex)
class Branches(object):
def __init__(self, repository, flag=GIT_BRANCH_ALL):

View File

@ -43,7 +43,7 @@ import six
if six.PY2:
from urllib import pathname2url
if six.PY3:
from urllib.request import pathname2url
@ -435,6 +435,28 @@ class RepositoryTest_II(utils.RepoTestCase):
self.repo.stash_drop()
self.assertRaises(KeyError, self.repo.stash_pop)
def test_revert(self):
master = self.repo.head.peel()
commit_to_revert = self.repo['4ec4389a8068641da2d6578db0419484972284c8']
parent = commit_to_revert.parents[0]
commit_diff_stats = (
parent.tree.diff_to_tree(commit_to_revert.tree).stats
)
revert_index = self.repo.revert_commit(commit_to_revert, master)
revert_diff_stats = revert_index.diff_to_tree(master.tree).stats
self.assertEquals(
revert_diff_stats.insertions, commit_diff_stats.deletions
)
self.assertEquals(
revert_diff_stats.deletions, commit_diff_stats.insertions
)
self.assertEquals(
revert_diff_stats.files_changed, commit_diff_stats.files_changed
)
class RepositorySignatureTest(utils.RepoTestCase):
def test_default_signature(self):
@ -533,7 +555,7 @@ class CloneRepositoryTest(utils.NoRepoTestCase):
src_repo_relpath = "./test/data/testrepo.git/"
repo_path = os.path.join(self._temp_dir, "clone-into")
url = pathname2url(os.path.realpath(src_repo_relpath))
if url.startswith('///'):
url = 'file:' + url
else: