refactor(repository)!: use Finalizer to automatically free allocated memory (#51)

BREAKING CHANGE: Return value of identity getter changed from Map<String, String> to Identity
This commit is contained in:
Aleksey Kulikov 2022-05-02 15:33:31 +03:00 committed by GitHub
parent aef440e345
commit 4e55d0f06c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 109 additions and 151 deletions

View file

@ -6,6 +6,8 @@ import 'package:libgit2dart/src/bindings/credentials.dart'
as credentials_bindings;
import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
import 'package:libgit2dart/src/bindings/remote.dart' as remote_bindings;
import 'package:libgit2dart/src/bindings/repository.dart'
as repository_bindings;
import 'package:libgit2dart/src/util.dart';
class RemoteCallbacks {
@ -112,17 +114,25 @@ class RemoteCallbacks {
int bare,
Pointer<Void> payload,
) {
final repoPointer = Repository.init(
var flagsInt = repositoryCbData!.flags.fold(
0,
(int acc, e) => acc | e.value,
);
if (repositoryCbData!.bare) {
flagsInt |= GitRepositoryInit.bare.value;
}
final repoPointer = repository_bindings.init(
path: repositoryCbData!.path,
bare: repositoryCbData!.bare,
flags: repositoryCbData!.flags,
flags: flagsInt,
mode: repositoryCbData!.mode,
workdirPath: repositoryCbData!.workdirPath,
description: repositoryCbData!.description,
templatePath: repositoryCbData!.templatePath,
initialHead: repositoryCbData!.initialHead,
originUrl: repositoryCbData!.originUrl,
).pointer;
);
repo[0] = repoPointer;

View file

@ -321,17 +321,19 @@ void setIdentity({
}
/// Retrieve the configured identity to use for reflogs.
Map<String, String> identity(Pointer<git_repository> repo) {
///
/// Returns list with name and email respectively.
List<String> identity(Pointer<git_repository> repo) {
final name = calloc<Pointer<Int8>>();
final email = calloc<Pointer<Int8>>();
libgit2.git_repository_ident(name, email, repo);
final identity = <String, String>{};
final identity = <String>[];
if (name.value == nullptr && email.value == nullptr) {
return identity;
} else {
identity[name.value.cast<Utf8>().toDartString()] =
email.value.cast<Utf8>().toDartString();
identity.add(name.value.cast<Utf8>().toDartString());
identity.add(email.value.cast<Utf8>().toDartString());
}
calloc.free(name);

View file

@ -272,9 +272,6 @@ class Reference {
/// Whether reference is a tag.
bool get isTag => bindings.isTag(_refPointer);
/// Repository where a reference resides.
Repository get owner => Repository(bindings.owner(_refPointer));
/// Compares two references.
bool equals(Reference other) {
return bindings.compare(

View file

@ -2,13 +2,14 @@ import 'dart:collection';
import 'dart:ffi';
import 'package:libgit2dart/libgit2dart.dart';
import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
import 'package:libgit2dart/src/bindings/reference.dart' as reference_bindings;
import 'package:libgit2dart/src/bindings/reflog.dart' as bindings;
class RefLog with IterableMixin<RefLogEntry> {
/// Initializes a new instance of [RefLog] class from provided [Reference].
RefLog(Reference ref) {
_reflogPointer = bindings.read(
repoPointer: ref.owner.pointer,
repoPointer: reference_bindings.owner(ref.pointer),
name: ref.name,
);
_finalizer.attach(this, _reflogPointer, detach: this);
@ -19,7 +20,10 @@ class RefLog with IterableMixin<RefLogEntry> {
/// Deletes the reflog for the given reference.
static void delete(Reference ref) {
bindings.delete(repoPointer: ref.owner.pointer, name: ref.name);
bindings.delete(
repoPointer: reference_bindings.owner(ref.pointer),
name: ref.name,
);
}
/// Renames a reflog.

View file

@ -17,13 +17,14 @@ class Repository {
/// Initializes a new instance of the [Repository] class from provided
/// pointer to repository object in memory.
///
/// **IMPORTANT**: Should be freed to release allocated memory.
///
/// Note: For internal use. Instead, use one of:
/// - [Repository.init]
/// - [Repository.open]
/// - [Repository.clone]
Repository(this._repoPointer);
Repository(Pointer<git_repository> pointer) {
_repoPointer = pointer;
_finalizer.attach(this, _repoPointer, detach: this);
}
/// Creates new git repository at the provided [path].
///
@ -55,8 +56,6 @@ class Repository {
/// [originUrl] if set, then after the rest of the repository initialization
/// is completed, an "origin" remote will be added pointing to this URL.
///
/// **IMPORTANT**: Should be freed to release allocated memory.
///
/// Throws a [LibGit2Error] if error occured.
Repository.init({
required String path,
@ -87,6 +86,8 @@ class Repository {
initialHead: initialHead,
originUrl: originUrl,
);
_finalizer.attach(this, _repoPointer, detach: this);
}
/// Opens repository at provided [path].
@ -95,13 +96,13 @@ class Repository {
/// or to the working directory. For a bare repository, [path] should directly
/// point to the repository folder.
///
/// **IMPORTANT**: Should be freed to release allocated memory.
///
/// Throws a [LibGit2Error] if error occured.
Repository.open(String path) {
libgit2.git_libgit2_init();
_repoPointer = bindings.open(path);
_finalizer.attach(this, _repoPointer, detach: this);
}
/// Clones a remote repository at provided [url] into [localPath].
@ -128,8 +129,6 @@ class Repository {
/// [callbacks] is the combination of callback functions from [Callbacks]
/// object.
///
/// **IMPORTANT**: Should be freed to release allocated memory.
///
/// Throws a [LibGit2Error] if error occured.
Repository.clone({
required String url,
@ -151,6 +150,8 @@ class Repository {
checkoutBranch: checkoutBranch,
callbacks: callbacks,
);
_finalizer.attach(this, _repoPointer, detach: this);
}
late final Pointer<git_repository> _repoPointer;
@ -294,9 +295,12 @@ class Repository {
}
/// Configured identity to use for reflogs.
///
/// Returns map with name as key and email as value.
Map<String, String> get identity => bindings.identity(_repoPointer);
Identity get identity {
final identity = bindings.identity(_repoPointer);
return identity.isNotEmpty
? Identity(name: identity[0], email: identity[1])
: const Identity(name: '', email: '');
}
/// Whether repository was a shallow clone.
bool get isShallow => bindings.isShallow(_repoPointer);
@ -364,7 +368,10 @@ class Repository {
}
/// Releases memory allocated for repository object.
void free() => bindings.free(_repoPointer);
void free() {
bindings.free(_repoPointer);
_finalizer.detach(this);
}
@override
String toString() {
@ -736,6 +743,12 @@ class Repository {
}
}
// coverage:ignore-start
final _finalizer = Finalizer<Pointer<git_repository>>(
(pointer) => bindings.free(pointer),
);
// coverage:ignore-end
class RepositoryCallback {
/// Values used to override the repository creation and customization process
/// during a clone operation.
@ -807,3 +820,11 @@ class RepositoryCallback {
/// initialization is completed.
final String? originUrl;
}
class Identity {
/// Identity to use for reflogs.
const Identity({required this.name, required this.email});
final String name;
final String email;
}

View file

@ -119,9 +119,6 @@ class Submodule {
/// This will only work if the submodule is checked out into the working
/// directory.
///
/// **IMPORTANT**: Returned [Repository] object should be freed to release
/// allocated memory.
///
/// Throws a [LibGit2Error] if error occured.
Repository open() {
return Repository(bindings.open(_submodulePointer));