feat(repository): add ability to pass credentials in callbacks argument

This commit is contained in:
Aleksey Kulikov 2021-09-29 18:54:29 +03:00
parent 299d1a17e7
commit 4c7a096fe3
31 changed files with 1340 additions and 308 deletions

View file

@ -20,5 +20,7 @@ export 'src/stash.dart';
export 'src/remote.dart'; export 'src/remote.dart';
export 'src/refspec.dart'; export 'src/refspec.dart';
export 'src/callbacks.dart'; export 'src/callbacks.dart';
export 'src/credentials.dart';
export 'src/features.dart';
export 'src/error.dart'; export 'src/error.dart';
export 'src/git_types.dart'; export 'src/git_types.dart';

View file

@ -0,0 +1,135 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import '../error.dart';
import '../util.dart';
import 'libgit2_bindings.dart';
/// Create a credential to specify a username.
///
/// This is used with ssh authentication to query for the username if none is
/// specified in the url.
///
/// Throws a [LibGit2Error] if error occured.
Pointer<git_credential> username(String username) {
final out = calloc<Pointer<git_credential>>();
final usernameC = username.toNativeUtf8().cast<Int8>();
final error = libgit2.git_credential_username_new(out, usernameC);
calloc.free(usernameC);
if (error < 0) {
throw LibGit2Error(libgit2.git_error_last());
} else {
return out.value;
}
}
/// Create a new plain-text username and password credential object.
///
/// Throws a [LibGit2Error] if error occured.
Pointer<git_credential> userPass(String username, String password) {
final out = calloc<Pointer<git_credential>>();
final usernameC = username.toNativeUtf8().cast<Int8>();
final passwordC = password.toNativeUtf8().cast<Int8>();
final error =
libgit2.git_credential_userpass_plaintext_new(out, usernameC, passwordC);
calloc.free(usernameC);
calloc.free(passwordC);
if (error < 0) {
throw LibGit2Error(libgit2.git_error_last());
} else {
return out.value;
}
}
/// Create a new passphrase-protected ssh key credential object.
///
/// Throws a [LibGit2Error] if error occured.
Pointer<git_credential> sshKey(
String username,
String publicKey,
String privateKey,
String passPhrase,
) {
final out = calloc<Pointer<git_credential>>();
final usernameC = username.toNativeUtf8().cast<Int8>();
final publicKeyC = publicKey.toNativeUtf8().cast<Int8>();
final privateKeyC = privateKey.toNativeUtf8().cast<Int8>();
final passPhraseC = passPhrase.toNativeUtf8().cast<Int8>();
final error = libgit2.git_credential_ssh_key_new(
out,
usernameC,
publicKeyC,
privateKeyC,
passPhraseC,
);
calloc.free(usernameC);
calloc.free(publicKeyC);
calloc.free(privateKeyC);
calloc.free(passPhraseC);
if (error < 0) {
throw LibGit2Error(libgit2.git_error_last());
} else {
return out.value;
}
}
/// Create a new ssh key credential object used for querying an ssh-agent.
///
/// Throws a [LibGit2Error] if error occured.
Pointer<git_credential> sshKeyFromAgent(String username) {
final out = calloc<Pointer<git_credential>>();
final usernameC = username.toNativeUtf8().cast<Int8>();
final error = libgit2.git_credential_ssh_key_from_agent(out, usernameC);
calloc.free(usernameC);
if (error < 0) {
throw LibGit2Error(libgit2.git_error_last());
} else {
return out.value;
}
}
/// Create a new ssh key credential object reading the keys from memory.
///
/// Throws a [LibGit2Error] if error occured.
Pointer<git_credential> sshKeyFromMemory(
String username,
String publicKey,
String privateKey,
String passPhrase,
) {
final out = calloc<Pointer<git_credential>>();
final usernameC = username.toNativeUtf8().cast<Int8>();
final publicKeyC = publicKey.toNativeUtf8().cast<Int8>();
final privateKeyC = privateKey.toNativeUtf8().cast<Int8>();
final passPhraseC = passPhrase.toNativeUtf8().cast<Int8>();
final error = libgit2.git_credential_ssh_key_memory_new(
out,
usernameC,
publicKeyC,
privateKeyC,
passPhraseC,
);
calloc.free(usernameC);
calloc.free(publicKeyC);
calloc.free(privateKeyC);
calloc.free(passPhraseC);
if (error < 0) {
throw LibGit2Error(libgit2.git_error_last());
} else {
return out.value;
}
}

View file

