mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-04 20:29:08 -04:00
feat(reference): add ability to set target
This commit is contained in:
parent
58fa54f24a
commit
371d52b7f8
5 changed files with 147 additions and 15 deletions
|
@ -163,12 +163,12 @@ Pointer<git_reference> createDirect(
|
||||||
String name,
|
String name,
|
||||||
Pointer<git_oid> oid,
|
Pointer<git_oid> oid,
|
||||||
bool force,
|
bool force,
|
||||||
String logMessage,
|
String? logMessage,
|
||||||
) {
|
) {
|
||||||
final out = calloc<Pointer<git_reference>>();
|
final out = calloc<Pointer<git_reference>>();
|
||||||
final nameC = name.toNativeUtf8().cast<Int8>();
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
final forceC = force == true ? 1 : 0;
|
final forceC = force == true ? 1 : 0;
|
||||||
final logMessageC = logMessage.toNativeUtf8().cast<Int8>();
|
final logMessageC = logMessage?.toNativeUtf8().cast<Int8>() ?? nullptr;
|
||||||
final error = libgit2.git_reference_create(
|
final error = libgit2.git_reference_create(
|
||||||
out,
|
out,
|
||||||
repo,
|
repo,
|
||||||
|
@ -214,13 +214,13 @@ Pointer<git_reference> createSymbolic(
|
||||||
String name,
|
String name,
|
||||||
String target,
|
String target,
|
||||||
bool force,
|
bool force,
|
||||||
String logMessage,
|
String? logMessage,
|
||||||
) {
|
) {
|
||||||
final out = calloc<Pointer<git_reference>>();
|
final out = calloc<Pointer<git_reference>>();
|
||||||
final nameC = name.toNativeUtf8().cast<Int8>();
|
final nameC = name.toNativeUtf8().cast<Int8>();
|
||||||
final targetC = target.toNativeUtf8().cast<Int8>();
|
final targetC = target.toNativeUtf8().cast<Int8>();
|
||||||
final forceC = force == true ? 1 : 0;
|
final forceC = force == true ? 1 : 0;
|
||||||
final logMessageC = logMessage.toNativeUtf8().cast<Int8>();
|
final logMessageC = logMessage?.toNativeUtf8().cast<Int8>() ?? nullptr;
|
||||||
final error = libgit2.git_reference_symbolic_create(
|
final error = libgit2.git_reference_symbolic_create(
|
||||||
out,
|
out,
|
||||||
repo,
|
repo,
|
||||||
|
@ -259,6 +259,60 @@ Pointer<git_repository> owner(Pointer<git_reference> ref) {
|
||||||
return libgit2.git_reference_owner(ref);
|
return libgit2.git_reference_owner(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Conditionally create a new reference with the same name as the given reference
|
||||||
|
/// but a different OID target. The reference must be a direct reference, otherwise this will fail.
|
||||||
|
///
|
||||||
|
/// The new reference will be written to disk, overwriting the given reference.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_reference> setTarget(
|
||||||
|
Pointer<git_reference> ref,
|
||||||
|
Pointer<git_oid> oid,
|
||||||
|
String? logMessage,
|
||||||
|
) {
|
||||||
|
final out = calloc<Pointer<git_reference>>();
|
||||||
|
final logMessageC = logMessage?.toNativeUtf8().cast<Int8>() ?? nullptr;
|
||||||
|
final error = libgit2.git_reference_set_target(out, ref, oid, logMessageC);
|
||||||
|
calloc.free(logMessageC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new reference with the same name as the given reference but a different
|
||||||
|
/// symbolic target. The reference must be a symbolic reference, otherwise this will fail.
|
||||||
|
///
|
||||||
|
/// The new reference will be written to disk, overwriting the given reference.
|
||||||
|
///
|
||||||
|
/// The target name will be checked for validity.
|
||||||
|
///
|
||||||
|
/// The message for the reflog will be ignored if the reference does not belong in the
|
||||||
|
/// standard set (HEAD, branches and remote-tracking branches) and and it does not have a reflog.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_reference> setTargetSymbolic(
|
||||||
|
Pointer<git_reference> ref,
|
||||||
|
String target,
|
||||||
|
String? logMessage,
|
||||||
|
) {
|
||||||
|
final out = calloc<Pointer<git_reference>>();
|
||||||
|
final targetC = target.toNativeUtf8().cast<Int8>();
|
||||||
|
final logMessageC = logMessage?.toNativeUtf8().cast<Int8>() ?? nullptr;
|
||||||
|
final error =
|
||||||
|
libgit2.git_reference_symbolic_set_target(out, ref, targetC, logMessageC);
|
||||||
|
calloc.free(targetC);
|
||||||
|
calloc.free(logMessageC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ensure the reference name is well-formed.
|
/// Ensure the reference name is well-formed.
|
||||||
///
|
///
|
||||||
/// Valid reference names must follow one of two patterns:
|
/// Valid reference names must follow one of two patterns:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'bindings/libgit2_bindings.dart';
|
import 'bindings/libgit2_bindings.dart';
|
||||||
import 'bindings/reference.dart' as bindings;
|
import 'bindings/reference.dart' as bindings;
|
||||||
|
import 'bindings/repository.dart' as repo_bindings;
|
||||||
|
import 'odb.dart';
|
||||||
import 'oid.dart';
|
import 'oid.dart';
|
||||||
import 'reflog.dart';
|
import 'reflog.dart';
|
||||||
import 'util.dart';
|
import 'util.dart';
|
||||||
|
@ -37,7 +39,7 @@ class Reference {
|
||||||
required String name,
|
required String name,
|
||||||
required Pointer<git_oid> oid,
|
required Pointer<git_oid> oid,
|
||||||
required bool force,
|
required bool force,
|
||||||
required String logMessage,
|
String? logMessage,
|
||||||
}) {
|
}) {
|
||||||
_refPointer = bindings.createDirect(repo, name, oid, force, logMessage);
|
_refPointer = bindings.createDirect(repo, name, oid, force, logMessage);
|
||||||
}
|
}
|
||||||
|
@ -69,7 +71,7 @@ class Reference {
|
||||||
required String name,
|
required String name,
|
||||||
required String target,
|
required String target,
|
||||||
required bool force,
|
required bool force,
|
||||||
required String logMessage,
|
String? logMessage,
|
||||||
}) {
|
}) {
|
||||||
_refPointer =
|
_refPointer =
|
||||||
bindings.createSymbolic(repo, name, target, force, logMessage);
|
bindings.createSymbolic(repo, name, target, force, logMessage);
|
||||||
|
@ -89,7 +91,7 @@ class Reference {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pointer to memory address for allocated reference object.
|
/// Pointer to memory address for allocated reference object.
|
||||||
late final Pointer<git_reference> _refPointer;
|
late Pointer<git_reference> _refPointer;
|
||||||
|
|
||||||
/// Checks if the reference [name] is well-formed.
|
/// Checks if the reference [name] is well-formed.
|
||||||
///
|
///
|
||||||
|
@ -129,6 +131,37 @@ class Reference {
|
||||||
return Oid(oidPointer);
|
return Oid(oidPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Conditionally creates a new reference with the same name as the given reference
|
||||||
|
/// but a different OID target.
|
||||||
|
///
|
||||||
|
/// The new reference will be written to disk, overwriting the given reference.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void setTarget(String target, [String? logMessage]) {
|
||||||
|
late final Oid oid;
|
||||||
|
|
||||||
|
if (isValidShaHex(target)) {
|
||||||
|
if (target.length == 40) {
|
||||||
|
oid = Oid.fromSHA(target);
|
||||||
|
} else {
|
||||||
|
final shortOid = Oid.fromSHAn(target);
|
||||||
|
final odb = Odb(repo_bindings.odb(owner));
|
||||||
|
oid = Oid(odb.existsPrefix(shortOid.pointer, target.length));
|
||||||
|
odb.free();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final ref = Reference(bindings.lookup(owner, target));
|
||||||
|
oid = ref.target;
|
||||||
|
ref.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ReferenceType.direct) {
|
||||||
|
_refPointer = bindings.setTarget(_refPointer, oid.pointer, logMessage);
|
||||||
|
} else {
|
||||||
|
_refPointer = bindings.setTargetSymbolic(_refPointer, target, logMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the full name of a reference.
|
/// Returns the full name of a reference.
|
||||||
String get name => bindings.name(_refPointer);
|
String get name => bindings.name(_refPointer);
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ class Repository {
|
||||||
required String name,
|
required String name,
|
||||||
required Object target,
|
required Object target,
|
||||||
bool force = false,
|
bool force = false,
|
||||||
String logMessage = '',
|
String? logMessage,
|
||||||
}) {
|
}) {
|
||||||
late final Oid oid;
|
late final Oid oid;
|
||||||
late final bool isDirect;
|
late final bool isDirect;
|
||||||
|
@ -186,7 +186,7 @@ class Repository {
|
||||||
if (target.runtimeType == Oid) {
|
if (target.runtimeType == Oid) {
|
||||||
oid = target as Oid;
|
oid = target as Oid;
|
||||||
isDirect = true;
|
isDirect = true;
|
||||||
} else if (_isValidShaHex(target as String)) {
|
} else if (isValidShaHex(target as String)) {
|
||||||
if (target.length == 40) {
|
if (target.length == 40) {
|
||||||
oid = Oid.fromSHA(target);
|
oid = Oid.fromSHA(target);
|
||||||
} else {
|
} else {
|
||||||
|
@ -252,10 +252,4 @@ class Repository {
|
||||||
///
|
///
|
||||||
/// Throws a [LibGit2Error] if error occured.
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
Odb get odb => Odb(bindings.odb(_repoPointer));
|
Odb get odb => Odb(bindings.odb(_repoPointer));
|
||||||
|
|
||||||
bool _isValidShaHex(String str) {
|
|
||||||
final hexRegExp = RegExp(r'^[0-9a-fA-F]+$');
|
|
||||||
return hexRegExp.hasMatch(str) &&
|
|
||||||
(GIT_OID_MINPREFIXLEN <= str.length && GIT_OID_HEXSZ >= str.length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,3 +19,9 @@ DynamicLibrary loadLibrary() {
|
||||||
}
|
}
|
||||||
|
|
||||||
final libgit2 = Libgit2(loadLibrary());
|
final libgit2 = Libgit2(loadLibrary());
|
||||||
|
|
||||||
|
bool isValidShaHex(String str) {
|
||||||
|
final hexRegExp = RegExp(r'^[0-9a-fA-F]+$');
|
||||||
|
return hexRegExp.hasMatch(str) &&
|
||||||
|
(GIT_OID_MINPREFIXLEN <= str.length && GIT_OID_HEXSZ >= str.length);
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'helpers/util.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const lastCommit = '78b8bf123e3952c970ae5c1ce0a3ea1d1336f6e8';
|
const lastCommit = '78b8bf123e3952c970ae5c1ce0a3ea1d1336f6e8';
|
||||||
|
const newCommit = 'c68ff54aabf660fcdd9a2838d401583fe31249e3';
|
||||||
|
|
||||||
group('Reference', () {
|
group('Reference', () {
|
||||||
late final Repository repo;
|
late final Repository repo;
|
||||||
|
@ -343,6 +344,50 @@ void main() {
|
||||||
ref.free();
|
ref.free();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('setTarget()', () {
|
||||||
|
test('successfully sets target with SHA hex', () {
|
||||||
|
final ref = repo.getReference('refs/heads/master');
|
||||||
|
ref.setTarget(newCommit);
|
||||||
|
expect(ref.target.sha, newCommit);
|
||||||
|
|
||||||
|
// change back for tests purpose
|
||||||
|
ref.setTarget(lastCommit);
|
||||||
|
ref.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully sets target with short SHA hex', () {
|
||||||
|
final ref = repo.getReference('refs/heads/master');
|
||||||
|
ref.setTarget(newCommit.substring(0, 5));
|
||||||
|
expect(ref.target.sha, newCommit);
|
||||||
|
|
||||||
|
// change back for tests purpose
|
||||||
|
ref.setTarget(lastCommit);
|
||||||
|
ref.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully sets symbolic target', () {
|
||||||
|
final ref = repo.getReference('HEAD');
|
||||||
|
expect(ref.target.sha, lastCommit);
|
||||||
|
|
||||||
|
ref.setTarget('refs/heads/feature');
|
||||||
|
expect(ref.target.sha, '5aecfa0fb97eadaac050ccb99f03c3fb65460ad4');
|
||||||
|
|
||||||
|
// change back for tests purpose
|
||||||
|
ref.setTarget('refs/heads/master');
|
||||||
|
ref.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws on invalid target', () {
|
||||||
|
final ref = repo.getReference('HEAD');
|
||||||
|
expect(
|
||||||
|
() => ref.setTarget('refs/heads/invalid~'),
|
||||||
|
throwsA(isA<LibGit2Error>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
ref.free();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group('isValidName()', () {
|
group('isValidName()', () {
|
||||||
test('returns true for valid names', () {
|
test('returns true for valid names', () {
|
||||||
expect(Reference.isValidName('HEAD'), true);
|
expect(Reference.isValidName('HEAD'), true);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue