diff --git a/README.rst b/README.rst index bc66152cb..587997633 100644 --- a/README.rst +++ b/README.rst @@ -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 ============== diff --git a/pygit2/decl.h b/pygit2/decl.h index 431c10d4e..cd5dae955 100644 --- a/pygit2/decl.h +++ b/pygit2/decl.h @@ -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); diff --git a/pygit2/repository.py b/pygit2/repository.py index 472f4ffb8..76f633021 100644 --- a/pygit2/repository.py +++ b/pygit2/repository.py @@ -1001,6 +1001,39 @@ def set_ident(self, name, email): 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): diff --git a/test/test_repository.py b/test/test_repository.py index 0969fc00f..941851bb4 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -43,7 +43,7 @@ if six.PY2: from urllib import pathname2url - + if six.PY3: from urllib.request import pathname2url @@ -435,6 +435,28 @@ def test_stash(self): 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 @@ def test_clone_repository_and_remote_callbacks(self): src_repo_relpath = "./test/data/testrepo.git/" repo_path = os.path.join(self._temp_dir, "clone-into") url = pathname2url(os.path.realpath(src_repo_relpath)) - + if url.startswith('///'): url = 'file:' + url else: