Skip to content

Commit 584bda3

Browse files
committed
Add Repository.revert()
This exposes libgit2's git_revert(), which produces changes in the index and working directory. It also affects the repository's state (via .git/REVERT_HEAD) and prepared message (via .git/MERGE_MSG). The existing function Repository.revert_commit(), which exposes git_revert_commit(), is less powerful -- it doesn't check out the resulting index, and it doesn't modify the state and prepared message. Note: git_revert() takes additional checkout/revert settings. We could implement support for these as extra arguments to Repository.revert() in the future.
1 parent 1a8442d commit 584bda3

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

pygit2/decl/revert.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
#define GIT_REVERT_OPTIONS_VERSION ...
2+
3+
typedef struct {
4+
unsigned int version;
5+
unsigned int mainline;
6+
git_merge_options merge_opts;
7+
git_checkout_options checkout_opts;
8+
} git_revert_options;
9+
10+
int git_revert(
11+
git_repository *repo,
12+
git_commit *commit,
13+
const git_revert_options *given_opts);
14+
115
int git_revert_commit(
216
git_index **out,
317
git_repository *repo,

pygit2/repository.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,19 @@ def set_ident(self, name, email):
13431343
err = C.git_repository_set_ident(self._repo, to_bytes(name), to_bytes(email))
13441344
check_error(err)
13451345

1346+
def revert(self, commit: Commit):
1347+
"""
1348+
Revert the given commit, producing changes in the index and working
1349+
directory.
1350+
1351+
This operation updates the repository's state and prepared message
1352+
(MERGE_MSG).
1353+
"""
1354+
commit_ptr = ffi.new('git_commit **')
1355+
ffi.buffer(commit_ptr)[:] = commit._pointer[:]
1356+
err = C.git_revert(self._repo, commit_ptr[0], ffi.NULL)
1357+
check_error(err)
1358+
13461359
def revert_commit(self, revert_commit, our_commit, mainline=0):
13471360
"""
13481361
Revert the given Commit against the given "our" Commit, producing an

test/test_repository.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
FileStatus,
4040
ObjectType,
4141
RepositoryOpenFlag,
42+
RepositoryState,
4243
ResetMode,
4344
StashApplyProgress,
4445
)
@@ -538,7 +539,7 @@ def checkout_notify(self, why, path, baseline, target, workdir):
538539
assert f.read() == 'stashed content'
539540

540541

541-
def test_revert(testrepo):
542+
def test_revert_commit(testrepo):
542543
master = testrepo.head.peel()
543544
commit_to_revert = testrepo['4ec4389a8068641da2d6578db0419484972284c8']
544545
parent = commit_to_revert.parents[0]
@@ -552,6 +553,26 @@ def test_revert(testrepo):
552553
assert revert_diff_stats.files_changed == commit_diff_stats.files_changed
553554

554555

556+
def test_revert(testrepo):
557+
hello_txt = Path(testrepo.workdir) / 'hello.txt'
558+
commit_to_revert = testrepo['4ec4389a8068641da2d6578db0419484972284c8']
559+
560+
assert testrepo.state() == RepositoryState.NONE
561+
assert not testrepo.message
562+
assert 'bonjour le monde' in hello_txt.read_text()
563+
564+
# Revert addition of French line in hello.txt
565+
testrepo.revert(commit_to_revert)
566+
567+
assert 'bonjour le monde' not in hello_txt.read_text()
568+
assert testrepo.status()['hello.txt'] == FileStatus.INDEX_MODIFIED
569+
assert testrepo.state() == RepositoryState.REVERT
570+
assert (
571+
testrepo.message
572+
== f'Revert "Say hello in French"\n\nThis reverts commit {commit_to_revert.id}.\n'
573+
)
574+
575+
555576
def test_default_signature(testrepo):
556577
config = testrepo.config
557578
config['user.name'] = 'Random J Hacker'

0 commit comments

Comments
 (0)