@ -2447,6 +2447,22 @@ class Libgit2 {
/// > Override the default priority of the loose ODB backend which /// > Override the default priority of the loose ODB backend which
/// > is added when default backends are assigned to a repository /// > is added when default backends are assigned to a repository
/// ///
/// opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out)
/// > Returns the list of git extensions that are supported. This
/// > is the list of built-in extensions supported by libgit2 and
/// > custom extensions that have been added with
/// > `GIT_OPT_SET_EXTENSIONS`. Extensions that have been negated
/// > will not be returned. The returned list should be released
/// > with `git_strarray_dispose`.
///
/// opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len)
/// > Set that the given git extensions are supported by the caller.
/// > Extensions supported by libgit2 may be negated by prefixing
/// > them with a `!`. For example: setting extensions to
/// > { "!noop", "newext" } indicates that the caller does not want
/// > to support repositories with the `noop` extension but does want
/// > to support repositories with the `newext` extension.
///
/// @param option Option key /// @param option Option key
/// @param ... value to set the option /// @param ... value to set the option
/// @return 0 on success, <0 on failure /// @return 0 on success, <0 on failure
@ -3990,13 +4006,15 @@ class Libgit2 {
/// ///
/// @param out Output value of calculated SHA /// @param out Output value of calculated SHA
/// @param repo Repository pointer /// @param repo Repository pointer
/// @param path Path to file on disk whose contents should be hashed. If the /// @param path Path to file on disk whose contents should be hashed. This
/// repository is not NULL, this can be a relative path. /// may be an absolute path or a relative path, in which case it
/// will be treated as a path within the working directory.
/// @param type The object type to hash as (e.g. GIT_OBJECT_BLOB) /// @param type The object type to hash as (e.g. GIT_OBJECT_BLOB)
/// @param as_path The path to use to look up filtering rules. If this is /// @param as_path The path to use to look up filtering rules. If this is
/// NULL, then the `path` parameter will be used instead. If /// an empty string then no filters will be applied when
/// this is passed as the empty string, then no filters will be /// calculating the hash. If this is `NULL` and the `path`
/// applied when calculating the hash. /// parameter is a file within the repository's working
/// directory, then the `path` will be used.
/// @return 0 on success, or an error code /// @return 0 on success, or an error code
int git_repository_hashfile( int git_repository_hashfile(
ffi.Pointer<git_oid> out, ffi.Pointer<git_oid> out,
@ -8083,112 +8101,6 @@ class Libgit2 {
late final _git_diff_stats_free = _git_diff_stats_freePtr late final _git_diff_stats_free = _git_diff_stats_freePtr
.asFunction<void Function(ffi.Pointer<git_diff_stats>)>(); .asFunction<void Function(ffi.Pointer<git_diff_stats>)>();
/// Create an e-mail ready patch from a diff.
///
/// @param out buffer to store the e-mail patch in
/// @param diff containing the commit
/// @param opts structure with options to influence content and formatting.
/// @return 0 or an error code
int git_diff_format_email(
ffi.Pointer<git_buf> out,
ffi.Pointer<git_diff> diff,
ffi.Pointer<git_diff_format_email_options> opts,
) {
return _git_diff_format_email(
out,
diff,
opts,
);
}
late final _git_diff_format_emailPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(ffi.Pointer<git_buf>, ffi.Pointer<git_diff>,
ffi.Pointer<git_diff_format_email_options>)>>(
'git_diff_format_email');
late final _git_diff_format_email = _git_diff_format_emailPtr.asFunction<
int Function(ffi.Pointer<git_buf>, ffi.Pointer<git_diff>,
ffi.Pointer<git_diff_format_email_options>)>();
/// Create an e-mail ready patch for a commit.
///
/// Does not support creating patches for merge commits (yet).
///
/// @param out buffer to store the e-mail patch in
/// @param repo containing the commit
/// @param commit pointer to up commit
/// @param patch_no patch number of the commit
/// @param total_patches total number of patches in the patch set
/// @param flags determines the formatting of the e-mail
/// @param diff_opts structure with options to influence diff or NULL for defaults.
/// @return 0 or an error code
int git_diff_commit_as_email(
ffi.Pointer<git_buf> out,
ffi.Pointer<git_repository> repo,
ffi.Pointer<git_commit> commit,
int patch_no,
int total_patches,
int flags,
ffi.Pointer<git_diff_options> diff_opts,
) {
return _git_diff_commit_as_email(
out,
repo,
commit,
patch_no,
total_patches,
flags,
diff_opts,
);
}
late final _git_diff_commit_as_emailPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(
ffi.Pointer<git_buf>,
ffi.Pointer<git_repository>,
ffi.Pointer<git_commit>,
size_t,
size_t,
ffi.Uint32,
ffi.Pointer<git_diff_options>)>>('git_diff_commit_as_email');
late final _git_diff_commit_as_email =
_git_diff_commit_as_emailPtr.asFunction<
int Function(
ffi.Pointer<git_buf>,
ffi.Pointer<git_repository>,
ffi.Pointer<git_commit>,
int,
int,
int,
ffi.Pointer<git_diff_options>)>();
/// Initialize git_diff_format_email_options structure
///
/// Initializes a `git_diff_format_email_options` with default values. Equivalent
/// to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
///
/// @param opts The `git_blame_options` struct to initialize.
/// @param version The struct version; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`.
/// @return Zero on success; -1 on failure.
int git_diff_format_email_options_init(
ffi.Pointer<git_diff_format_email_options> opts,
int version,
) {
return _git_diff_format_email_options_init(
opts,
version,
);
}
late final _git_diff_format_email_options_initPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(ffi.Pointer<git_diff_format_email_options>,
ffi.Uint32)>>('git_diff_format_email_options_init');
late final _git_diff_format_email_options_init =
_git_diff_format_email_options_initPtr.asFunction<
int Function(ffi.Pointer<git_diff_format_email_options>, int)>();
/// Initialize git_diff_patchid_options structure /// Initialize git_diff_patchid_options structure
/// ///
/// Initializes a `git_diff_patchid_options` with default values. Equivalent to /// Initializes a `git_diff_patchid_options` with default values. Equivalent to
@ -10006,29 +9918,26 @@ class Libgit2 {
int Function(ffi.Pointer<git_repository>, ffi.Pointer<git_object>, int Function(ffi.Pointer<git_repository>, ffi.Pointer<git_object>,
ffi.Pointer<git_checkout_options>)>(); ffi.Pointer<git_checkout_options>)>();
/// Free the OID array /// Free the object IDs contained in an oid_array. This method should
/// /// be called on `git_oidarray` objects that were provided by the
/// This method must (and must only) be called on `git_oidarray` /// library. Not doing so will result in a memory leak.
/// objects where the array is allocated by the library. Not doing so,
/// will result in a memory leak.
/// ///
/// This does not free the `git_oidarray` itself, since the library will /// This does not free the `git_oidarray` itself, since the library will
/// never allocate that object directly itself (it is more commonly embedded /// never allocate that object directly itself.
/// inside another struct or created on the stack).
/// ///
/// @param array git_oidarray from which to free oid data /// @param array git_oidarray from which to free oid data
void git_oidarray_free( void git_oidarray_dispose(
ffi.Pointer<git_oidarray> array, ffi.Pointer<git_oidarray> array,
) { ) {
return _git_oidarray_free( return _git_oidarray_dispose(
array, array,
); );
} }
late final _git_oidarray_freePtr = late final _git_oidarray_disposePtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<git_oidarray>)>>( _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<git_oidarray>)>>(
'git_oidarray_free'); 'git_oidarray_dispose');
late final _git_oidarray_free = _git_oidarray_freePtr late final _git_oidarray_dispose = _git_oidarray_disposePtr
.asFunction<void Function(ffi.Pointer<git_oidarray>)>(); .asFunction<void Function(ffi.Pointer<git_oidarray>)>();
/// Initializes a `git_indexer_options` with default values. Equivalent to /// Initializes a `git_indexer_options` with default values. Equivalent to
@ -19948,6 +19857,102 @@ class Libgit2 {
late final _git_buf_free = late final _git_buf_free =
_git_buf_freePtr.asFunction<void Function(ffi.Pointer<git_buf>)>(); _git_buf_freePtr.asFunction<void Function(ffi.Pointer<git_buf>)>();
/// Create an e-mail ready patch from a diff.
///
/// @deprecated git_email_create_from_diff
/// @see git_email_create_from_diff
int git_diff_format_email(
ffi.Pointer<git_buf> out,
ffi.Pointer<git_diff> diff,
ffi.Pointer<git_diff_format_email_options> opts,
) {
return _git_diff_format_email(
out,
diff,
opts,
);
}
late final _git_diff_format_emailPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(ffi.Pointer<git_buf>, ffi.Pointer<git_diff>,
ffi.Pointer<git_diff_format_email_options>)>>(
'git_diff_format_email');
late final _git_diff_format_email = _git_diff_format_emailPtr.asFunction<
int Function(ffi.Pointer<git_buf>, ffi.Pointer<git_diff>,
ffi.Pointer<git_diff_format_email_options>)>();
/// Create an e-mail ready patch for a commit.
///
/// @deprecated git_email_create_from_commit
/// @see git_email_create_from_commit
int git_diff_commit_as_email(
ffi.Pointer<git_buf> out,
ffi.Pointer<git_repository> repo,
ffi.Pointer<git_commit> commit,
int patch_no,
int total_patches,
int flags,
ffi.Pointer<git_diff_options> diff_opts,
) {
return _git_diff_commit_as_email(
out,
repo,
commit,
patch_no,
total_patches,
flags,
diff_opts,
);
}
late final _git_diff_commit_as_emailPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(
ffi.Pointer<git_buf>,
ffi.Pointer<git_repository>,
ffi.Pointer<git_commit>,
size_t,
size_t,
ffi.Uint32,
ffi.Pointer<git_diff_options>)>>('git_diff_commit_as_email');
late final _git_diff_commit_as_email =
_git_diff_commit_as_emailPtr.asFunction<
int Function(
ffi.Pointer<git_buf>,
ffi.Pointer<git_repository>,
ffi.Pointer<git_commit>,
int,
int,
int,
ffi.Pointer<git_diff_options>)>();
/// Initialize git_diff_format_email_options structure
///
/// Initializes a `git_diff_format_email_options` with default values. Equivalent
/// to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
///
/// @param opts The `git_blame_options` struct to initialize.
/// @param version The struct version; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`.
/// @return Zero on success; -1 on failure.
int git_diff_format_email_options_init(
ffi.Pointer<git_diff_format_email_options> opts,
int version,
) {
return _git_diff_format_email_options_init(
opts,
version,
);
}
late final _git_diff_format_email_options_initPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(ffi.Pointer<git_diff_format_email_options>,
ffi.Uint32)>>('git_diff_format_email_options_init');
late final _git_diff_format_email_options_init =
_git_diff_format_email_options_initPtr.asFunction<
int Function(ffi.Pointer<git_diff_format_email_options>, int)>();
/// Return the last `git_error` object that was generated for the /// Return the last `git_error` object that was generated for the
/// current thread. This is an alias of `git_error_last` and is /// current thread. This is an alias of `git_error_last` and is
/// preserved for backward compatibility. /// preserved for backward compatibility.
@ -20446,6 +20451,28 @@ class Libgit2 {
late final _git_oid_iszero = late final _git_oid_iszero =
_git_oid_iszeroPtr.asFunction<int Function(ffi.Pointer<git_oid>)>(); _git_oid_iszeroPtr.asFunction<int Function(ffi.Pointer<git_oid>)>();
/// Free the memory referred to by the git_oidarray. This is an alias of
/// `git_oidarray_dispose` and is preserved for backward compatibility.
///
/// This function is deprecated, but there is no plan to remove this
/// function at this time.
///
/// @deprecated Use git_oidarray_dispose
/// @see git_oidarray_dispose
void git_oidarray_free(
ffi.Pointer<git_oidarray> array,
) {
return _git_oidarray_free(
array,
);
}
late final _git_oidarray_freePtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<git_oidarray>)>>(
'git_oidarray_free');
late final _git_oidarray_free = _git_oidarray_freePtr
.asFunction<void Function(ffi.Pointer<git_oidarray>)>();
/// Free the memory referred to by the git_strarray. This is an alias of /// Free the memory referred to by the git_strarray. This is an alias of
/// `git_strarray_dispose` and is preserved for backward compatibility. /// `git_strarray_dispose` and is preserved for backward compatibility.
/// ///
@ -20925,6 +20952,95 @@ class Libgit2 {
_git_worktree_prune_init_optionsPtr.asFunction< _git_worktree_prune_init_optionsPtr.asFunction<
int Function(ffi.Pointer<git_worktree_prune_options>, int)>(); int Function(ffi.Pointer<git_worktree_prune_options>, int)>();
/// Create a diff for a commit in mbox format for sending via email.
///
/// @param out buffer to store the e-mail patch in
/// @param diff the changes to include in the email
/// @param patch_idx the patch index
/// @param patch_count the total number of patches that will be included
/// @param commit_id the commit id for this change
/// @param summary the commit message for this change
/// @param body optional text to include above the diffstat
/// @param author the person who authored this commit
/// @param opts email creation options
int git_email_create_from_diff(
ffi.Pointer<git_buf> out,
ffi.Pointer<git_diff> diff,
int patch_idx,
int patch_count,
ffi.Pointer<git_oid> commit_id,
ffi.Pointer<ffi.Int8> summary,
ffi.Pointer<ffi.Int8> body,
ffi.Pointer<git_signature> author,
ffi.Pointer<git_email_create_options> opts,
) {
return _git_email_create_from_diff(
out,
diff,
patch_idx,
patch_count,
commit_id,
summary,
body,
author,
opts,
);
}
late final _git_email_create_from_diffPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(
ffi.Pointer<git_buf>,
ffi.Pointer<git_diff>,
size_t,
size_t,
ffi.Pointer<git_oid>,
ffi.Pointer<ffi.Int8>,
ffi.Pointer<ffi.Int8>,
ffi.Pointer<git_signature>,
ffi.Pointer<git_email_create_options>)>>(
'git_email_create_from_diff');
late final _git_email_create_from_diff =
_git_email_create_from_diffPtr.asFunction<
int Function(
ffi.Pointer<git_buf>,
ffi.Pointer<git_diff>,
int,
int,
ffi.Pointer<git_oid>,
ffi.Pointer<ffi.Int8>,
ffi.Pointer<ffi.Int8>,
ffi.Pointer<git_signature>,
ffi.Pointer<git_email_create_options>)>();
/// Create a diff for a commit in mbox format for sending via email.
/// The commit must not be a merge commit.
///
/// @param out buffer to store the e-mail patch in
/// @param commit commit to create a patch for
/// @param opts email creation options
int git_email_create_from_commit(
ffi.Pointer<git_buf> out,
ffi.Pointer<git_commit> commit,
ffi.Pointer<git_email_create_options> opts,
) {
return _git_email_create_from_commit(
out,
commit,
opts,
);
}
late final _git_email_create_from_commitPtr = _lookup<
ffi.NativeFunction<
ffi.Int32 Function(ffi.Pointer<git_buf>, ffi.Pointer<git_commit>,
ffi.Pointer<git_email_create_options>)>>(
'git_email_create_from_commit');
late final _git_email_create_from_commit =
_git_email_create_from_commitPtr.asFunction<
int Function(ffi.Pointer<git_buf>, ffi.Pointer<git_commit>,
ffi.Pointer<git_email_create_options>)>();
/// Init the global state /// Init the global state
/// ///
/// This function must be called before any other libgit2 function in /// This function must be called before any other libgit2 function in
@ -26449,6 +26565,8 @@ abstract class git_libgit2_opt_t {
static const int GIT_OPT_SET_MWINDOW_FILE_LIMIT = 30; static const int GIT_OPT_SET_MWINDOW_FILE_LIMIT = 30;
static const int GIT_OPT_SET_ODB_PACKED_PRIORITY = 31; static const int GIT_OPT_SET_ODB_PACKED_PRIORITY = 31;
static const int GIT_OPT_SET_ODB_LOOSE_PRIORITY = 32; static const int GIT_OPT_SET_ODB_LOOSE_PRIORITY = 32;
static const int GIT_OPT_GET_EXTENSIONS = 33;
static const int GIT_OPT_SET_EXTENSIONS = 34;
} }
/// A data buffer for exporting data from libgit2 /// A data buffer for exporting data from libgit2
@ -27607,6 +27725,9 @@ abstract class git_diff_option_t {
/// diff hunks. /// diff hunks.
static const int GIT_DIFF_INDENT_HEURISTIC = 262144; static const int GIT_DIFF_INDENT_HEURISTIC = 262144;
/// Ignore blank lines
static const int GIT_DIFF_IGNORE_BLANK_LINES = 524288;
/// Treat all files as text, disabling binary attributes & detection /// Treat all files as text, disabling binary attributes & detection
static const int GIT_DIFF_FORCE_TEXT = 1048576; static const int GIT_DIFF_FORCE_TEXT = 1048576;
@ -27643,9 +27764,6 @@ abstract class git_diff_option_t {
/// Include the necessary deflate / delta information so that `git-apply` /// Include the necessary deflate / delta information so that `git-apply`
/// can apply given diff information to binary files. /// can apply given diff information to binary files.
static const int GIT_DIFF_SHOW_BINARY = 1073741824; static const int GIT_DIFF_SHOW_BINARY = 1073741824;
/// Ignore blank lines
static const int GIT_DIFF_IGNORE_BLANK_LINES = -2147483648;
} }
class git_diff extends ffi.Opaque {} class git_diff extends ffi.Opaque {}
@ -28298,45 +28416,6 @@ abstract class git_diff_stats_format_t {
static const int GIT_DIFF_STATS_INCLUDE_SUMMARY = 8; static const int GIT_DIFF_STATS_INCLUDE_SUMMARY = 8;
} }
/// Formatting options for diff e-mail generation
abstract class git_diff_format_email_flags_t {
/// Normal patch, the default
static const int GIT_DIFF_FORMAT_EMAIL_NONE = 0;
/// Don't insert "[PATCH]" in the subject header
static const int GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = 1;
}
/// Options for controlling the formatting of the generated e-mail.
class git_diff_format_email_options extends ffi.Struct {
@ffi.Uint32()
external int version;
/// see `git_diff_format_email_flags_t` above
@ffi.Uint32()
external int flags;
/// This patch number
@size_t()
external int patch_no;
/// Total number of patches in this series
@size_t()
external int total_patches;
/// id to use for the commit
external ffi.Pointer<git_oid> id;
/// Summary of the change
external ffi.Pointer<ffi.Int8> summary;
/// Commit message's body
external ffi.Pointer<ffi.Int8> body;
/// Author of the change
external ffi.Pointer<git_signature> author;
}
/// Patch ID options structure /// Patch ID options structure
/// ///
/// Initialize with `GIT_PATCHID_OPTIONS_INIT`. Alternatively, you can /// Initialize with `GIT_PATCHID_OPTIONS_INIT`. Alternatively, you can
@ -28446,9 +28525,11 @@ class git_attr_options extends ffi.Struct {
@ffi.Uint32() @ffi.Uint32()
external int flags; external int flags;
external ffi.Pointer<git_oid> commit_id;
/// The commit to load attributes from, when /// The commit to load attributes from, when
/// `GIT_ATTR_CHECK_INCLUDE_COMMIT` is specified. /// `GIT_ATTR_CHECK_INCLUDE_COMMIT` is specified.
external ffi.Pointer<git_oid> commit_id; external git_oid attr_commit_id;
} }
/// The callback used with git_attr_foreach. /// The callback used with git_attr_foreach.
@ -28500,9 +28581,11 @@ class git_blob_filter_options extends ffi.Struct {
@ffi.Uint32() @ffi.Uint32()
external int flags; external int flags;
external ffi.Pointer<git_oid> commit_id;
/// The commit to load attributes from, when /// The commit to load attributes from, when
/// `GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT` is specified. /// `GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
external ffi.Pointer<git_oid> commit_id; external git_oid attr_commit_id;
} }
/// Flags for indicating option behavior for git_blame APIs. /// Flags for indicating option behavior for git_blame APIs.
@ -30208,9 +30291,11 @@ class git_filter_options extends ffi.Struct {
@ffi.Uint32() @ffi.Uint32()
external int flags; external int flags;
external ffi.Pointer<git_oid> commit_id;
/// The commit to load attributes from, when /// The commit to load attributes from, when
/// `GIT_FILTER_ATTRIBUTES_FROM_COMMIT` is specified. /// `GIT_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
external ffi.Pointer<git_oid> commit_id; external git_oid attr_commit_id;
} }
class git_filter extends ffi.Opaque {} class git_filter extends ffi.Opaque {}
@ -30872,6 +30957,92 @@ class git_credential_userpass_payload extends ffi.Struct {
external ffi.Pointer<ffi.Int8> password; external ffi.Pointer<ffi.Int8> password;
} }
/// Formatting options for diff e-mail generation
abstract class git_diff_format_email_flags_t {
/// Normal patch, the default
static const int GIT_DIFF_FORMAT_EMAIL_NONE = 0;
/// Don't insert "[PATCH]" in the subject header
static const int GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = 1;
}
/// Options for controlling the formatting of the generated e-mail.
class git_diff_format_email_options extends ffi.Struct {
@ffi.Uint32()
external int version;
/// see `git_diff_format_email_flags_t` above
@ffi.Uint32()
external int flags;
/// This patch number
@size_t()
external int patch_no;
/// Total number of patches in this series
@size_t()
external int total_patches;
/// id to use for the commit
external ffi.Pointer<git_oid> id;
/// Summary of the change
external ffi.Pointer<ffi.Int8> summary;
/// Commit message's body
external ffi.Pointer<ffi.Int8> body;
/// Author of the change
external ffi.Pointer<git_signature> author;
}
/// Formatting options for diff e-mail generation
abstract class git_email_create_flags_t {
/// Normal patch, the default
static const int GIT_EMAIL_CREATE_DEFAULT = 0;
/// Do not include patch numbers in the subject prefix.
static const int GIT_EMAIL_CREATE_OMIT_NUMBERS = 1;
/// Include numbers in the subject prefix even when the
/// patch is for a single commit (1/1).
static const int GIT_EMAIL_CREATE_ALWAYS_NUMBER = 2;
/// Do not perform rename or similarity detection.
static const int GIT_EMAIL_CREATE_NO_RENAMES = 4;
}
/// Options for controlling the formatting of the generated e-mail.
class git_email_create_options extends ffi.Struct {
@ffi.Uint32()
external int version;
/// see `git_email_create_flags_t` above
@ffi.Uint32()
external int flags;
/// Options to use when creating diffs
external git_diff_options diff_opts;
/// Options for finding similarities within diffs
external git_diff_find_options diff_find_opts;
/// The subject prefix, by default "PATCH". If set to an empty
/// string ("") then only the patch numbers will be shown in the
/// prefix. If the subject_prefix is empty and patch numbers
/// are not being shown, the prefix will be omitted entirely.
external ffi.Pointer<ffi.Int8> subject_prefix;
/// The starting patch number; this cannot be 0. By default,
/// this is 1.
@size_t()
external int start_number;
/// The "re-roll" number. By default, there is no re-roll.
@size_t()
external int reroll_number;
}
/// Represents a single git message trailer. /// Represents a single git message trailer.
class git_message_trailer extends ffi.Struct { class git_message_trailer extends ffi.Struct {
external ffi.Pointer<ffi.Int8> key; external ffi.Pointer<ffi.Int8> key;
@ -31791,8 +31962,6 @@ const int GIT_DIFF_HUNK_HEADER_SIZE = 128;
const int GIT_DIFF_FIND_OPTIONS_VERSION = 1; const int GIT_DIFF_FIND_OPTIONS_VERSION = 1;
const int GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION = 1;
const int GIT_DIFF_PATCHID_OPTIONS_VERSION = 1; const int GIT_DIFF_PATCHID_OPTIONS_VERSION = 1;
const int GIT_APPLY_OPTIONS_VERSION = 1; const int GIT_APPLY_OPTIONS_VERSION = 1;
@ -31901,6 +32070,8 @@ const int GIT_CVAR_INT32 = 2;
const int GIT_CVAR_STRING = 3; const int GIT_CVAR_STRING = 3;
const int GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION = 1;
const int GITERR_NONE = 0; const int GITERR_NONE = 0;
const int GITERR_NOMEMORY = 1; const int GITERR_NOMEMORY = 1;
@ -32071,14 +32242,16 @@ const int GIT_CREDTYPE_USERNAME = 32;
const int GIT_CREDTYPE_SSH_MEMORY = 64; const int GIT_CREDTYPE_SSH_MEMORY = 64;
const String LIBGIT2_VERSION = '1.2.0'; const int GIT_EMAIL_CREATE_OPTIONS_VERSION = 1;
const String LIBGIT2_VERSION = '1.3.0';
const int LIBGIT2_VER_MAJOR = 1; const int LIBGIT2_VER_MAJOR = 1;
const int LIBGIT2_VER_MINOR = 2; const int LIBGIT2_VER_MINOR = 3;
const int LIBGIT2_VER_REVISION = 0; const int LIBGIT2_VER_REVISION = 0;
const int LIBGIT2_VER_PATCH = 0; const int LIBGIT2_VER_PATCH = 0;
const String LIBGIT2_SOVERSION = '1.2'; const String LIBGIT2_SOVERSION = '1.3';

View file

@ -1,10 +1,13 @@
import 'dart:ffi'; import 'dart:ffi';
import 'package:ffi/ffi.dart'; import 'package:ffi/ffi.dart';
import 'package:libgit2dart/libgit2dart.dart';
import '../credentials.dart';
import '../callbacks.dart'; import '../callbacks.dart';
import '../repository.dart'; import '../repository.dart';
import 'libgit2_bindings.dart';
import '../oid.dart'; import '../oid.dart';
import '../remote.dart'; import '../remote.dart';
import 'libgit2_bindings.dart';
import 'credentials.dart' as credentials_bindings;
class RemoteCallbacks { class RemoteCallbacks {
/// Callback function that reports transfer progress. /// Callback function that reports transfer progress.
@ -105,6 +108,56 @@ class RemoteCallbacks {
return 0; return 0;
} }
/// [Credentials] object used for authentication in order to connect to remote.
static Credentials? credentials;
/// Credential acquisition callback that will be called if the remote host requires
/// authentication in order to connect to it.
static int credentialsCb(
Pointer<Pointer<git_credential>> credPointer,
Pointer<Int8> url,
Pointer<Int8> username,
int allowedTypes,
Pointer<Void> payload,
) {
final credentialType = credentials!.credentialType;
if (allowedTypes & credentialType.value != credentialType.value) {
throw ArgumentError('Invalid credential type $credentialType');
}
if (credentials is Username) {
final cred = credentials as Username;
credPointer[0] = credentials_bindings.username(cred.username);
} else if (credentials is UserPass) {
final cred = credentials as UserPass;
credPointer[0] = credentials_bindings.userPass(
cred.username,
cred.password,
);
} else if (credentials is Keypair) {
final cred = credentials as Keypair;
credPointer[0] = credentials_bindings.sshKey(
cred.username,
cred.pubKey,
cred.privateKey,
cred.passPhrase,
);
} else if (credentials is KeypairFromAgent) {
final cred = credentials as KeypairFromAgent;
credPointer[0] = credentials_bindings.sshKeyFromAgent(cred.username);
} else if (credentials is KeypairFromMemory) {
final cred = credentials as KeypairFromMemory;
credPointer[0] = credentials_bindings.sshKeyFromMemory(
cred.username,
cred.pubKey,
cred.privateKey,
cred.passPhrase,
);
}
return 0;
}
/// Plugs provided callbacks into libgit2 callbacks. /// Plugs provided callbacks into libgit2 callbacks.
static void plug({ static void plug({
required git_remote_callbacks callbacksOptions, required git_remote_callbacks callbacksOptions,
@ -143,6 +196,14 @@ class RemoteCallbacks {
except, except,
); );
} }
if (callbacks.credentials != null) {
credentials = callbacks.credentials;
callbacksOptions.credentials = Pointer.fromFunction(
credentialsCb,
except,
);
}
} }
/// Resets callback functions to their original null values. /// Resets callback functions to their original null values.
@ -153,5 +214,6 @@ class RemoteCallbacks {
pushUpdateReference = null; pushUpdateReference = null;
remoteFunction = null; remoteFunction = null;
repositoryFunction = null; repositoryFunction = null;
credentials = null;
} }
} }

