From 4a36922129bbf88ca6653e053432f80dd5e07e65 Mon Sep 17 00:00:00 2001 From: Aleksey Kulikov Date: Thu, 23 Jun 2022 18:37:27 +0300 Subject: [PATCH] feat(reset): add ability to pass checkout options to `reset(...)` API method (#72) --- lib/src/bindings/reset.dart | 39 +++++++++++++++++++++++++++++++++++-- lib/src/repository.dart | 21 ++++++++++++++++++-- test/reset_test.dart | 28 ++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/lib/src/bindings/reset.dart b/lib/src/bindings/reset.dart index cca5dba..7b45c3f 100644 --- a/lib/src/bindings/reset.dart +++ b/lib/src/bindings/reset.dart @@ -17,13 +17,48 @@ import 'package:libgit2dart/src/util.dart'; /// HARD reset will trigger a MIXED reset and the working directory will be /// replaced with the content of the index. (Untracked and ignored files will /// be left alone, however.) +/// +/// Throws a [LibGit2Error] if error occured. void reset({ required Pointer repoPointer, required Pointer targetPointer, required int resetType, - required Pointer checkoutOptsPointer, + int? strategy, + String? checkoutDirectory, + List? pathspec, }) { - libgit2.git_reset(repoPointer, targetPointer, resetType, checkoutOptsPointer); + final opts = calloc(); + libgit2.git_checkout_options_init(opts, GIT_CHECKOUT_OPTIONS_VERSION); + + if (strategy != null) { + opts.ref.checkout_strategy = strategy; + } + if (checkoutDirectory != null) { + opts.ref.target_directory = checkoutDirectory.toChar(); + } + var pathPointers = >[]; + Pointer> strArray = nullptr; + if (pathspec != null) { + pathPointers = pathspec.map((e) => e.toChar()).toList(); + strArray = calloc(pathspec.length); + for (var i = 0; i < pathspec.length; i++) { + strArray[i] = pathPointers[i]; + } + opts.ref.paths.strings = strArray; + opts.ref.paths.count = pathspec.length; + } + + final error = libgit2.git_reset(repoPointer, targetPointer, resetType, opts); + + for (final p in pathPointers) { + calloc.free(p); + } + calloc.free(strArray); + calloc.free(opts); + + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } } /// Updates some entries in the index from the target commit tree. diff --git a/lib/src/repository.dart b/lib/src/repository.dart index 619b1ea..03c7190 100644 --- a/lib/src/repository.dart +++ b/lib/src/repository.dart @@ -557,8 +557,23 @@ class Repository extends Equatable { /// /// [resetType] is one of the [GitReset] flags. /// + /// [strategy], [checkoutDirectory] and [pathspec] are optional checkout + /// options to be used for a HARD reset. + /// + /// [strategy] is optional combination of [GitCheckout] flags. + /// + /// [checkoutDirectory] is optional alternative checkout path to workdir. + /// + /// [pathspec] is optional list of files to checkout. + /// /// Throws a [LibGit2Error] if error occured. - void reset({required Oid oid, required GitReset resetType}) { + void reset({ + required Oid oid, + required GitReset resetType, + Set? strategy, + String? checkoutDirectory, + List? pathspec, + }) { final object = object_bindings.lookup( repoPointer: _repoPointer, oidPointer: oid.pointer, @@ -569,7 +584,9 @@ class Repository extends Equatable { repoPointer: _repoPointer, targetPointer: object, resetType: resetType.value, - checkoutOptsPointer: nullptr, + strategy: strategy?.fold(0, (acc, e) => acc! | e.value), + checkoutDirectory: checkoutDirectory, + pathspec: pathspec, ); object_bindings.free(object); diff --git a/test/reset_test.dart b/test/reset_test.dart index 96366d6..f5dd62e 100644 --- a/test/reset_test.dart +++ b/test/reset_test.dart @@ -50,6 +50,34 @@ void main() { expect(diff.deltas.length, 1); }); + test('resets with provided checkout options', () { + expect(file.readAsStringSync(), 'Feature edit\n'); + + repo.reset( + oid: repo[sha], + resetType: GitReset.hard, + strategy: {GitCheckout.conflictStyleZdiff3}, + pathspec: ['feature_file'], + ); + + expect(file.readAsStringSync(), isEmpty); + }); + + test( + 'throws when trying to reset and error occurs', + testOn: '!windows', + () { + expect( + () => repo.reset( + oid: repo[sha], + resetType: GitReset.hard, + checkoutDirectory: '', + ), + throwsA(isA()), + ); + }, + ); + group('resetDefault', () { test('updates entry in the index', () { file.writeAsStringSync('new edit');