feat(repository): add ability to pass callbacks for remote and repository creation during clone

This commit is contained in:
Aleksey Kulikov 2021-09-27 11:19:00 +03:00
parent b1f112a30d
commit 6d48ae742c
4 changed files with 161 additions and 6 deletions

View file

@ -1,6 +1,8 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import '../error.dart';
import '../remote.dart';
import '../repository.dart';
import 'libgit2_bindings.dart';
import '../util.dart';
@ -135,6 +137,8 @@ Pointer<git_repository> clone(
String url,
String localPath,
bool bare,
Remote Function(Repository, String, String)? remote,
Repository Function(String, bool)? repository,
String checkoutBranch,
) {
final out = calloc<Pointer<git_repository>>();
@ -143,6 +147,7 @@ Pointer<git_repository> clone(
final checkoutBranchC = checkoutBranch.isEmpty
? nullptr
: checkoutBranch.toNativeUtf8().cast<Int8>();
final cloneOptions = calloc<git_clone_options>();
final cloneOptionsError =
libgit2.git_clone_options_init(cloneOptions, GIT_CLONE_OPTIONS_VERSION);
@ -159,8 +164,24 @@ Pointer<git_repository> clone(
throw LibGit2Error(libgit2.git_error_last());
}
const except = -1;
git_remote_create_cb remoteCb = nullptr;
if (remote != null) {
_remoteFunction = remote;
remoteCb = Pointer.fromFunction(_remoteCb, except);
}
git_repository_create_cb repositoryCb = nullptr;
if (repository != null) {
_repositoryFunction = repository;
repositoryCb = Pointer.fromFunction(_repositoryCb, except);
}
cloneOptions.ref.bare = bare ? 1 : 0;
cloneOptions.ref.remote_cb = remoteCb;
cloneOptions.ref.checkout_branch = checkoutBranchC;
cloneOptions.ref.repository_cb = repositoryCb;
cloneOptions.ref.fetch_opts = fetchOptions.ref;
final error = libgit2.git_clone(out, urlC, localPathC, cloneOptions);
@ -170,6 +191,8 @@ Pointer<git_repository> clone(
calloc.free(checkoutBranchC);
calloc.free(cloneOptions);
calloc.free(fetchOptions);
_remoteFunction = null;
_repositoryFunction = null;
if (error < 0) {
throw LibGit2Error(libgit2.git_error_last());
@ -178,6 +201,47 @@ Pointer<git_repository> clone(
}
}
/// A function matching the `Remote Function(Repository repo, String name, String url)` signature
/// to override the remote creation and customization process during a clone operation.
Remote Function(Repository, String, String)? _remoteFunction;
/// A callback used to create the git remote, prior to its being used to perform
/// the clone operation.
int _remoteCb(
Pointer<Pointer<git_remote>> remote,
Pointer<git_repository> repo,
Pointer<Int8> name,
Pointer<Int8> url,
Pointer<Void> payload,
) {
remote[0] = _remoteFunction!(
Repository(repo),
name.cast<Utf8>().toDartString(),
url.cast<Utf8>().toDartString(),
).pointer;
return 0;
}
/// A function matching the `Repository Function(String path, bool bare)` signature to override
/// the repository creation and customization process during a clone operation.
Repository Function(String, bool)? _repositoryFunction;
/// A callback used to create the new repository into which to clone.
int _repositoryCb(
Pointer<Pointer<git_repository>> repo,
Pointer<Int8> path,
int bare,
Pointer<Void> payload,
) {
repo[0] = _repositoryFunction!(
path.cast<Utf8>().toDartString(),
bare == 1 ? true : false,
).pointer;
return 0;
}
/// Returns the path to the `.git` folder for normal repositories or the
/// repository itself for bare repositories.
String path(Pointer<git_repository> repo) {