View file

@ -1,14 +1,19 @@
import 'credentials.dart';
import 'oid.dart'; import 'oid.dart';
import 'remote.dart'; import 'remote.dart';
class Callbacks { class Callbacks {
const Callbacks({ const Callbacks({
this.credentials,
this.transferProgress, this.transferProgress,
this.sidebandProgress, this.sidebandProgress,
this.updateTips, this.updateTips,
this.pushUpdateReference, this.pushUpdateReference,
}); });
/// Credentials used for authentication.
final Credentials? credentials;
/// Callback function that reports transfer progress. /// Callback function that reports transfer progress.
final void Function(TransferProgress)? transferProgress; final void Function(TransferProgress)? transferProgress;

92
lib/src/credentials.dart Normal file
View file

@ -0,0 +1,92 @@
import 'package:libgit2dart/src/git_types.dart';
abstract class Credentials {
/// Returns type of authentication method.
GitCredential get credentialType;
}
/// Credential with specific username.
class Username implements Credentials {
const Username(this.username);
/// The username to authenticate with.
final String username;
@override
GitCredential get credentialType => GitCredential.username;
}
/// Plain-text username and password credential.
class UserPass implements Credentials {
const UserPass({required this.username, required this.password});
/// The username to authenticate with.
final String username;
/// The password of the credential.
final String password;
@override
GitCredential get credentialType => GitCredential.userPassPlainText;
}
/// Passphrase-protected ssh key credential.
class Keypair implements Credentials {
const Keypair({
required this.username,
required this.pubKey,
required this.privateKey,
required this.passPhrase,
});
/// The username to authenticate with.
final String username;
/// The path to the public key of the credential.
final String pubKey;
/// The path to the private key of the credential.
final String privateKey;
/// The passphrase of the credential.
final String passPhrase;
@override
GitCredential get credentialType => GitCredential.sshKey;
}
/// Ssh key credential used for querying an ssh-agent.
class KeypairFromAgent implements Credentials {
const KeypairFromAgent(this.username);
/// The username to authenticate with.
final String username;
@override
GitCredential get credentialType => GitCredential.sshKey;
}
/// Ssh key credential used for reading the keys from memory.
class KeypairFromMemory implements Credentials {
const KeypairFromMemory({
required this.username,
required this.pubKey,
required this.privateKey,
required this.passPhrase,
});
/// The username to authenticate with.
final String username;
/// The path to the public key of the credential.
final String pubKey;
/// The path to the private key of the credential.
final String privateKey;
/// The passphrase of the credential.
final String passPhrase;
@override
GitCredential get credentialType => GitCredential.sshMemory;
}

18
lib/src/features.dart Normal file
View file

@ -0,0 +1,18 @@
import 'util.dart';
import 'git_types.dart';
class Features {
/// Returns list of compile time options for libgit2.
static List<GitFeature> get list {
var result = <GitFeature>[];
final featuresInt = libgit2.git_libgit2_features();
for (var flag in GitFeature.values) {
if (featuresInt & flag.value == flag.value) {
result.add(flag);
}
}
return result;
}
}

View file

@ -1269,3 +1269,90 @@ class GitRepositoryInit {
@override @override
String toString() => 'GitRepositoryInit.$_name'; String toString() => 'GitRepositoryInit.$_name';
} }
/// Supported credential types.
///
/// This represents the various types of authentication methods supported by
/// the library.
class GitCredential {
const GitCredential._(this._value, this._name);
final int _value;
final String _name;
/// A vanilla user/password request.
static const userPassPlainText = GitCredential._(1, 'userPassPlainText');
/// An SSH key-based authentication request.
static const sshKey = GitCredential._(2, 'sshKey');
/// An SSH key-based authentication request, with a custom signature.
static const sshCustom = GitCredential._(4, 'sshCustom');
/// An NTLM/Negotiate-based authentication request.
static const defaultAuth = GitCredential._(8, 'defaultAuth');
/// An SSH interactive authentication request.
static const sshInteractive = GitCredential._(16, 'sshInteractive');
/// Username-only authentication request.
///
/// Used as a pre-authentication step if the underlying transport
/// (eg. SSH, with no username in its URL) does not know which username
/// to use.
static const username = GitCredential._(32, 'username');
/// An SSH key-based authentication request.
///
/// Allows credentials to be read from memory instead of files.
/// Note that because of differences in crypto backend support, it might
/// not be functional.
static const sshMemory = GitCredential._(64, 'sshMemory');
static const List<GitCredential> values = [
userPassPlainText,
sshKey,
sshCustom,
defaultAuth,
sshInteractive,
username,
sshMemory,
];
int get value => _value;
@override
String toString() => 'GitCredential.$_name';
}
/// Combinations of these values describe the features with which libgit2
/// was compiled.
class GitFeature {
const GitFeature._(this._value, this._name);
final int _value;
final String _name;
/// If set, libgit2 was built thread-aware and can be safely used from multiple
/// threads.
static const threads = GitFeature._(1, 'threads');
/// If set, libgit2 was built with and linked against a TLS implementation.
/// Custom TLS streams may still be added by the user to support HTTPS
/// regardless of this.
static const https = GitFeature._(2, 'https');
/// If set, libgit2 was built with and linked against libssh2. A custom
/// transport may still be added by the user to support libssh2 regardless of
/// this.
static const ssh = GitFeature._(4, 'ssh');
/// If set, libgit2 was built with support for sub-second resolution in file
/// modification times.
static const nsec = GitFeature._(8, 'nsec');
static const List<GitFeature> values = [threads, https, ssh, nsec];
int get value => _value;
@override
String toString() => 'GitFeature.$_name';
}

View file

@ -5,7 +5,7 @@ import 'bindings/libgit2_bindings.dart';
DynamicLibrary loadLibrary() { DynamicLibrary loadLibrary() {
if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia) { if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia) {
return DynamicLibrary.open( return DynamicLibrary.open(
'${Directory.current.path}/libgit2/libgit2-1.2.0.so'); '${Directory.current.path}/libgit2/libgit2.so.1.3.0');
} }
if (Platform.isMacOS) { if (Platform.isMacOS) {
return DynamicLibrary.open( return DynamicLibrary.open(

View file

@ -26,6 +26,7 @@
#include "git2/deprecated.h" #include "git2/deprecated.h"
#include "git2/describe.h" #include "git2/describe.h"
#include "git2/diff.h" #include "git2/diff.h"
#include "git2/email.h"
#include "git2/errors.h" #include "git2/errors.h"
#include "git2/filter.h" #include "git2/filter.h"
#include "git2/global.h" #include "git2/global.h"

View file

@ -147,11 +147,17 @@ typedef struct {
/** A combination of GIT_ATTR_CHECK flags */ /** A combination of GIT_ATTR_CHECK flags */
unsigned int flags; unsigned int flags;
#ifdef GIT_DEPRECATE_HARD
void *reserved;
#else
git_oid *commit_id;
#endif
/** /**
* The commit to load attributes from, when * The commit to load attributes from, when
* `GIT_ATTR_CHECK_INCLUDE_COMMIT` is specified. * `GIT_ATTR_CHECK_INCLUDE_COMMIT` is specified.
*/ */
git_oid *commit_id; git_oid attr_commit_id;
} git_attr_options; } git_attr_options;
#define GIT_ATTR_OPTIONS_VERSION 1 #define GIT_ATTR_OPTIONS_VERSION 1

View file

@ -135,11 +135,17 @@ typedef struct {
/** Flags to control the filtering process, see `git_blob_filter_flag_t` above */ /** Flags to control the filtering process, see `git_blob_filter_flag_t` above */
uint32_t flags; uint32_t flags;
#ifdef GIT_DEPRECATE_HARD
void *reserved;
#else
git_oid *commit_id;
#endif
/** /**
* The commit to load attributes from, when * The commit to load attributes from, when
* `GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT` is specified. * `GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
*/ */
git_oid *commit_id; git_oid attr_commit_id;
} git_blob_filter_options; } git_blob_filter_options;
#define GIT_BLOB_FILTER_OPTIONS_VERSION 1 #define GIT_BLOB_FILTER_OPTIONS_VERSION 1

View file

@ -209,7 +209,9 @@ typedef enum {
GIT_OPT_GET_MWINDOW_FILE_LIMIT, GIT_OPT_GET_MWINDOW_FILE_LIMIT,
GIT_OPT_SET_MWINDOW_FILE_LIMIT, GIT_OPT_SET_MWINDOW_FILE_LIMIT,
GIT_OPT_SET_ODB_PACKED_PRIORITY, GIT_OPT_SET_ODB_PACKED_PRIORITY,
GIT_OPT_SET_ODB_LOOSE_PRIORITY GIT_OPT_SET_ODB_LOOSE_PRIORITY,
GIT_OPT_GET_EXTENSIONS,
GIT_OPT_SET_EXTENSIONS
} git_libgit2_opt_t; } git_libgit2_opt_t;
/** /**
@ -431,6 +433,22 @@ typedef enum {
* > Override the default priority of the loose ODB backend which * > Override the default priority of the loose ODB backend which
* > is added when default backends are assigned to a repository * > is added when default backends are assigned to a repository
* *
* opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out)
* > Returns the list of git extensions that are supported. This
* > is the list of built-in extensions supported by libgit2 and
* > custom extensions that have been added with
* > `GIT_OPT_SET_EXTENSIONS`. Extensions that have been negated
* > will not be returned. The returned list should be released
* > with `git_strarray_dispose`.
*
* opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len)
* > Set that the given git extensions are supported by the caller.
* > Extensions supported by libgit2 may be negated by prefixing
* > them with a `!`. For example: setting extensions to
* > { "!noop", "newext" } indicates that the caller does not want
* > to support repositories with the `noop` extension but does want
* > to support repositories with the `newext` extension.
*
* @param option Option key * @param option Option key
* @param ... value to set the option * @param ... value to set the option
* @return 0 on success, <0 on failure * @return 0 on success, <0 on failure

View file

@ -294,6 +294,102 @@ typedef git_configmap git_cvar_map;
/**@}*/ /**@}*/
/** @name Deprecated Diff Functions and Constants
*
* These functions and enumeration values are retained for backward
* compatibility. The newer versions of these functions and values
* should be preferred in all new code.
*
* There is no plan to remove these backward compatibility values at
* this time.
*/
/**@{*/
/**
* Formatting options for diff e-mail generation
*/
typedef enum {
/** Normal patch, the default */
GIT_DIFF_FORMAT_EMAIL_NONE = 0,
/** Don't insert "[PATCH]" in the subject header*/
GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0),
} git_diff_format_email_flags_t;
/**
* Options for controlling the formatting of the generated e-mail.
*/
typedef struct {
unsigned int version;
/** see `git_diff_format_email_flags_t` above */
uint32_t flags;
/** This patch number */
size_t patch_no;
/** Total number of patches in this series */
size_t total_patches;
/** id to use for the commit */
const git_oid *id;
/** Summary of the change */
const char *summary;
/** Commit message's body */
const char *body;
/** Author of the change */
const git_signature *author;
} git_diff_format_email_options;
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL, NULL}
/**
* Create an e-mail ready patch from a diff.
*
* @deprecated git_email_create_from_diff
* @see git_email_create_from_diff
*/
GIT_EXTERN(int) git_diff_format_email(
git_buf *out,
git_diff *diff,
const git_diff_format_email_options *opts);
/**
* Create an e-mail ready patch for a commit.
*
* @deprecated git_email_create_from_commit
* @see git_email_create_from_commit
*/
GIT_EXTERN(int) git_diff_commit_as_email(
git_buf *out,
git_repository *repo,
git_commit *commit,
size_t patch_no,
size_t total_patches,
uint32_t flags,
const git_diff_options *diff_opts);
/**
* Initialize git_diff_format_email_options structure
*
* Initializes a `git_diff_format_email_options` with default values. Equivalent
* to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
*
* @param opts The `git_blame_options` struct to initialize.
* @param version The struct version; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_diff_format_email_options_init(
git_diff_format_email_options *opts,
unsigned int version);
/**@}*/
/** @name Deprecated Error Functions and Constants /** @name Deprecated Error Functions and Constants
* *
* These functions and enumeration values are retained for backward * These functions and enumeration values are retained for backward
@ -683,6 +779,30 @@ GIT_EXTERN(int) git_oid_iszero(const git_oid *id);
/**@}*/ /**@}*/
/** @name Deprecated OID Array Functions
*
* These types are retained for backward compatibility. The newer
* versions of these values should be preferred in all new code.
*
* There is no plan to remove these backward compatibility values at
* this time.
*/
/**@{*/
/**
* Free the memory referred to by the git_oidarray. This is an alias of
* `git_oidarray_dispose` and is preserved for backward compatibility.
*
* This function is deprecated, but there is no plan to remove this
* function at this time.
*
* @deprecated Use git_oidarray_dispose
* @see git_oidarray_dispose
*/
GIT_EXTERN(void) git_oidarray_free(git_oidarray *array);
/**@}*/
/** @name Deprecated Transfer Progress Types /** @name Deprecated Transfer Progress Types
* *
* These types are retained for backward compatibility. The newer * These types are retained for backward compatibility. The newer

View file

@ -133,6 +133,9 @@ typedef enum {
*/ */
GIT_DIFF_INDENT_HEURISTIC = (1u << 18), GIT_DIFF_INDENT_HEURISTIC = (1u << 18),
/** Ignore blank lines */
GIT_DIFF_IGNORE_BLANK_LINES = (1u << 19),
/** Treat all files as text, disabling binary attributes & detection */ /** Treat all files as text, disabling binary attributes & detection */
GIT_DIFF_FORCE_TEXT = (1u << 20), GIT_DIFF_FORCE_TEXT = (1u << 20),
/** Treat all files as binary, disabling text diffs */ /** Treat all files as binary, disabling text diffs */
@ -168,10 +171,6 @@ typedef enum {
* can apply given diff information to binary files. * can apply given diff information to binary files.
*/ */
GIT_DIFF_SHOW_BINARY = (1u << 30), GIT_DIFF_SHOW_BINARY = (1u << 30),
/** Ignore blank lines */
GIT_DIFF_IGNORE_BLANK_LINES = (1u << 31),
} git_diff_option_t; } git_diff_option_t;
/** /**
@ -1376,99 +1375,6 @@ GIT_EXTERN(int) git_diff_stats_to_buf(
*/ */
GIT_EXTERN(void) git_diff_stats_free(git_diff_stats *stats); GIT_EXTERN(void) git_diff_stats_free(git_diff_stats *stats);
/**
* Formatting options for diff e-mail generation
*/
typedef enum {
/** Normal patch, the default */
GIT_DIFF_FORMAT_EMAIL_NONE = 0,
/** Don't insert "[PATCH]" in the subject header*/
GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0),
} git_diff_format_email_flags_t;
/**
* Options for controlling the formatting of the generated e-mail.
*/
typedef struct {
unsigned int version;
/** see `git_diff_format_email_flags_t` above */
uint32_t flags;
/** This patch number */
size_t patch_no;
/** Total number of patches in this series */
size_t total_patches;
/** id to use for the commit */
const git_oid *id;
/** Summary of the change */
const char *summary;
/** Commit message's body */
const char *body;
/** Author of the change */
const git_signature *author;
} git_diff_format_email_options;
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL, NULL}
/**
* Create an e-mail ready patch from a diff.
*
* @param out buffer to store the e-mail patch in
* @param diff containing the commit
* @param opts structure with options to influence content and formatting.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_diff_format_email(
git_buf *out,
git_diff *diff,
const git_diff_format_email_options *opts);
/**
* Create an e-mail ready patch for a commit.
*
* Does not support creating patches for merge commits (yet).
*
* @param out buffer to store the e-mail patch in
* @param repo containing the commit
* @param commit pointer to up commit
* @param patch_no patch number of the commit
* @param total_patches total number of patches in the patch set
* @param flags determines the formatting of the e-mail
* @param diff_opts structure with options to influence diff or NULL for defaults.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_diff_commit_as_email(
git_buf *out,
git_repository *repo,
git_commit *commit,
size_t patch_no,
size_t total_patches,
uint32_t flags,
const git_diff_options *diff_opts);
/**
* Initialize git_diff_format_email_options structure
*
* Initializes a `git_diff_format_email_options` with default values. Equivalent
* to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
*
* @param opts The `git_blame_options` struct to initialize.
* @param version The struct version; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_diff_format_email_options_init(
git_diff_format_email_options *opts,
unsigned int version);
/** /**
* Patch ID options structure * Patch ID options structure
* *

View file

@ -0,0 +1,127 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_email_h__
#define INCLUDE_git_email_h__
#include "common.h"
/**
* @file git2/email.h
* @brief Git email formatting and application routines.
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Formatting options for diff e-mail generation
*/
typedef enum {
/** Normal patch, the default */
GIT_EMAIL_CREATE_DEFAULT = 0,
/** Do not include patch numbers in the subject prefix. */
GIT_EMAIL_CREATE_OMIT_NUMBERS = (1u << 0),
/**
* Include numbers in the subject prefix even when the
* patch is for a single commit (1/1).
*/
GIT_EMAIL_CREATE_ALWAYS_NUMBER = (1u << 1),
/** Do not perform rename or similarity detection. */
GIT_EMAIL_CREATE_NO_RENAMES = (1u << 2),
} git_email_create_flags_t;
/**
* Options for controlling the formatting of the generated e-mail.
*/
typedef struct {
unsigned int version;
/** see `git_email_create_flags_t` above */
uint32_t flags;
/** Options to use when creating diffs */
git_diff_options diff_opts;
/** Options for finding similarities within diffs */
git_diff_find_options diff_find_opts;
/**
* The subject prefix, by default "PATCH". If set to an empty
* string ("") then only the patch numbers will be shown in the
* prefix. If the subject_prefix is empty and patch numbers
* are not being shown, the prefix will be omitted entirely.
*/
const char *subject_prefix;
/**
* The starting patch number; this cannot be 0. By default,
* this is 1.
*/
size_t start_number;
/** The "re-roll" number. By default, there is no re-roll. */
size_t reroll_number;
} git_email_create_options;
/*
* By default, our options include rename detection and binary
* diffs to match `git format-patch`.
*/
#define GIT_EMAIL_CREATE_OPTIONS_VERSION 1
#define GIT_EMAIL_CREATE_OPTIONS_INIT \
{ \
GIT_EMAIL_CREATE_OPTIONS_VERSION, \
GIT_EMAIL_CREATE_DEFAULT, \
{ GIT_DIFF_OPTIONS_VERSION, GIT_DIFF_SHOW_BINARY, GIT_SUBMODULE_IGNORE_UNSPECIFIED, {NULL,0}, NULL, NULL, NULL, 3 }, \
GIT_DIFF_FIND_OPTIONS_INIT \
}
/**
* Create a diff for a commit in mbox format for sending via email.
*
* @param out buffer to store the e-mail patch in
* @param diff the changes to include in the email
* @param patch_idx the patch index
* @param patch_count the total number of patches that will be included
* @param commit_id the commit id for this change
* @param summary the commit message for this change
* @param body optional text to include above the diffstat
* @param author the person who authored this commit
* @param opts email creation options
*/
GIT_EXTERN(int) git_email_create_from_diff(
git_buf *out,
git_diff *diff,
size_t patch_idx,
size_t patch_count,
const git_oid *commit_id,
const char *summary,
const char *body,
const git_signature *author,
const git_email_create_options *opts);
/**
* Create a diff for a commit in mbox format for sending via email.
* The commit must not be a merge commit.
*
* @param out buffer to store the e-mail patch in
* @param commit commit to create a patch for
* @param opts email creation options
*/
GIT_EXTERN(int) git_email_create_from_commit(
git_buf *out,
git_commit *commit,
const git_email_create_options *opts);
GIT_END_DECL
/** @} */
#endif

