feat(blame): add binding and api method for git_blame_buffer (#20)

This commit is contained in:
Aleksey Kulikov 2021-12-20 15:03:31 +03:00 committed by GitHub
parent 7148fbf194
commit 39a71811cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 4 deletions

View file

@ -58,6 +58,38 @@ Pointer<git_blame> file({
} }
} }
/// Get blame data for a file that has been modified in memory. The [reference]
/// parameter is a pre-calculated blame for the in-odb history of the file.
/// This means that once a file blame is completed (which can be expensive),
/// updating the buffer blame is very fast.
///
/// Lines that differ between the buffer and the committed version are marked
/// as having a zero OID for their finalCommitOid.
///
/// Throws a [LibGit2Error] if error occured.
Pointer<git_blame> buffer({
required Pointer<git_blame> reference,
required String buffer,
}) {
final out = calloc<Pointer<git_blame>>();
final bufferC = buffer.toNativeUtf8().cast<Int8>();
final error = libgit2.git_blame_buffer(
out,
reference,
bufferC,
buffer.length,
);
calloc.free(bufferC);
if (error < 0) {
calloc.free(out);
throw LibGit2Error(libgit2.git_error_last());
} else {
return out.value;
}
}
/// Gets the number of hunks that exist in the blame structure. /// Gets the number of hunks that exist in the blame structure.
int hunkCount(Pointer<git_blame> blame) { int hunkCount(Pointer<git_blame> blame) {
return libgit2.git_blame_get_hunk_count(blame); return libgit2.git_blame_get_hunk_count(blame);

View file

@ -59,6 +59,23 @@ class Blame with IterableMixin<BlameHunk> {
); );
} }
/// Returns blame data for a file that has been modified in memory. The
/// [reference] parameter is a pre-calculated blame for the in-odb history of
/// the file.
/// This means that once a file blame is completed (which can be expensive),
/// updating the buffer blame is very fast.
///
/// Lines that differ between the buffer and the committed version are marked
/// as having a zero Oid for their finalCommitOid.
///
/// Throws a [LibGit2Error] if error occured.
Blame.buffer({required Blame reference, required String buffer}) {
_blamePointer = bindings.buffer(
reference: reference._blamePointer,
buffer: buffer,
);
}
/// Pointer to memory address for allocated blame object. /// Pointer to memory address for allocated blame object.
late final Pointer<git_blame> _blamePointer; late final Pointer<git_blame> _blamePointer;
@ -117,8 +134,11 @@ class BlameHunk {
/// Author of [finalCommitOid]. If [GitBlameFlag.useMailmap] has been /// Author of [finalCommitOid]. If [GitBlameFlag.useMailmap] has been
/// specified, it will contain the canonical real name and email address. /// specified, it will contain the canonical real name and email address.
Signature get finalCommitter => Signature? get finalCommitter {
Signature(_blameHunkPointer.ref.final_signature); return _blameHunkPointer.ref.final_signature == nullptr
? null
: Signature(_blameHunkPointer.ref.final_signature);
}
/// [Oid] of the commit where this line was last changed. /// [Oid] of the commit where this line was last changed.
Oid get finalCommitOid => Oid.fromRaw(_blameHunkPointer.ref.final_commit_id); Oid get finalCommitOid => Oid.fromRaw(_blameHunkPointer.ref.final_commit_id);
@ -129,8 +149,11 @@ class BlameHunk {
/// Author of [originCommitOid]. If [GitBlameFlag.useMailmap] has been /// Author of [originCommitOid]. If [GitBlameFlag.useMailmap] has been
/// specified, it will contain the canonical real name and email address. /// specified, it will contain the canonical real name and email address.
Signature get originCommitter => Signature? get originCommitter {
Signature(_blameHunkPointer.ref.orig_signature); return _blameHunkPointer.ref.orig_signature == nullptr
? null
: Signature(_blameHunkPointer.ref.orig_signature);
}
/// [Oid] of the commit where this hunk was found. This will usually be the /// [Oid] of the commit where this hunk was found. This will usually be the
/// same as [finalCommitOid], except when /// same as [finalCommitOid], except when

View file

@ -88,6 +88,31 @@ void main() {
expect(() => repo.blame(path: 'invalid'), throwsA(isA<LibGit2Error>())); expect(() => repo.blame(path: 'invalid'), throwsA(isA<LibGit2Error>()));
}); });
test('returns blame for buffer', () {
final blame = repo.blame(path: 'feature_file');
expect(blame.length, 2);
final bufferBlame = Blame.buffer(reference: blame, buffer: ' ');
final blameHunk = bufferBlame.first;
expect(bufferBlame.length, 1);
expect(blameHunk.originCommitOid.sha, '0' * 40);
expect(blameHunk.originCommitter, null);
expect(blameHunk.finalCommitOid.sha, '0' * 40);
expect(blameHunk.finalCommitter, null);
bufferBlame.free();
blame.free();
});
test('throws when trying to get blame for empty buffer', () {
final blame = repo.blame(path: 'feature_file');
expect(
() => Blame.buffer(reference: blame, buffer: ''),
throwsA(isA<LibGit2Error>()),
);
blame.free();
});
test( test(
'successfully gets the blame for provided file with ' 'successfully gets the blame for provided file with '
'minMatchCharacters set', () { 'minMatchCharacters set', () {