diff --git a/lib/src/bindings/reference.dart b/lib/src/bindings/reference.dart index 3f96aec..b179254 100644 --- a/lib/src/bindings/reference.dart +++ b/lib/src/bindings/reference.dart @@ -14,6 +14,28 @@ int referenceType(Pointer ref) => Pointer? target(Pointer ref) => libgit2.git_reference_target(ref); +/// Resolve a symbolic reference to a direct reference. +/// +/// This method iteratively peels a symbolic reference until it resolves +/// to a direct reference to an OID. +/// +/// The peeled reference must be freed manually once it's no longer needed. +/// +/// If a direct reference is passed as an argument, a copy of that reference is returned. +/// This copy must be manually freed too. +/// +/// Throws a [LibGit2Error] if error occured. +Pointer resolve(Pointer ref) { + final out = calloc>(); + final error = libgit2.git_reference_resolve(out, ref); + + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } else { + return out.value; + } +} + /// Lookup a reference by name in a repository. /// /// The returned reference must be freed by the user. diff --git a/lib/src/reference.dart b/lib/src/reference.dart index be58273..c04b7b1 100644 --- a/lib/src/reference.dart +++ b/lib/src/reference.dart @@ -60,18 +60,18 @@ class Reference { : ReferenceType.symbolic; } - /// Returns the SHA hex of the OID pointed to by a direct reference. - /// - /// Only available if the reference is direct (i.e. an object id reference, not a symbolic one). + /// Returns the SHA hex of the OID pointed to by a reference. String get target { - final oidPointer = bindings.target(_refPointer); + late final Pointer? oidPointer; final sha = ''; - if (oidPointer == nullptr) { - return sha; + + if (type == ReferenceType.direct) { + oidPointer = bindings.target(_refPointer); } else { - final oid = Oid(oidPointer!); - return oid.sha; + oidPointer = bindings.target(bindings.resolve(_refPointer)); } + + return oidPointer == nullptr ? sha : Oid(oidPointer!).sha; } /// Returns the full name of a reference. diff --git a/test/reference_test.dart b/test/reference_test.dart index 1c65343..05bf714 100644 --- a/test/reference_test.dart +++ b/test/reference_test.dart @@ -33,6 +33,10 @@ void main() { test('returns correct type of reference', () { expect(repo.head.type, ReferenceType.direct); repo.head.free(); + + final ref = Reference.lookup(repo, 'HEAD'); + expect(ref.type, ReferenceType.symbolic); + ref.free(); }); test('returns SHA hex of direct reference', () { @@ -40,6 +44,12 @@ void main() { repo.head.free(); }); + test('returns SHA hex of symbolic reference', () { + final ref = Reference.lookup(repo, 'HEAD'); + expect(ref.target, lastCommit); + ref.free(); + }); + test('returns the full name of a reference', () { expect(repo.head.name, 'refs/heads/master'); repo.head.free();