View file

@ -66,11 +66,17 @@ typedef struct {
/** See `git_filter_flag_t` above */ /** See `git_filter_flag_t` above */
uint32_t flags; uint32_t flags;
#ifdef GIT_DEPRECATE_HARD
void *reserved;
#else
git_oid *commit_id;
#endif
/** /**
* The commit to load attributes from, when * The commit to load attributes from, when
* `GIT_FILTER_ATTRIBUTES_FROM_COMMIT` is specified. * `GIT_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
*/ */
git_oid *commit_id; git_oid attr_commit_id;
} git_filter_options; } git_filter_options;
#define GIT_FILTER_OPTIONS_VERSION 1 #define GIT_FILTER_OPTIONS_VERSION 1

View file

@ -19,19 +19,16 @@ typedef struct git_oidarray {
} git_oidarray; } git_oidarray;
/** /**
* Free the OID array * Free the object IDs contained in an oid_array. This method should
* * be called on `git_oidarray` objects that were provided by the
* This method must (and must only) be called on `git_oidarray` * library. Not doing so will result in a memory leak.
* objects where the array is allocated by the library. Not doing so,
* will result in a memory leak.
* *
* This does not free the `git_oidarray` itself, since the library will * This does not free the `git_oidarray` itself, since the library will
* never allocate that object directly itself (it is more commonly embedded * never allocate that object directly itself.
* inside another struct or created on the stack).
* *
* @param array git_oidarray from which to free oid data * @param array git_oidarray from which to free oid data
*/ */
GIT_EXTERN(void) git_oidarray_free(git_oidarray *array); GIT_EXTERN(void) git_oidarray_dispose(git_oidarray *array);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL

