mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-05 04:39:07 -04:00
feat(remote): add bindings and api
This commit is contained in:
parent
3b883c49e3
commit
e0e16aea30
9 changed files with 1218 additions and 1 deletions
|
@ -17,5 +17,7 @@ export 'src/worktree.dart';
|
||||||
export 'src/diff.dart';
|
export 'src/diff.dart';
|
||||||
export 'src/patch.dart';
|
export 'src/patch.dart';
|
||||||
export 'src/stash.dart';
|
export 'src/stash.dart';
|
||||||
|
export 'src/remote.dart';
|
||||||
|
export 'src/refspec.dart';
|
||||||
export 'src/error.dart';
|
export 'src/error.dart';
|
||||||
export 'src/git_types.dart';
|
export 'src/git_types.dart';
|
||||||
|
|
87
lib/src/bindings/refspec.dart
Normal file
87
lib/src/bindings/refspec.dart
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'package:ffi/ffi.dart';
|
||||||
|
import '../error.dart';
|
||||||
|
import 'libgit2_bindings.dart';
|
||||||
|
import '../util.dart';
|
||||||
|
|
||||||
|
/// Get the source specifier.
|
||||||
|
String source(Pointer<git_refspec> refspec) {
|
||||||
|
return libgit2.git_refspec_src(refspec).cast<Utf8>().toDartString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the destination specifier.
|
||||||
|
String destination(Pointer<git_refspec> refspec) {
|
||||||
|
return libgit2.git_refspec_dst(refspec).cast<Utf8>().toDartString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the force update setting.
|
||||||
|
bool force(Pointer<git_refspec> refspec) {
|
||||||
|
return libgit2.git_refspec_force(refspec) == 1 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the refspec's string.
|
||||||
|
String string(Pointer<git_refspec> refspec) {
|
||||||
|
return libgit2.git_refspec_string(refspec).cast<Utf8>().toDartString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the refspec's direction.
|
||||||
|
int direction(Pointer<git_refspec> refspec) =>
|
||||||
|
libgit2.git_refspec_direction(refspec);
|
||||||
|
|
||||||
|
/// Check if a refspec's source descriptor matches a reference.
|
||||||
|
bool matchesSource(Pointer<git_refspec> refspec, String refname) {
|
||||||
|
final refnameC = refname.toNativeUtf8().cast<Int8>();
|
||||||
|
final result = libgit2.git_refspec_src_matches(refspec, refnameC);
|
||||||
|
|
||||||
|
calloc.free(refnameC);
|
||||||
|
|
||||||
|
return result == 1 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if a refspec's destination descriptor matches a reference.
|
||||||
|
bool matchesDestination(Pointer<git_refspec> refspec, String refname) {
|
||||||
|
final refnameC = refname.toNativeUtf8().cast<Int8>();
|
||||||
|
final result = libgit2.git_refspec_dst_matches(refspec, refnameC);
|
||||||
|
|
||||||
|
calloc.free(refnameC);
|
||||||
|
|
||||||
|
return result == 1 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transform a reference to its target following the refspec's rules.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
String transform(Pointer<git_refspec> spec, String name) {
|
||||||
|
final out = calloc<git_buf>(sizeOf<git_buf>());
|
||||||
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_refspec_transform(out, spec, nameC);
|
||||||
|
|
||||||
|
calloc.free(nameC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
final result = out.ref.ptr.cast<Utf8>().toDartString();
|
||||||
|
calloc.free(out);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transform a target reference to its source reference following the refspec's rules.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
String rTransform(Pointer<git_refspec> spec, String name) {
|
||||||
|
final out = calloc<git_buf>(sizeOf<git_buf>());
|
||||||
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_refspec_rtransform(out, spec, nameC);
|
||||||
|
|
||||||
|
calloc.free(nameC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
final result = out.ref.ptr.cast<Utf8>().toDartString();
|
||||||
|
calloc.free(out);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
549
lib/src/bindings/remote.dart
Normal file
549
lib/src/bindings/remote.dart
Normal file
|
@ -0,0 +1,549 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'package:ffi/ffi.dart';
|
||||||
|
import '../error.dart';
|
||||||
|
import '../oid.dart';
|
||||||
|
import 'libgit2_bindings.dart';
|
||||||
|
import '../util.dart';
|
||||||
|
|
||||||
|
/// Get a list of the configured remotes for a repo.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
List<String> list(Pointer<git_repository> repo) {
|
||||||
|
final out = calloc<git_strarray>();
|
||||||
|
final error = libgit2.git_remote_list(out, repo);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
final count = out.ref.count;
|
||||||
|
var result = <String>[];
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
result.add(out.ref.strings[i].cast<Utf8>().toDartString());
|
||||||
|
}
|
||||||
|
calloc.free(out);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the information for a particular remote.
|
||||||
|
///
|
||||||
|
/// The name will be checked for validity.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_remote> lookup(Pointer<git_repository> repo, String name) {
|
||||||
|
final out = calloc<Pointer<git_remote>>();
|
||||||
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_lookup(out, repo, nameC);
|
||||||
|
|
||||||
|
calloc.free(nameC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a remote with the default fetch refspec to the repository's configuration.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_remote> create(
|
||||||
|
Pointer<git_repository> repo,
|
||||||
|
String name,
|
||||||
|
String url,
|
||||||
|
) {
|
||||||
|
final out = calloc<Pointer<git_remote>>();
|
||||||
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
|
final urlC = url.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_create(out, repo, nameC, urlC);
|
||||||
|
|
||||||
|
calloc.free(nameC);
|
||||||
|
calloc.free(urlC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a remote with the provided fetch refspec to the repository's configuration.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_remote> createWithFetchSpec(
|
||||||
|
Pointer<git_repository> repo,
|
||||||
|
String name,
|
||||||
|
String url,
|
||||||
|
String fetch,
|
||||||
|
) {
|
||||||
|
final out = calloc<Pointer<git_remote>>();
|
||||||
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
|
final urlC = url.toNativeUtf8().cast<Int8>();
|
||||||
|
final fetchC = fetch.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_create_with_fetchspec(
|
||||||
|
out,
|
||||||
|
repo,
|
||||||
|
nameC,
|
||||||
|
urlC,
|
||||||
|
fetchC,
|
||||||
|
);
|
||||||
|
|
||||||
|
calloc.free(nameC);
|
||||||
|
calloc.free(urlC);
|
||||||
|
calloc.free(fetchC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete an existing persisted remote.
|
||||||
|
///
|
||||||
|
/// All remote-tracking branches and configuration settings for the remote will be removed.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void delete(Pointer<git_repository> repo, String name) {
|
||||||
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_delete(repo, nameC);
|
||||||
|
|
||||||
|
calloc.free(nameC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Give the remote a new name.
|
||||||
|
///
|
||||||
|
/// Returns list of non-default refspecs that cannot be renamed.
|
||||||
|
///
|
||||||
|
/// All remote-tracking branches and configuration settings for the remote are updated.
|
||||||
|
///
|
||||||
|
/// The new name will be checked for validity.
|
||||||
|
///
|
||||||
|
/// No loaded instances of a the remote with the old name will change their name or
|
||||||
|
/// their list of refspecs.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
List<String> rename(Pointer<git_repository> repo, String name, String newName) {
|
||||||
|
final out = calloc<git_strarray>();
|
||||||
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
|
final newNameC = newName.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_rename(out, repo, nameC, newNameC);
|
||||||
|
|
||||||
|
calloc.free(nameC);
|
||||||
|
calloc.free(newNameC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
final count = out.ref.count;
|
||||||
|
var result = <String>[];
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
result.add(out.ref.strings[i].cast<Utf8>().toDartString());
|
||||||
|
}
|
||||||
|
calloc.free(out);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the remote's url in the configuration.
|
||||||
|
///
|
||||||
|
/// Remote objects already in memory will not be affected. This assumes the common
|
||||||
|
/// case of a single-url remote and will otherwise return an error.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void setUrl(Pointer<git_repository> repo, String remote, String url) {
|
||||||
|
final remoteC = remote.toNativeUtf8().cast<Int8>();
|
||||||
|
final urlC = url.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_set_url(repo, remoteC, urlC);
|
||||||
|
|
||||||
|
calloc.free(remoteC);
|
||||||
|
calloc.free(urlC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the remote's url for pushing in the configuration.
|
||||||
|
///
|
||||||
|
/// Remote objects already in memory will not be affected. This assumes the common
|
||||||
|
/// case of a single-url remote and will otherwise return an error.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void setPushUrl(Pointer<git_repository> repo, String remote, String url) {
|
||||||
|
final remoteC = remote.toNativeUtf8().cast<Int8>();
|
||||||
|
final urlC = url.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_set_pushurl(repo, remoteC, urlC);
|
||||||
|
|
||||||
|
calloc.free(remoteC);
|
||||||
|
calloc.free(urlC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the remote's repository.
|
||||||
|
Pointer<git_repository> owner(Pointer<git_remote> remote) {
|
||||||
|
return libgit2.git_remote_owner(remote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the remote's name.
|
||||||
|
String name(Pointer<git_remote> remote) {
|
||||||
|
final result = libgit2.git_remote_name(remote);
|
||||||
|
return result == nullptr ? '' : result.cast<Utf8>().toDartString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the remote's url.
|
||||||
|
String url(Pointer<git_remote> remote) {
|
||||||
|
return libgit2.git_remote_url(remote).cast<Utf8>().toDartString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the remote's url for pushing.
|
||||||
|
///
|
||||||
|
/// Returns empty string if no special url for pushing is set.
|
||||||
|
String pushUrl(Pointer<git_remote> remote) {
|
||||||
|
final result = libgit2.git_remote_pushurl(remote);
|
||||||
|
return result == nullptr ? '' : result.cast<Utf8>().toDartString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the number of refspecs for a remote.
|
||||||
|
int refspecCount(Pointer<git_remote> remote) =>
|
||||||
|
libgit2.git_remote_refspec_count(remote);
|
||||||
|
|
||||||
|
/// Get a refspec from the remote at provided position.
|
||||||
|
Pointer<git_refspec> getRefspec(Pointer<git_remote> remote, int n) {
|
||||||
|
return libgit2.git_remote_get_refspec(remote, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the remote's list of fetch refspecs.
|
||||||
|
List<String> fetchRefspecs(Pointer<git_remote> remote) {
|
||||||
|
final out = calloc<git_strarray>();
|
||||||
|
libgit2.git_remote_get_fetch_refspecs(out, remote);
|
||||||
|
|
||||||
|
var result = <String>[];
|
||||||
|
final count = out.ref.count;
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
result.add(out.ref.strings[i].cast<Utf8>().toDartString());
|
||||||
|
}
|
||||||
|
calloc.free(out);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the remote's list of push refspecs.
|
||||||
|
List<String> pushRefspecs(Pointer<git_remote> remote) {
|
||||||
|
final out = calloc<git_strarray>();
|
||||||
|
libgit2.git_remote_get_push_refspecs(out, remote);
|
||||||
|
|
||||||
|
var result = <String>[];
|
||||||
|
final count = out.ref.count;
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
result.add(out.ref.strings[i].cast<Utf8>().toDartString());
|
||||||
|
}
|
||||||
|
calloc.free(out);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a fetch refspec to the remote's configuration.
|
||||||
|
///
|
||||||
|
/// Add the given refspec to the fetch list in the configuration. No loaded remote
|
||||||
|
/// instances will be affected.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void addFetch(Pointer<git_repository> repo, String remote, String refspec) {
|
||||||
|
final remoteC = remote.toNativeUtf8().cast<Int8>();
|
||||||
|
final refspecC = refspec.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_add_fetch(repo, remoteC, refspecC);
|
||||||
|
|
||||||
|
calloc.free(remoteC);
|
||||||
|
calloc.free(refspecC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a push refspec to the remote's configuration.
|
||||||
|
///
|
||||||
|
/// Add the given refspec to the push list in the configuration. No loaded remote
|
||||||
|
/// instances will be affected.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void addPush(Pointer<git_repository> repo, String remote, String refspec) {
|
||||||
|
final remoteC = remote.toNativeUtf8().cast<Int8>();
|
||||||
|
final refspecC = refspec.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_remote_add_push(repo, remoteC, refspecC);
|
||||||
|
|
||||||
|
calloc.free(remoteC);
|
||||||
|
calloc.free(refspecC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open a connection to a remote.
|
||||||
|
///
|
||||||
|
/// The transport is selected based on the URL. The direction argument is due to a
|
||||||
|
/// limitation of the git protocol (over TCP or SSH) which starts up a specific binary
|
||||||
|
/// which can only do the one or the other.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void connect(
|
||||||
|
Pointer<git_remote> remote,
|
||||||
|
int direction,
|
||||||
|
String proxyOption,
|
||||||
|
) {
|
||||||
|
final callbacks = calloc<git_remote_callbacks>();
|
||||||
|
final callbacksError = libgit2.git_remote_init_callbacks(
|
||||||
|
callbacks,
|
||||||
|
GIT_REMOTE_CALLBACKS_VERSION,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (callbacksError < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
|
||||||
|
final proxyOptions = _proxyOptionsInit(proxyOption);
|
||||||
|
|
||||||
|
final error = libgit2.git_remote_connect(
|
||||||
|
remote,
|
||||||
|
direction,
|
||||||
|
callbacks,
|
||||||
|
proxyOptions,
|
||||||
|
nullptr,
|
||||||
|
);
|
||||||
|
|
||||||
|
calloc.free(callbacks);
|
||||||
|
calloc.free(proxyOptions);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the remote repository's reference advertisement list.
|
||||||
|
///
|
||||||
|
/// Get the list of references with which the server responds to a new connection.
|
||||||
|
///
|
||||||
|
/// The remote (or more exactly its transport) must have connected to the remote repository.
|
||||||
|
/// This list is available as soon as the connection to the remote is initiated and it
|
||||||
|
/// remains available after disconnecting.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
List<Map<String, dynamic>> lsRemotes(Pointer<git_remote> remote) {
|
||||||
|
final out = calloc<Pointer<Pointer<git_remote_head>>>();
|
||||||
|
final size = calloc<Uint64>();
|
||||||
|
final error = libgit2.git_remote_ls(out, size, remote);
|
||||||
|
|
||||||
|
var result = <Map<String, dynamic>>[];
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < size.value; i++) {
|
||||||
|
var remote = <String, dynamic>{};
|
||||||
|
Oid? loid;
|
||||||
|
|
||||||
|
final bool local = out[0][i].ref.local == 1 ? true : false;
|
||||||
|
if (local) {
|
||||||
|
loid = Oid.fromRaw(out[0][i].ref.loid);
|
||||||
|
}
|
||||||
|
|
||||||
|
remote['local'] = local;
|
||||||
|
remote['loid'] = loid;
|
||||||
|
remote['name'] = out[0][i].ref.name == nullptr
|
||||||
|
? ''
|
||||||
|
: out[0][i].ref.name.cast<Utf8>().toDartString();
|
||||||
|
remote['symref'] = out[0][i].ref.symref_target == nullptr
|
||||||
|
? ''
|
||||||
|
: out[0][i].ref.symref_target.cast<Utf8>().toDartString();
|
||||||
|
remote['oid'] = Oid.fromRaw(out[0][i].ref.oid);
|
||||||
|
|
||||||
|
result.add(remote);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Download new data and update tips.
|
||||||
|
///
|
||||||
|
/// Convenience function to connect to a remote, download the data, disconnect and
|
||||||
|
/// update the remote-tracking branches.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void fetch(
|
||||||
|
Pointer<git_remote> remote,
|
||||||
|
List<String> refspecs,
|
||||||
|
String reflogMessage,
|
||||||
|
int prune,
|
||||||
|
String proxyOption,
|
||||||
|
) {
|
||||||
|
var refspecsC = calloc<git_strarray>();
|
||||||
|
final refspecsPointers =
|
||||||
|
refspecs.map((e) => e.toNativeUtf8().cast<Int8>()).toList();
|
||||||
|
final strArray = calloc<Pointer<Int8>>(refspecs.length);
|
||||||
|
|
||||||
|
for (var i = 0; i < refspecs.length; i++) {
|
||||||
|
strArray[i] = refspecsPointers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
refspecsC.ref.count = refspecs.length;
|
||||||
|
refspecsC.ref.strings = strArray;
|
||||||
|
|
||||||
|
final proxyOptions = _proxyOptionsInit(proxyOption);
|
||||||
|
|
||||||
|
final opts = calloc<git_fetch_options>();
|
||||||
|
final optsError = libgit2.git_fetch_options_init(
|
||||||
|
opts,
|
||||||
|
GIT_FETCH_OPTIONS_VERSION,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (optsError < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.ref.prune = prune;
|
||||||
|
opts.ref.proxy_opts = proxyOptions.ref;
|
||||||
|
|
||||||
|
final reflogMessageC = reflogMessage.isEmpty
|
||||||
|
? nullptr
|
||||||
|
: reflogMessage.toNativeUtf8().cast<Int8>();
|
||||||
|
|
||||||
|
final error = libgit2.git_remote_fetch(
|
||||||
|
remote,
|
||||||
|
refspecsC,
|
||||||
|
opts,
|
||||||
|
reflogMessageC,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (var p in refspecsPointers) {
|
||||||
|
calloc.free(p);
|
||||||
|
}
|
||||||
|
calloc.free(strArray);
|
||||||
|
calloc.free(refspecsC);
|
||||||
|
calloc.free(proxyOptions);
|
||||||
|
calloc.free(opts);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a push.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void push(
|
||||||
|
Pointer<git_remote> remote,
|
||||||
|
List<String> refspecs,
|
||||||
|
String proxyOption,
|
||||||
|
) {
|
||||||
|
var refspecsC = calloc<git_strarray>();
|
||||||
|
final refspecsPointers =
|
||||||
|
refspecs.map((e) => e.toNativeUtf8().cast<Int8>()).toList();
|
||||||
|
final strArray = calloc<Pointer<Int8>>(refspecs.length);
|
||||||
|
|
||||||
|
for (var i = 0; i < refspecs.length; i++) {
|
||||||
|
strArray[i] = refspecsPointers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
refspecsC.ref.count = refspecs.length;
|
||||||
|
refspecsC.ref.strings = strArray;
|
||||||
|
|
||||||
|
final proxyOptions = _proxyOptionsInit(proxyOption);
|
||||||
|
|
||||||
|
final opts = calloc<git_push_options>();
|
||||||
|
final optsError =
|
||||||
|
libgit2.git_push_options_init(opts, GIT_PUSH_OPTIONS_VERSION);
|
||||||
|
|
||||||
|
if (optsError < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.ref.proxy_opts = proxyOptions.ref;
|
||||||
|
|
||||||
|
final error = libgit2.git_remote_push(remote, refspecsC, opts);
|
||||||
|
|
||||||
|
for (var p in refspecsPointers) {
|
||||||
|
calloc.free(p);
|
||||||
|
}
|
||||||
|
calloc.free(strArray);
|
||||||
|
calloc.free(refspecsC);
|
||||||
|
calloc.free(proxyOptions);
|
||||||
|
calloc.free(opts);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the statistics structure that is filled in by the fetch operation.
|
||||||
|
Pointer<git_indexer_progress> stats(Pointer<git_remote> remote) =>
|
||||||
|
libgit2.git_remote_stats(remote);
|
||||||
|
|
||||||
|
/// Close the connection to the remote.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void disconnect(Pointer<git_remote> remote) {
|
||||||
|
final error = libgit2.git_remote_disconnect(remote);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prune tracking refs that are no longer present on remote.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void prune(Pointer<git_remote> remote) {
|
||||||
|
final callbacks = calloc<git_remote_callbacks>();
|
||||||
|
final callbacksError = libgit2.git_remote_init_callbacks(
|
||||||
|
callbacks,
|
||||||
|
GIT_REMOTE_CALLBACKS_VERSION,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (callbacksError < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
|
||||||
|
final error = libgit2.git_remote_prune(remote, callbacks);
|
||||||
|
|
||||||
|
calloc.free(callbacks);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Free the memory associated with a remote.
|
||||||
|
///
|
||||||
|
/// This also disconnects from the remote, if the connection has not been closed
|
||||||
|
/// yet (using `disconnect()`).
|
||||||
|
void free(Pointer<git_remote> remote) => libgit2.git_remote_free(remote);
|
||||||
|
|
||||||
|
/// Initializes git_proxy_options structure.
|
||||||
|
Pointer<git_proxy_options> _proxyOptionsInit(String proxyOption) {
|
||||||
|
final proxyOptions = calloc<git_proxy_options>();
|
||||||
|
final proxyOptionsError =
|
||||||
|
libgit2.git_proxy_options_init(proxyOptions, GIT_PROXY_OPTIONS_VERSION);
|
||||||
|
|
||||||
|
if (proxyOptionsError < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxyOption.isEmpty) {
|
||||||
|
proxyOptions.ref.type = git_proxy_t.GIT_PROXY_NONE;
|
||||||
|
} else if (proxyOption == 'auto') {
|
||||||
|
proxyOptions.ref.type = git_proxy_t.GIT_PROXY_AUTO;
|
||||||
|
} else {
|
||||||
|
proxyOptions.ref.type = git_proxy_t.GIT_PROXY_SPECIFIED;
|
||||||
|
proxyOptions.ref.url = proxyOption.toNativeUtf8().cast<Int8>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxyOptions;
|
||||||
|
}
|
|
@ -1174,3 +1174,44 @@ class GitStashApply {
|
||||||
@override
|
@override
|
||||||
String toString() => 'GitStashApply.$_name';
|
String toString() => 'GitStashApply.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Direction of the connection.
|
||||||
|
class GitDirection {
|
||||||
|
const GitDirection._(this._value, this._name);
|
||||||
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
|
static const fetch = GitDirection._(0, 'fetch');
|
||||||
|
static const push = GitDirection._(1, 'push');
|
||||||
|
|
||||||
|
static const List<GitDirection> values = [fetch, push];
|
||||||
|
|
||||||
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitDirection.$_name';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Acceptable prune settings when fetching.
|
||||||
|
class GitFetchPrune {
|
||||||
|
const GitFetchPrune._(this._value, this._name);
|
||||||
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
|
/// Use the setting from the configuration.
|
||||||
|
static const unspecified = GitFetchPrune._(0, 'unspecified');
|
||||||
|
|
||||||
|
/// Force pruning on. Removes any remote branch in the local repository
|
||||||
|
/// that does not exist in the remote
|
||||||
|
static const prune = GitFetchPrune._(1, 'prune');
|
||||||
|
|
||||||
|
/// Force pruning off. Keeps the remote branches.
|
||||||
|
static const noPrune = GitFetchPrune._(2, 'noPrune');
|
||||||
|
|
||||||
|
static const List<GitFetchPrune> values = [unspecified, prune, noPrune];
|
||||||
|
|
||||||
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitFetchPrune.$_name';
|
||||||
|
}
|
||||||
|
|
52
lib/src/refspec.dart
Normal file
52
lib/src/refspec.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'package:libgit2dart/libgit2dart.dart';
|
||||||
|
|
||||||
|
import 'bindings/libgit2_bindings.dart';
|
||||||
|
import 'bindings/refspec.dart' as bindings;
|
||||||
|
import 'git_types.dart';
|
||||||
|
|
||||||
|
class Refspec {
|
||||||
|
/// Initializes a new instance of the [Refspec] class
|
||||||
|
/// from provided pointer to refspec object in memory.
|
||||||
|
Refspec(this._refspecPointer);
|
||||||
|
|
||||||
|
/// Pointer to memory address for allocated refspec object.
|
||||||
|
final Pointer<git_refspec> _refspecPointer;
|
||||||
|
|
||||||
|
/// Returns the source specifier.
|
||||||
|
String get source => bindings.source(_refspecPointer);
|
||||||
|
|
||||||
|
/// Returns the destination specifier.
|
||||||
|
String get destination => bindings.destination(_refspecPointer);
|
||||||
|
|
||||||
|
/// Returns the force update setting.
|
||||||
|
bool get force => bindings.force(_refspecPointer);
|
||||||
|
|
||||||
|
/// Returns the refspec's string.
|
||||||
|
String get string => bindings.string(_refspecPointer);
|
||||||
|
|
||||||
|
/// Returns the refspec's direction (fetch or push).
|
||||||
|
GitDirection get direction {
|
||||||
|
return bindings.direction(_refspecPointer) == 0
|
||||||
|
? GitDirection.fetch
|
||||||
|
: GitDirection.push;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if a refspec's source descriptor matches a reference.
|
||||||
|
bool matchesSource(String refname) =>
|
||||||
|
bindings.matchesSource(_refspecPointer, refname);
|
||||||
|
|
||||||
|
/// Checks if a refspec's destination descriptor matches a reference.
|
||||||
|
bool matchesDestination(String refname) =>
|
||||||
|
bindings.matchesDestination(_refspecPointer, refname);
|
||||||
|
|
||||||
|
/// Transforms a reference to its target following the refspec's rules.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
String transform(String name) => bindings.transform(_refspecPointer, name);
|
||||||
|
|
||||||
|
/// Transforms a target reference to its source reference following the refspec's rules.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
String rTransform(String name) => bindings.rTransform(_refspecPointer, name);
|
||||||
|
}
|
226
lib/src/remote.dart
Normal file
226
lib/src/remote.dart
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'package:libgit2dart/libgit2dart.dart';
|
||||||
|
|
||||||
|
import 'bindings/libgit2_bindings.dart';
|
||||||
|
import 'bindings/remote.dart' as bindings;
|
||||||
|
import 'git_types.dart';
|
||||||
|
import 'refspec.dart';
|
||||||
|
import 'repository.dart';
|
||||||
|
|
||||||
|
class Remotes {
|
||||||
|
/// Initializes a new instance of the [References] class
|
||||||
|
/// from provided [Repository] object.
|
||||||
|
Remotes(Repository repo) {
|
||||||
|
_repoPointer = repo.pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pointer to memory address for allocated repository object.
|
||||||
|
late final Pointer<git_repository> _repoPointer;
|
||||||
|
|
||||||
|
/// Returns a list of the configured remotes for a repo.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
List<String> get list {
|
||||||
|
return bindings.list(_repoPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns number of the configured remotes for a repo.
|
||||||
|
int get length => list.length;
|
||||||
|
|
||||||
|
/// Returns [Remote] by looking up [name] in a repository.
|
||||||
|
///
|
||||||
|
/// The name will be checked for validity.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Remote operator [](String name) {
|
||||||
|
return Remote(bindings.lookup(_repoPointer, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a remote to the repository's configuration with the default [fetch]
|
||||||
|
/// refspec if none provided .
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Remote create({
|
||||||
|
required String name,
|
||||||
|
required String url,
|
||||||
|
String fetch = '',
|
||||||
|
}) {
|
||||||
|
if (fetch.isEmpty) {
|
||||||
|
return Remote(bindings.create(_repoPointer, name, url));
|
||||||
|
} else {
|
||||||
|
return Remote(bindings.createWithFetchSpec(
|
||||||
|
_repoPointer,
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
fetch,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes an existing persisted remote.
|
||||||
|
///
|
||||||
|
/// All remote-tracking branches and configuration settings for the remote will be removed.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void delete(String name) => bindings.delete(_repoPointer, name);
|
||||||
|
|
||||||
|
/// Give the remote a new name.
|
||||||
|
///
|
||||||
|
/// Returns list of non-default refspecs that cannot be renamed.
|
||||||
|
///
|
||||||
|
/// All remote-tracking branches and configuration settings for the remote are updated.
|
||||||
|
///
|
||||||
|
/// The new name will be checked for validity.
|
||||||
|
///
|
||||||
|
/// No loaded instances of a the remote with the old name will change their name or
|
||||||
|
/// their list of refspecs.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
List<String> rename(String name, String newName) =>
|
||||||
|
bindings.rename(_repoPointer, name, newName);
|
||||||
|
|
||||||
|
/// Sets the remote's url in the configuration.
|
||||||
|
///
|
||||||
|
/// Remote objects already in memory will not be affected. This assumes the common
|
||||||
|
/// case of a single-url remote and will otherwise return an error.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void setUrl(String remote, String url) =>
|
||||||
|
bindings.setUrl(_repoPointer, remote, url);
|
||||||
|
|
||||||
|
/// Sets the remote's url for pushing in the configuration.
|
||||||
|
///
|
||||||
|
/// Remote objects already in memory will not be affected. This assumes the common
|
||||||
|
/// case of a single-url remote and will otherwise return an error.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void setPushUrl(String remote, String url) =>
|
||||||
|
bindings.setPushUrl(_repoPointer, remote, url);
|
||||||
|
|
||||||
|
/// Adds a fetch refspec to the remote's configuration.
|
||||||
|
///
|
||||||
|
/// No loaded remote instances will be affected.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void addFetch(String remote, String refspec) =>
|
||||||
|
bindings.addFetch(_repoPointer, remote, refspec);
|
||||||
|
|
||||||
|
/// Adds a push refspec to the remote's configuration.
|
||||||
|
///
|
||||||
|
/// No loaded remote instances will be affected.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void addPush(String remote, String refspec) =>
|
||||||
|
bindings.addPush(_repoPointer, remote, refspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Remote {
|
||||||
|
/// Initializes a new instance of [Remote] class from provided pointer
|
||||||
|
/// to remote object in memory.
|
||||||
|
Remote(this._remotePointer);
|
||||||
|
|
||||||
|
/// Pointer to memory address for allocated remote object.
|
||||||
|
late final Pointer<git_remote> _remotePointer;
|
||||||
|
|
||||||
|
/// Returns the remote's name.
|
||||||
|
String get name => bindings.name(_remotePointer);
|
||||||
|
|
||||||
|
/// Returns the remote's url.
|
||||||
|
String get url => bindings.url(_remotePointer);
|
||||||
|
|
||||||
|
/// Returns the remote's url for pushing.
|
||||||
|
///
|
||||||
|
/// Returns empty string if no special url for pushing is set.
|
||||||
|
String get pushUrl => bindings.pushUrl(_remotePointer);
|
||||||
|
|
||||||
|
/// Returns the number of refspecs for a remote.
|
||||||
|
int get refspecCount => bindings.refspecCount(_remotePointer);
|
||||||
|
|
||||||
|
/// Returns a [Refspec] object from the remote at provided position.
|
||||||
|
Refspec getRefspec(int index) =>
|
||||||
|
Refspec(bindings.getRefspec(_remotePointer, index));
|
||||||
|
|
||||||
|
/// Returns the remote's list of fetch refspecs.
|
||||||
|
List<String> get fetchRefspecs => bindings.fetchRefspecs(_remotePointer);
|
||||||
|
|
||||||
|
/// Get the remote's list of push refspecs.
|
||||||
|
List<String> get pushRefspecs => bindings.pushRefspecs(_remotePointer);
|
||||||
|
|
||||||
|
/// Get the remote repository's reference advertisement list.
|
||||||
|
///
|
||||||
|
/// [proxy] can be 'auto' to try to auto-detect the proxy from the git configuration or some
|
||||||
|
/// specified url. By default connection isn't done through proxy.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
List<Map<String, dynamic>> ls([String proxy = '']) {
|
||||||
|
bindings.connect(_remotePointer, GitDirection.fetch.value, proxy);
|
||||||
|
final result = bindings.lsRemotes(_remotePointer);
|
||||||
|
bindings.disconnect(_remotePointer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Downloads new data and updates tips.
|
||||||
|
///
|
||||||
|
/// [proxy] can be 'auto' to try to auto-detect the proxy from the git configuration or some
|
||||||
|
/// specified url. By default connection isn't done through proxy.
|
||||||
|
///
|
||||||
|
/// [reflogMessage] is the message to insert into the reflogs. Default is "fetch".
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
TransferProgress fetch({
|
||||||
|
List<String> refspecs = const [],
|
||||||
|
String reflogMessage = '',
|
||||||
|
GitFetchPrune prune = GitFetchPrune.unspecified,
|
||||||
|
String proxy = '',
|
||||||
|
}) {
|
||||||
|
bindings.fetch(_remotePointer, refspecs, reflogMessage, prune.value, proxy);
|
||||||
|
return TransferProgress(bindings.stats(_remotePointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a push.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void push(List<String> refspecs, [String proxy = '']) {
|
||||||
|
bindings.push(_remotePointer, refspecs, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prunes tracking refs that are no longer present on remote.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void prune() => bindings.prune(_remotePointer);
|
||||||
|
|
||||||
|
/// Releases memory allocated for remote object.
|
||||||
|
void free() => bindings.free(_remotePointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides callers information about the progress of indexing a packfile, either
|
||||||
|
/// directly or part of a fetch or clone that downloads a packfile.
|
||||||
|
class TransferProgress {
|
||||||
|
/// Initializes a new instance of [TransferProgress] class from provided pointer
|
||||||
|
/// to transfer progress object in memory.
|
||||||
|
TransferProgress(this._transferProgressPointer);
|
||||||
|
|
||||||
|
/// Pointer to memory address for allocated transfer progress object.
|
||||||
|
final Pointer<git_indexer_progress> _transferProgressPointer;
|
||||||
|
|
||||||
|
/// Returns total number of objects to download.
|
||||||
|
int get totalObjects => _transferProgressPointer.ref.total_objects;
|
||||||
|
|
||||||
|
/// Returns number of objects that have been indexed.
|
||||||
|
int get indexedObjects => _transferProgressPointer.ref.indexed_objects;
|
||||||
|
|
||||||
|
/// Returns number of objects that have been downloaded.
|
||||||
|
int get receivedObjects => _transferProgressPointer.ref.received_objects;
|
||||||
|
|
||||||
|
/// Returns number of local objects that have been used to fix the thin pack.
|
||||||
|
int get localObjects => _transferProgressPointer.ref.local_objects;
|
||||||
|
|
||||||
|
/// Returns total number of deltas in the pack.
|
||||||
|
int get totalDeltas => _transferProgressPointer.ref.total_deltas;
|
||||||
|
|
||||||
|
/// Returns number of deltas that have been indexed.
|
||||||
|
int get indexedDeltas => _transferProgressPointer.ref.indexed_deltas;
|
||||||
|
|
||||||
|
/// Returns number of bytes received up to now.
|
||||||
|
int get receivedBytes => _transferProgressPointer.ref.received_bytes;
|
||||||
|
}
|
|
@ -919,4 +919,7 @@ class Repository {
|
||||||
List<Stash> get stashList {
|
List<Stash> get stashList {
|
||||||
return stash_bindings.list(_repoPointer);
|
return stash_bindings.list(_repoPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns [Remotes] object.
|
||||||
|
Remotes get remotes => Remotes(this);
|
||||||
}
|
}
|
||||||
|
|
257
test/remote_test.dart
Normal file
257
test/remote_test.dart
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:libgit2dart/libgit2dart.dart';
|
||||||
|
import 'helpers/util.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late Repository repo;
|
||||||
|
final tmpDir = '${Directory.systemTemp.path}/remote_testrepo/';
|
||||||
|
const remoteName = 'origin';
|
||||||
|
const remoteUrl = 'git://github.com/SkinnyMind/libgit2dart.git';
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
if (await Directory(tmpDir).exists()) {
|
||||||
|
await Directory(tmpDir).delete(recursive: true);
|
||||||
|
}
|
||||||
|
await copyRepo(
|
||||||
|
from: Directory('test/assets/testrepo/'),
|
||||||
|
to: await Directory(tmpDir).create(),
|
||||||
|
);
|
||||||
|
repo = Repository.open(tmpDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() async {
|
||||||
|
repo.free();
|
||||||
|
await Directory(tmpDir).delete(recursive: true);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Remote', () {
|
||||||
|
test('returns list of remotes', () {
|
||||||
|
expect(repo.remotes.list, ['origin']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully looks up remote for provided name', () {
|
||||||
|
final remote = repo.remotes['origin'];
|
||||||
|
|
||||||
|
expect(remote.name, remoteName);
|
||||||
|
expect(remote.url, remoteUrl);
|
||||||
|
expect(remote.pushUrl, '');
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when provided name for lookup is not found', () {
|
||||||
|
expect(() => repo.remotes['upstream'], throwsA(isA<LibGit2Error>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully creates without fetchspec', () {
|
||||||
|
final remote = repo.remotes.create(name: 'upstream', url: remoteUrl);
|
||||||
|
|
||||||
|
expect(repo.remotes.length, 2);
|
||||||
|
expect(remote.name, 'upstream');
|
||||||
|
expect(remote.url, remoteUrl);
|
||||||
|
expect(remote.pushUrl, '');
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully creates with provided fetchspec', () {
|
||||||
|
const spec = '+refs/*:refs/*';
|
||||||
|
final remote = repo.remotes.create(
|
||||||
|
name: 'upstream',
|
||||||
|
url: remoteUrl,
|
||||||
|
fetch: spec,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(repo.remotes.length, 2);
|
||||||
|
expect(remote.name, 'upstream');
|
||||||
|
expect(remote.url, remoteUrl);
|
||||||
|
expect(remote.pushUrl, '');
|
||||||
|
expect(remote.fetchRefspecs, [spec]);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully deletes', () {
|
||||||
|
final remote = repo.remotes.create(name: 'upstream', url: remoteUrl);
|
||||||
|
expect(repo.remotes.length, 2);
|
||||||
|
|
||||||
|
repo.remotes.delete(remote.name);
|
||||||
|
expect(repo.remotes.length, 1);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully renames', () {
|
||||||
|
final remote = repo.remotes[remoteName];
|
||||||
|
|
||||||
|
final problems = repo.remotes.rename(remoteName, 'new');
|
||||||
|
expect(problems, isEmpty);
|
||||||
|
expect(remote.name, isNot('new'));
|
||||||
|
|
||||||
|
final newRemote = repo.remotes['new'];
|
||||||
|
expect(newRemote.name, 'new');
|
||||||
|
|
||||||
|
newRemote.free();
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when renaming with invalid names', () {
|
||||||
|
expect(() => repo.remotes.rename('', ''), throwsA(isA<LibGit2Error>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully sets url', () {
|
||||||
|
final remote = repo.remotes[remoteName];
|
||||||
|
expect(remote.url, remoteUrl);
|
||||||
|
|
||||||
|
const newUrl = 'git://new/url.git';
|
||||||
|
repo.remotes.setUrl(remoteName, newUrl);
|
||||||
|
|
||||||
|
final newRemote = repo.remotes[remoteName];
|
||||||
|
expect(newRemote.url, newUrl);
|
||||||
|
|
||||||
|
newRemote.free();
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when trying to set invalid url name', () {
|
||||||
|
expect(
|
||||||
|
() => repo.remotes.setUrl('origin', ''),
|
||||||
|
throwsA(isA<LibGit2Error>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully sets url for pushing', () {
|
||||||
|
const newUrl = 'git://new/url.git';
|
||||||
|
repo.remotes.setPushUrl(remoteName, newUrl);
|
||||||
|
|
||||||
|
final remote = repo.remotes[remoteName];
|
||||||
|
expect(remote.pushUrl, newUrl);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when trying to set invalid push url name', () {
|
||||||
|
expect(
|
||||||
|
() => repo.remotes.setPushUrl('origin', ''),
|
||||||
|
throwsA(isA<LibGit2Error>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns refspec', () {
|
||||||
|
final remote = repo.remotes['origin'];
|
||||||
|
expect(remote.refspecCount, 1);
|
||||||
|
|
||||||
|
final refspec = remote.getRefspec(0);
|
||||||
|
expect(refspec.source, 'refs/heads/*');
|
||||||
|
expect(refspec.destination, 'refs/remotes/origin/*');
|
||||||
|
expect(refspec.force, true);
|
||||||
|
expect(refspec.string, '+refs/heads/*:refs/remotes/origin/*');
|
||||||
|
expect(remote.fetchRefspecs, ['+refs/heads/*:refs/remotes/origin/*']);
|
||||||
|
|
||||||
|
expect(refspec.matchesSource('refs/heads/master'), true);
|
||||||
|
expect(refspec.matchesDestination('refs/remotes/origin/master'), true);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
refspec.transform('refs/heads/master'),
|
||||||
|
'refs/remotes/origin/master',
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
refspec.rTransform('refs/remotes/origin/master'),
|
||||||
|
'refs/heads/master',
|
||||||
|
);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully adds fetch refspec', () {
|
||||||
|
repo.remotes.addFetch('origin', '+refs/test/*:refs/test/remotes/*');
|
||||||
|
final remote = repo.remotes['origin'];
|
||||||
|
expect(remote.fetchRefspecs.length, 2);
|
||||||
|
expect(
|
||||||
|
remote.fetchRefspecs,
|
||||||
|
[
|
||||||
|
'+refs/heads/*:refs/remotes/origin/*',
|
||||||
|
'+refs/test/*:refs/test/remotes/*',
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully adds push refspec', () {
|
||||||
|
repo.remotes.addPush('origin', '+refs/test/*:refs/test/remotes/*');
|
||||||
|
final remote = repo.remotes['origin'];
|
||||||
|
expect(remote.pushRefspecs.length, 1);
|
||||||
|
expect(remote.pushRefspecs, ['+refs/test/*:refs/test/remotes/*']);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully returns remote repo\'s reference list', () {
|
||||||
|
repo.remotes.setUrl(
|
||||||
|
'libgit2',
|
||||||
|
'https://github.com/libgit2/TestGitRepository',
|
||||||
|
);
|
||||||
|
final remote = repo.remotes['libgit2'];
|
||||||
|
|
||||||
|
final refs = remote.ls();
|
||||||
|
expect(refs.first['local'], false);
|
||||||
|
expect(refs.first['loid'], null);
|
||||||
|
expect(refs.first['name'], 'HEAD');
|
||||||
|
expect(refs.first['symref'], 'refs/heads/master');
|
||||||
|
expect(
|
||||||
|
(refs.first['oid'] as Oid).sha,
|
||||||
|
'49322bb17d3acc9146f98c97d078513228bbf3c0',
|
||||||
|
);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully fetches data', () async {
|
||||||
|
repo.remotes.setUrl(
|
||||||
|
'libgit2',
|
||||||
|
'https://github.com/libgit2/TestGitRepository',
|
||||||
|
);
|
||||||
|
final remote = repo.remotes['libgit2'];
|
||||||
|
|
||||||
|
final stats = remote.fetch();
|
||||||
|
|
||||||
|
expect(stats.totalObjects, 69);
|
||||||
|
expect(stats.indexedObjects, 69);
|
||||||
|
expect(stats.receivedObjects, 69);
|
||||||
|
expect(stats.localObjects, 0);
|
||||||
|
expect(stats.totalDeltas, 3);
|
||||||
|
expect(stats.indexedDeltas, 3);
|
||||||
|
expect(stats.receivedBytes, 0);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully pushes', () async {
|
||||||
|
final originDir = '${Directory.systemTemp.path}/origin_testrepo/';
|
||||||
|
|
||||||
|
if (await Directory(originDir).exists()) {
|
||||||
|
await Directory(originDir).delete(recursive: true);
|
||||||
|
}
|
||||||
|
await copyRepo(
|
||||||
|
from: Directory('test/assets/empty_bare.git/'),
|
||||||
|
to: await Directory(originDir).create(),
|
||||||
|
);
|
||||||
|
final originRepo = Repository.open(originDir);
|
||||||
|
|
||||||
|
repo.remotes.create(name: 'local', url: originDir);
|
||||||
|
final remote = repo.remotes['local'];
|
||||||
|
|
||||||
|
remote.push(['refs/heads/master']);
|
||||||
|
expect(
|
||||||
|
(originRepo[originRepo.head.target.sha] as Commit).id.sha,
|
||||||
|
'821ed6e80627b8769d170a293862f9fc60825226',
|
||||||
|
);
|
||||||
|
|
||||||
|
remote.free();
|
||||||
|
originRepo.free();
|
||||||
|
await Directory(originDir).delete(recursive: true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import 'helpers/util.dart';
|
||||||
void main() {
|
void main() {
|
||||||
late Repository repo;
|
late Repository repo;
|
||||||
late Signature stasher;
|
late Signature stasher;
|
||||||
final tmpDir = '${Directory.systemTemp.path}/patch_testrepo/';
|
final tmpDir = '${Directory.systemTemp.path}/stash_testrepo/';
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
if (await Directory(tmpDir).exists()) {
|
if (await Directory(tmpDir).exists()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue