From b83fea93609b09c9a3a0f6434a429a180d20dd4d Mon Sep 17 00:00:00 2001 From: Aleksey Kulikov Date: Thu, 16 Sep 2021 20:04:40 +0300 Subject: [PATCH] feat(commit): add ability to revert commit --- lib/src/bindings/commit.dart | 39 ++++++++++++++++++++++++++++++++++++ lib/src/repository.dart | 18 +++++++++++++++++ test/commit_test.dart | 15 ++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/lib/src/bindings/commit.dart b/lib/src/bindings/commit.dart index 720f5d3..c43344b 100644 --- a/lib/src/bindings/commit.dart +++ b/lib/src/bindings/commit.dart @@ -191,6 +191,45 @@ Pointer tree(Pointer commit) { return libgit2.git_commit_tree_id(commit); } +/// Reverts the given commit against the given "our" commit, producing an index that +/// reflects the result of the revert. +/// +/// The returned index must be freed explicitly with `free()`. +/// +/// Throws a [LibGit2Error] if error occured. +Pointer revertCommit( + Pointer repo, + Pointer revertCommit, + Pointer ourCommit, + int mainline, +) { + final out = calloc>(); + final opts = calloc(); + final optsError = + libgit2.git_merge_options_init(opts, GIT_MERGE_OPTIONS_VERSION); + + if (optsError < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } + + final error = libgit2.git_revert_commit( + out, + repo, + revertCommit, + ourCommit, + mainline, + opts, + ); + + calloc.free(opts); + + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } else { + return out.value; + } +} + /// Get the repository that contains the commit. Pointer owner(Pointer commit) => libgit2.git_commit_owner(commit); diff --git a/lib/src/repository.dart b/lib/src/repository.dart index 4d6ce1f..1f048e6 100644 --- a/lib/src/repository.dart +++ b/lib/src/repository.dart @@ -619,6 +619,24 @@ class Repository { return Index(result); } + /// Reverts the given commit against the given "our" commit, producing an index that + /// reflects the result of the revert. + /// + /// [mainline] is parent of the [revertCommit] if it is a merge (i.e. 1, 2). + /// + /// The returned index must be freed explicitly with `free()`. + /// + /// Throws a [LibGit2Error] if error occured. + Index revertCommit( + {required Commit revertCommit, required Commit ourCommit, mainline = 0}) { + return Index(commit_bindings.revertCommit( + _repoPointer, + revertCommit.pointer, + ourCommit.pointer, + mainline, + )); + } + /// Merges two trees, producing an index that reflects the result of the merge. /// The index may be written as-is to the working directory or checked out. If the index /// is to be converted to a tree, the caller should resolve any conflicts that arose as part diff --git a/test/commit_test.dart b/test/commit_test.dart index b91e769..0127792 100644 --- a/test/commit_test.dart +++ b/test/commit_test.dart @@ -56,6 +56,21 @@ void main() { commit.free(); }); + test('successfully reverts commit', () { + final to = repo['78b8bf123e3952c970ae5c1ce0a3ea1d1336f6e8'] as Commit; + final from = repo['821ed6e80627b8769d170a293862f9fc60825226'] as Commit; + final index = repo.index; + expect(index.contains('dir/dir_file.txt'), true); + + final revertIndex = repo.revertCommit(revertCommit: from, ourCommit: to); + expect(revertIndex.contains('dir/dir_file.txt'), false); + + revertIndex.free(); + index.free(); + to.free(); + from.free(); + }); + test('successfully creates commit', () { final oid = Commit.create( repo: repo,