View file

@ -971,7 +971,7 @@ GIT_EXTERN(int) git_remote_rename(
* @param remote_name name to be checked. * @param remote_name name to be checked.
* @return 0 on success or an error code * @return 0 on success or an error code
*/ */
int git_remote_name_is_valid(int *valid, const char *remote_name); GIT_EXTERN(int) git_remote_name_is_valid(int *valid, const char *remote_name);
/** /**
* Delete an existing persisted remote. * Delete an existing persisted remote.

View file

@ -762,13 +762,15 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(
* *
* @param out Output value of calculated SHA * @param out Output value of calculated SHA
* @param repo Repository pointer * @param repo Repository pointer
* @param path Path to file on disk whose contents should be hashed. If the * @param path Path to file on disk whose contents should be hashed. This
* repository is not NULL, this can be a relative path. * may be an absolute path or a relative path, in which case it
* will be treated as a path within the working directory.
* @param type The object type to hash as (e.g. GIT_OBJECT_BLOB) * @param type The object type to hash as (e.g. GIT_OBJECT_BLOB)
* @param as_path The path to use to look up filtering rules. If this is * @param as_path The path to use to look up filtering rules. If this is
* NULL, then the `path` parameter will be used instead. If * an empty string then no filters will be applied when
* this is passed as the empty string, then no filters will be * calculating the hash. If this is `NULL` and the `path`
* applied when calculating the hash. * parameter is a file within the repository's working
* directory, then the `path` will be used.
* @return 0 on success, or an error code * @return 0 on success, or an error code
*/ */
GIT_EXTERN(int) git_repository_hashfile( GIT_EXTERN(int) git_repository_hashfile(

View file

@ -29,9 +29,7 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [ #ifdef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [ #ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_ #define _MSC_STDINT_H_
@ -245,3 +243,5 @@ typedef uint64_t uintmax_t;
#endif // _MSC_STDINT_H_ ] #endif // _MSC_STDINT_H_ ]
#endif // _MSC_VER ]

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_email_h__
#define INCLUDE_sys_git_email_h__
/**
* @file git2/sys/email.h
* @brief Advanced git email creation routines
* @defgroup git_email Advanced git email creation routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Create a diff for a commit in mbox format for sending via email.
*
* @param out buffer to store the e-mail patch in
* @param diff the changes to include in the email
* @param patch_idx the patch index
* @param patch_count the total number of patches that will be included
* @param commit_id the commit id for this change
* @param summary the commit message for this change
* @param body optional text to include above the diffstat
* @param author the person who authored this commit
* @param opts email creation options
*/
GIT_EXTERN(int) git_email_create_from_diff(
git_buf *out,
git_diff *diff,
size_t patch_idx,
size_t patch_count,
const git_oid *commit_id,
const char *summary,
const char *body,
const git_signature *author,
const git_email_create_options *opts);
/** @} */
GIT_END_DECL
#endif

View file

@ -7,12 +7,12 @@
#ifndef INCLUDE_git_version_h__ #ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__ #define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "1.2.0" #define LIBGIT2_VERSION "1.3.0"
#define LIBGIT2_VER_MAJOR 1 #define LIBGIT2_VER_MAJOR 1
#define LIBGIT2_VER_MINOR 2 #define LIBGIT2_VER_MINOR 3
#define LIBGIT2_VER_REVISION 0 #define LIBGIT2_VER_REVISION 0
#define LIBGIT2_VER_PATCH 0 #define LIBGIT2_VER_PATCH 0
#define LIBGIT2_SOVERSION "1.2" #define LIBGIT2_SOVERSION "1.3"
#endif #endif

39
test/assets/keys/id_rsa Normal file
View file

@ -0,0 +1,39 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCcT0eRuC
NRvnDkorGSaQqaAAAAEAAAAAEAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQC5bu0UuVdG
eimAo2mu87uy/hWCbvie6N8H4a7ZjnSThpDIv0clcnbycCukDb/d8o9FRIPNNp2astBlWp
nZ9vCHByP8z8ITO/pG5Mu0Wp0n1Hrja5UVdk4cBvvoEcr2sdNqj3wUUhqeAnNCYeeJuW9V
j2JNV2wwJYPAZBDi6GJTM9FPlCJz+QA6dJLkUiIwngrL8bSPzXd+1mzHOrIcqjxKm8J+ed
3tVSlRq7YvefrACUOTI9ymXwYr8a/TiwA76nTHvNPYIhmzH8PEF65QsFTs/qk0nqSwmqKA
vineapBMmrb3Vf/Hd/c0nEMgHt6gy/+dtlgPh1bTqaQaS/oeo5OtjMDK/w93SR9M3UZBX+
eeMUGfyhvYT4Nvo3TumKzaZ6peGu1T0MKprSwgRdI+v1q+58sKfzSK5QevTpKiX1+4Leo6
BiNKKu6doD19fgNSD/dwfOWehxFtD8q/1J5k0QPgqslFkqyZJXRCzzowRYunSN+AaHVD3W
o4AuqtfTiazPMAAAWQVrRkwWjO1Fcw7zebagqfBufB05nc08wL911ZPCVwqVSIepcEK/hM
CJ/5/N+UILn9BXGe9qmOHPUuMa9UaLBSyzmlJ1s/NMGLzYWiv62SX1QNEXPegxwLasQvbL
njjzdESGX+qUHxT4okNH52zi4DcBLX4HPL/TYQsKTNxCOclOljPDo+3IfHzx76yG5dAl5L
C7ghLsd1zxpwZI+ag7NhNzZ4hBxX9JUenAfGyuOL+YCTp8JnU+dXJ3XaA3WAVGnvsZlAaq
GJUGCdLlMiacO0eXNTm53xc92X9tPmetEVwhuD/Af7Vc4dOmH9Zu+7n9z9bLPrOowNr7ue
w8YCqCg83iuQYmSSPj/JTvCzaoGDfW+yjALlb5RJUAIMJ51k0WyVIyqS0TE8+EINKETlj7
iIx1Y5z54ZnldlqrD2vLImO2b401oOb7fJUEU9Ke5NPi93tsps8nYKhatcRYLnLq9gsFv9
YlDCueoJJobg1k9TO+IwxraPgz3jl24zskSKT/tLFvsz0fQM5QWha2vB8kyZI067ojuNLb
/mj5itgLIDmISa9cf98HhafeE8kGAtKEJR2rLwvb79EAhZ2ypt2I8LVur5hCM4cC9vSVyS
dq/f4sgQpyQqSByMXeLEFYJSCDDc/PL3RC0Q9PqrQYZ1+pqj/6esV3ujLogMAHqEuW4EVw
tMDUvjzfnC8MVUQpc5H4yonsWjGeGhH+VEkBSVISpABTSrYFN5kBodPD16wmRTbFF4tTQq
Egmj5vUmxSY+a2EjDJREQBerMhj3W5sPhAB1QGVVn5kyFvmsjM4t06zzZj/R5muIcX0cT+
Th3N+xeYIuVi9kS5v7yOBlMk0KGq8QATSL/u+niO0e0neoT5Jv6E7EIafAFrn3Ji0rNave
ObCqse3yZct0pbspM4f0c9mHaVbzmvwwtjmUFGdMJgse0UARXqvOlF9PUaN/AhqQlIyVjj
ednPLrOz617XDSixiP+tKzKmqjZsBASZzpGwpHKii9/k7Q7aG5/Int8ulBS3H8C6ipMSxW
EKSMJ4g6k33RY1EFL3dWtJYWhReAhY6kvIc3lmSeo7I9SQWXLupx0NUnkXeO63hLmJ9tjD
CXeI0cwb2a6DWKLh6c2gQ5LPNb/8xzvYJfdop2Oxr+9L2NP7pIgvYr/cmgPtF5WkLT2Ypk
z+KgwWxUKRiK/3G+dVe27u0Id7Yi596wnNGxJfZmlnbfioY4i+K9KcyS08LxlmgsIsQHiY
Scv6SuamPdjiHdSwK/GuAcQUVwXQRA7DoV2uxOosAaUXWMiiSjJ3n1L8IVgp17OKxVN0Bd
5phre4VhYFoXGnq43xFAY3XQJctBqLPdb47RNi3JlhVK+Q1WKzK9OWbDoiseoNnMD5NXOt
Wqf/vxD6AJEyO8sOT55l6hZAkNHIfFUGx4MNmLl12hJYSZgY9tx7aizz8RMT6GMBammQcU
Q0pNDF1RBFOtxgb/QE+9/Vym4dMGnJrhhdbcYZbKngcsho4Qs39qMQvv0V23zAExreQH8U
TBTZYyYkiPqdUiB2fNCW89QWksvBe3CXZAC0T0tdBcEYe5UPJRQ/K2FS6bJTYmxDkDWzHD
9iHbiu3Z8JGB9kHT6B5AgM+fYgEhpCgieDEHdF85cXtGSt8rjFFW6SMS70aLkgzFpYVeD0
zgzumI6JRY3vSMpUY60NCz+FOmIxy7oIpv7nDf/6Ubvah/heUF/P6IQwOQXumVMK9/Khqx
j5TxaRCZ7fXV7IXH1hjQgWSZkGNUHc+rEAZdPOYFXlQb/2+DkO8IE7SxSWwk8tDzS0L7+H
hWXgIm7mjIB6HDNfRb2zPL7gOgm83qZfrhSdP76XqnuV1LvvZMIs2dC8lKFfLk6oayzUvQ
z5AMR0EutUSCby7+DKyBmaYSq0s=
-----END OPENSSH PRIVATE KEY-----

View file

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5bu0UuVdGeimAo2mu87uy/hWCbvie6N8H4a7ZjnSThpDIv0clcnbycCukDb/d8o9FRIPNNp2astBlWpnZ9vCHByP8z8ITO/pG5Mu0Wp0n1Hrja5UVdk4cBvvoEcr2sdNqj3wUUhqeAnNCYeeJuW9Vj2JNV2wwJYPAZBDi6GJTM9FPlCJz+QA6dJLkUiIwngrL8bSPzXd+1mzHOrIcqjxKm8J+ed3tVSlRq7YvefrACUOTI9ymXwYr8a/TiwA76nTHvNPYIhmzH8PEF65QsFTs/qk0nqSwmqKAvineapBMmrb3Vf/Hd/c0nEMgHt6gy/+dtlgPh1bTqaQaS/oeo5OtjMDK/w93SR9M3UZBX+eeMUGfyhvYT4Nvo3TumKzaZ6peGu1T0MKprSwgRdI+v1q+58sKfzSK5QevTpKiX1+4Leo6BiNKKu6doD19fgNSD/dwfOWehxFtD8q/1J5k0QPgqslFkqyZJXRCzzowRYunSN+AaHVD3Wo4AuqtfTiazPM= libgit2dart

170
test/credentials_test.dart Normal file
View file

@ -0,0 +1,170 @@
import 'dart:io';
import 'package:test/test.dart';
import 'package:libgit2dart/libgit2dart.dart';
void main() {
final cloneDir = Directory('${Directory.systemTemp.path}/credentials_cloned');
setUp(() async {
if (await cloneDir.exists()) {
cloneDir.delete(recursive: true);
}
});
tearDown(() async {
if (await cloneDir.exists()) {
cloneDir.delete(recursive: true);
}
});
group('Credentials', () {
test('successfully initializes username credentials', () {
final credentials = const Username('user');
expect(credentials, isA<Credentials>());
expect(credentials.username, 'user');
expect(credentials.credentialType, GitCredential.username);
});
test('successfully initializes username/password credentials', () {
final credentials = const UserPass(
username: 'user',
password: 'password',
);
expect(credentials, isA<Credentials>());
expect(credentials.username, 'user');
expect(credentials.password, 'password');
expect(credentials.credentialType, GitCredential.userPassPlainText);
});
test('successfully initializes keypair credentials', () {
final credentials = const Keypair(
username: 'user',
pubKey: 'id_rsa.pub',
privateKey: 'id_rsa',
passPhrase: 'passphrase',
);
expect(credentials, isA<Credentials>());
expect(credentials.username, 'user');
expect(credentials.pubKey, 'id_rsa.pub');
expect(credentials.privateKey, 'id_rsa');
expect(credentials.passPhrase, 'passphrase');
expect(credentials.credentialType, GitCredential.sshKey);
});
test('successfully initializes keypair from memory credentials', () {
final credentials = const KeypairFromMemory(
username: 'user',
pubKey: 'pubkey data',
privateKey: 'private key data',
passPhrase: 'passphrase',
);
expect(credentials, isA<Credentials>());
expect(credentials.username, 'user');
expect(credentials.pubKey, 'pubkey data');
expect(credentials.privateKey, 'private key data');
expect(credentials.passPhrase, 'passphrase');
expect(credentials.credentialType, GitCredential.sshMemory);
});
test('successfully initializes keypair from agent credentials', () {
final credentials = const KeypairFromAgent('user');
expect(credentials, isA<Credentials>());
expect(credentials.username, 'user');
expect(credentials.credentialType, GitCredential.sshKey);
});
test('sucessfully clones repository with provided keypair', () {
final keypair = const Keypair(
username: 'git',
pubKey: 'test/assets/keys/id_rsa.pub',
privateKey: 'test/assets/keys/id_rsa',
passPhrase: 'empty',
);
final callbacks = Callbacks(credentials: keypair);
final repo = Repository.clone(
url: 'ssh://git@github.com/libgit2/TestGitRepository',
localPath: cloneDir.path,
callbacks: callbacks,
);
expect(repo.isEmpty, false);
repo.free();
});
test('throws when no credentials is provided', () {
expect(
() => Repository.clone(
url: 'ssh://git@github.com/libgit2/TestGitRepository',
localPath: cloneDir.path,
),
throwsA(isA<LibGit2Error>()),
);
});
test('throws when provided keypair is invalid', () {
final keypair = const Keypair(
username: 'git',
pubKey: 'invalid.pub',
privateKey: 'invalid',
passPhrase: 'invalid',
);
final callbacks = Callbacks(credentials: keypair);
expect(
() => Repository.clone(
url: 'ssh://git@github.com/libgit2/TestGitRepository',
localPath: cloneDir.path,
callbacks: callbacks,
),
throwsA(isA<LibGit2Error>()),
);
});
test('sucessfully clones repository with provided keypair from memory', () {
final pubKey = File('test/assets/keys/id_rsa.pub').readAsStringSync();
final privateKey = File('test/assets/keys/id_rsa').readAsStringSync();
final keypair = KeypairFromMemory(
username: 'git',
pubKey: pubKey,
privateKey: privateKey,
passPhrase: 'empty',
);
final callbacks = Callbacks(credentials: keypair);
final repo = Repository.clone(
url: 'ssh://git@github.com/libgit2/TestGitRepository',
localPath: cloneDir.path,
callbacks: callbacks,
);
expect(repo.isEmpty, false);
repo.free();
});
test('sucessfully clones repository with provided username and password',
() {
final userPass = const UserPass(
username: 'libgit2',
password: 'libgit2',
);
final callbacks = Callbacks(credentials: userPass);
final repo = Repository.clone(
url: 'https://github.com/libgit2/TestGitRepository',
localPath: cloneDir.path,
callbacks: callbacks,
);
expect(repo.isEmpty, false);
repo.free();
});
});
}

14
test/features_test.dart Normal file
View file

@ -0,0 +1,14 @@
import 'package:libgit2dart/src/features.dart';
import 'package:test/test.dart';
import 'package:libgit2dart/libgit2dart.dart';
void main() {
group('Features', () {
test('returns list of compile time options for libgit2', () {
expect(
Features.list,
[GitFeature.threads, GitFeature.https, GitFeature.ssh, GitFeature.nsec],
);
});
});
}