From d0f7746a01f3c6a8dc393ee52bc4339b4e017311 Mon Sep 17 00:00:00 2001 From: Aleksey Kulikov Date: Sat, 19 Feb 2022 12:42:19 +0300 Subject: [PATCH] refactor(revparse)!: add ability to get different git objects based on spec (#46) --- lib/src/revparse.dart | 34 ++++++++++++++++++++++++++-------- test/revparse_test.dart | 31 +++++++++++++++++++++---------- test/worktree_test.dart | 2 +- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/lib/src/revparse.dart b/lib/src/revparse.dart index 4cb6793..0e2d617 100644 --- a/lib/src/revparse.dart +++ b/lib/src/revparse.dart @@ -1,6 +1,7 @@ import 'dart:ffi'; import 'package:libgit2dart/libgit2dart.dart'; import 'package:libgit2dart/src/bindings/libgit2_bindings.dart'; +import 'package:libgit2dart/src/bindings/object.dart' as object_bindings; import 'package:libgit2dart/src/bindings/revparse.dart' as bindings; class RevParse { @@ -40,18 +41,35 @@ class RevParse { /// See `man gitrevisions`, or https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions /// for information on the syntax accepted. /// + /// Returned object should be explicitly downcasted to one of four of git + /// object types. + /// + /// ```dart + /// final commit = RevParse.single(repo: repo, spec: 'HEAD') as Commit; + /// final tree = RevParse.single(repo: repo, spec: 'HEAD^{tree}') as Tree; + /// final blob = RevParse.single(repo: repo, spec: 'HEAD:file.txt') as Blob; + /// final tag = RevParse.single(repo: repo, spec: 'v1.0') as Tag; + /// ``` + /// /// **IMPORTANT**: Should be freed to release allocated memory. /// /// Throws a [LibGit2Error] if error occured. - static Commit single({required Repository repo, required String spec}) { - return Commit( - bindings - .revParseSingle( - repoPointer: repo.pointer, - spec: spec, - ) - .cast(), + static Object single({required Repository repo, required String spec}) { + final object = bindings.revParseSingle( + repoPointer: repo.pointer, + spec: spec, ); + final objectType = object_bindings.type(object); + + if (objectType == GitObject.commit.value) { + return Commit(object.cast()); + } else if (objectType == GitObject.tree.value) { + return Tree(object.cast()); + } else if (objectType == GitObject.blob.value) { + return Blob(object.cast()); + } else { + return Tag(object.cast()); + } } /// Parses a revision string for from, to, and intent. diff --git a/test/revparse_test.dart b/test/revparse_test.dart index 9f0df3e..80b07c4 100644 --- a/test/revparse_test.dart +++ b/test/revparse_test.dart @@ -23,19 +23,30 @@ void main() { }); group('revParse', () { - test('.single() returns commit with different spec strings', () { - final headCommit = RevParse.single(repo: repo, spec: 'HEAD'); - expect(headCommit.oid.sha, headSHA); + test('.single() returns correct objects with different spec strings', () { + final commit = RevParse.single(repo: repo, spec: 'HEAD') as Commit; + expect(commit, isA()); + expect(commit.oid.sha, headSHA); - final parentCommit = RevParse.single(repo: repo, spec: 'HEAD^'); - expect(parentCommit.oid.sha, parentSHA); + final tree = RevParse.single(repo: repo, spec: 'HEAD^{tree}') as Tree; + expect(tree, isA()); + expect(tree.length, isNonZero); - final initCommit = RevParse.single(repo: repo, spec: '@{-1}'); - expect(initCommit.oid.sha, '5aecfa0fb97eadaac050ccb99f03c3fb65460ad4'); + final blob = RevParse.single( + repo: repo, + spec: 'HEAD:feature_file', + ) as Blob; + expect(blob, isA()); + expect(blob.content, 'Feature edit\n'); - headCommit.free(); - parentCommit.free(); - initCommit.free(); + final tag = RevParse.single(repo: repo, spec: 'v0.2') as Tag; + expect(tag, isA()); + expect(tag.message, 'annotated tag\n'); + + commit.free(); + tree.free(); + blob.free(); + tag.free(); }); test('.single() throws when spec string not found or invalid', () { diff --git a/test/worktree_test.dart b/test/worktree_test.dart index 33b6735..d8b5c24 100644 --- a/test/worktree_test.dart +++ b/test/worktree_test.dart @@ -55,7 +55,7 @@ void main() { }); test('creates worktree at provided path from provided reference', () { - final head = RevParse.single(repo: repo, spec: 'HEAD'); + final head = RevParse.single(repo: repo, spec: 'HEAD') as Commit; final worktreeBranch = Branch.create( repo: repo, name: 'v1',