From 2c28fddcec0d80cbb5edb30f6494f5f5b9d51545 Mon Sep 17 00:00:00 2001 From: Aleksey Kulikov Date: Fri, 16 Jul 2021 21:17:51 +0300 Subject: [PATCH] feat(oid): add base bindings and api --- lib/src/bindings/oid.dart | 44 +++++++++++++++++++++++++++++ lib/src/oid.dart | 58 +++++++++++++++++++++++++++++++++++++++ test/oid_test.dart | 47 +++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 lib/src/bindings/oid.dart create mode 100644 lib/src/oid.dart create mode 100644 test/oid_test.dart diff --git a/lib/src/bindings/oid.dart b/lib/src/bindings/oid.dart new file mode 100644 index 0000000..29ad2f8 --- /dev/null +++ b/lib/src/bindings/oid.dart @@ -0,0 +1,44 @@ +import 'dart:ffi'; +import 'package:ffi/ffi.dart'; +import '../error.dart'; +import 'libgit2_bindings.dart'; +import '../util.dart'; + +/// Parse a hex formatted object id into a git_oid. +/// +/// Throws a [LibGit2Error] if error occured. +Pointer fromSHA(String hex) { + final out = calloc(); + final str = hex.toNativeUtf8().cast(); + final error = libgit2.git_oid_fromstr(out, str); + calloc.free(str); + + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } else { + return out; + } +} + +/// Format a git_oid into a hex string. +/// +/// Throws a [LibGit2Error] if error occured. +String toSHA(Pointer id) { + final out = calloc.allocate(40); + final error = libgit2.git_oid_fmt(out, id); + final result = out.cast().toDartString(length: 40); + malloc.free(out); + + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } else { + return result; + } +} + +/// Compare two oid structures. +/// +/// Returns <0 if a < b, 0 if a == b, >0 if a > b. +int compare(Pointer a, Pointer b) { + return libgit2.git_oid_cmp(a, b); +} diff --git a/lib/src/oid.dart b/lib/src/oid.dart new file mode 100644 index 0000000..6801f28 --- /dev/null +++ b/lib/src/oid.dart @@ -0,0 +1,58 @@ +import 'dart:ffi'; +import 'bindings/libgit2_bindings.dart'; +import 'bindings/oid.dart' as bindings; +import 'util.dart'; + +class Oid { + /// Initializes a new instance of [Oid] class from provided + /// hexadecimal [sha] string. + /// + /// Throws a [LibGit2Error] if error occured. + Oid.fromSHA(String sha) { + libgit2.git_libgit2_init(); + + try { + _oidPointer = bindings.fromSHA(sha); + } catch (e) { + rethrow; + } + } + + /// Pointer to memory address for allocated oid object. + late Pointer _oidPointer; + + /// Returns hexadecimal SHA-1 string. + String get sha { + try { + return bindings.toSHA(_oidPointer); + } catch (e) { + rethrow; + } + } + + @override + bool operator ==(other) { + return (other is Oid) && + (bindings.compare(_oidPointer, other._oidPointer) == 0); + } + + bool operator <(other) { + return (other is Oid) && + (bindings.compare(_oidPointer, other._oidPointer) == -1); + } + + bool operator <=(other) { + return (other is Oid) && + (bindings.compare(_oidPointer, other._oidPointer) == -1); + } + + bool operator >(other) { + return (other is Oid) && + (bindings.compare(_oidPointer, other._oidPointer) == 1); + } + + bool operator >=(other) { + return (other is Oid) && + (bindings.compare(_oidPointer, other._oidPointer) == 1); + } +} diff --git a/test/oid_test.dart b/test/oid_test.dart new file mode 100644 index 0000000..6e6607e --- /dev/null +++ b/test/oid_test.dart @@ -0,0 +1,47 @@ +import 'package:test/test.dart'; +import 'package:libgit2dart/src/oid.dart'; +import 'package:libgit2dart/src/error.dart'; + +void main() { + const sha = '9d81c715ff606057fa448e558c7458467a86c8c7'; + + group('Oid', () { + group('fromSHA()', () { + test('initializes successfully', () { + expect(Oid.fromSHA(sha), isA()); + }); + + test('throws when hex string is lesser than 40 characters', () { + expect(() => Oid.fromSHA('9d8'), throwsA(isA())); + }); + }); + + test('returns sha hex string', () { + final oid = Oid.fromSHA(sha); + final hex = oid.sha; + expect(hex, equals(sha)); + }); + + group('compare', () { + test('< and <=', () { + final oid1 = Oid.fromSHA(sha); + final oid2 = Oid.fromSHA('9d81c715ff606057fa448e558c7458467a86c8c8'); + expect(oid1 < oid2, true); + expect(oid1 <= oid2, true); + }); + + test('==', () { + final oid1 = Oid.fromSHA(sha); + final oid2 = Oid.fromSHA(sha); + expect(oid1 == oid2, true); + }); + + test('> and >=', () { + final oid1 = Oid.fromSHA(sha); + final oid2 = Oid.fromSHA('9d81c715ff606057fa448e558c7458467a86c8c6'); + expect(oid1 > oid2, true); + expect(oid1 >= oid2, true); + }); + }); + }); +}