feat(diff): add more bindings and api methods (#18)

This commit is contained in:
Aleksey Kulikov 2021-12-14 12:53:17 +03:00 committed by GitHub
parent 6c1735d67d
commit b3e9f6dd1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 238 additions and 29 deletions

View file

@ -298,6 +298,24 @@ Pointer<git_buf> addToBuf({
return bufferPointer;
}
/// Counter for hunk number being applied.
///
/// **IMPORTANT**: make sure to reset it to 0 before using since it's a global
/// variable.
int _counter = 0;
/// When applying a patch, callback that will be made per hunk.
int _hunkCb(Pointer<git_diff_hunk> hunk, Pointer<Void> payload) {
final index = payload.cast<Int32>().value;
if (_counter == index) {
_counter++;
return 0;
} else {
_counter++;
return 1;
}
}
/// Apply a diff to the given repository, making changes directly in the
/// working directory, the index, or both.
///
@ -305,6 +323,7 @@ Pointer<git_buf> addToBuf({
bool apply({
required Pointer<git_repository> repoPointer,
required Pointer<git_diff> diffPointer,
int? hunkIndex,
required int location,
bool check = false,
}) {
@ -313,8 +332,18 @@ bool apply({
if (check) {
opts.ref.flags |= git_apply_flags_t.GIT_APPLY_CHECK;
}
Pointer<Int32> payload = nullptr;
if (hunkIndex != null) {
_counter = 0;
const except = -1;
final git_apply_hunk_cb callback = Pointer.fromFunction(_hunkCb, except);
payload = calloc<Int32>()..value = hunkIndex;
opts.ref.payload = payload.cast();
opts.ref.hunk_cb = callback;
}
final error = libgit2.git_apply(repoPointer, diffPointer, location, opts);
calloc.free(payload);
calloc.free(opts);
if (error < 0) {
@ -324,6 +353,46 @@ bool apply({
}
}
/// Apply a diff to a tree, and return the resulting image as an index.
///
/// Throws a [LibGit2Error] if error occured.
Pointer<git_index> applyToTree({
required Pointer<git_repository> repoPointer,
required Pointer<git_tree> treePointer,
required Pointer<git_diff> diffPointer,
int? hunkIndex,
}) {
final out = calloc<Pointer<git_index>>();
final opts = calloc<git_apply_options>();
libgit2.git_apply_options_init(opts, GIT_APPLY_OPTIONS_VERSION);
Pointer<Int32> payload = nullptr;
if (hunkIndex != null) {
_counter = 0;
const except = -1;
final git_apply_hunk_cb callback = Pointer.fromFunction(_hunkCb, except);
payload = calloc<Int32>()..value = hunkIndex;
opts.ref.payload = payload.cast();
opts.ref.hunk_cb = callback;
}
final error = libgit2.git_apply_to_tree(
out,
repoPointer,
treePointer,
diffPointer,
opts,
);
calloc.free(payload);
calloc.free(opts);
if (error < 0) {
calloc.free(out);
throw LibGit2Error(libgit2.git_error_last());
} else {
return out.value;
}
}
/// Free a previously allocated diff stats.
void statsFree(Pointer<git_diff_stats> stats) =>
libgit2.git_diff_stats_free(stats);

View file

@ -1362,27 +1362,56 @@ class Repository {
/// [location] (directly in the working directory (default), the index or
/// both).
///
/// [hunkIndex] is optional index of the hunk to apply.
///
/// Throws a [LibGit2Error] if error occured.
void apply({
required Diff diff,
int? hunkIndex,
GitApplyLocation location = GitApplyLocation.workdir,
}) {
diff_bindings.apply(
repoPointer: _repoPointer,
diffPointer: diff.pointer,
hunkIndex: hunkIndex,
location: location.value,
);
}
/// Applies the [diff] to the [tree], and returns the resulting image as an
/// index.
///
/// [hunkIndex] is optional index of the hunk to apply.
///
/// Throws a [LibGit2Error] if error occured.
Index applyToTree({
required Diff diff,
required Tree tree,
int? hunkIndex,
}) {
return Index(
diff_bindings.applyToTree(
repoPointer: _repoPointer,
diffPointer: diff.pointer,
treePointer: tree.pointer,
hunkIndex: hunkIndex,
),
);
}
/// Checks if the [diff] will apply to provided [location] (the working
/// directory (default), the index or both).
///
/// [hunkIndex] is optional index of the hunk to apply.
bool applies({
required Diff diff,
int? hunkIndex,
GitApplyLocation location = GitApplyLocation.workdir,
}) {
return diff_bindings.apply(
repoPointer: _repoPointer,
diffPointer: diff.pointer,
hunkIndex: hunkIndex,
location: location.value,
check: true,
);