From cf677e488ad20caae6eed13df8737b74c89fa000 Mon Sep 17 00:00:00 2001 From: Aleksey Kulikov Date: Mon, 20 Sep 2021 13:03:43 +0300 Subject: [PATCH] refactor!: use IterableMixin where possible --- lib/src/index.dart | 36 +++++++++++++++++++++++++----- lib/src/reflog.dart | 47 +++++++++++++++++++++++++++------------- lib/src/tag.dart | 5 ++--- lib/src/tree.dart | 3 +-- test/commit_test.dart | 4 ++-- test/index_test.dart | 46 +++++++++++++++++++-------------------- test/reference_test.dart | 8 +++---- test/reflog_test.dart | 8 ++++--- 8 files changed, 100 insertions(+), 57 deletions(-) diff --git a/lib/src/index.dart b/lib/src/index.dart index 7bb826d..f45f4e0 100644 --- a/lib/src/index.dart +++ b/lib/src/index.dart @@ -1,3 +1,4 @@ +import 'dart:collection'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'package:libgit2dart/libgit2dart.dart'; @@ -10,7 +11,7 @@ import 'git_types.dart'; import 'repository.dart'; import 'util.dart'; -class Index { +class Index with IterableMixin { /// Initializes a new instance of [Index] class from provided /// pointer to index object in memory. /// @@ -36,10 +37,7 @@ class Index { } /// Checks whether entry at provided [path] is in the git index or not. - bool contains(String path) => bindings.find(_indexPointer, path); - - /// Returns the count of entries currently in the index. - int get count => bindings.entryCount(_indexPointer); + bool find(String path) => bindings.find(_indexPointer, path); /// Checks if the index contains entries representing file conflicts. bool get hasConflicts => bindings.hasConflicts(_indexPointer); @@ -232,6 +230,9 @@ class Index { /// Releases memory allocated for index object. void free() => bindings.free(_indexPointer); + + @override + Iterator get iterator => _IndexIterator(_indexPointer); } class IndexEntry { @@ -307,3 +308,28 @@ class ConflictEntry { String toString() => 'ConflictEntry{ancestor: $ancestor, our: $our, their: $their}'; } + +class _IndexIterator implements Iterator { + _IndexIterator(this._indexPointer) { + count = bindings.entryCount(_indexPointer); + } + + final Pointer _indexPointer; + IndexEntry? _currentEntry; + int _index = 0; + late final int count; + + @override + IndexEntry get current => _currentEntry!; + + @override + bool moveNext() { + if (_index == count) { + return false; + } else { + _currentEntry = IndexEntry(bindings.getByIndex(_indexPointer, _index)); + _index++; + return true; + } + } +} diff --git a/lib/src/reflog.dart b/lib/src/reflog.dart index 760f8fb..b67ad14 100644 --- a/lib/src/reflog.dart +++ b/lib/src/reflog.dart @@ -1,3 +1,4 @@ +import 'dart:collection'; import 'dart:ffi'; import 'bindings/libgit2_bindings.dart'; import 'bindings/reflog.dart' as bindings; @@ -5,7 +6,7 @@ import 'reference.dart'; import 'signature.dart'; import 'util.dart'; -class RefLog { +class RefLog with IterableMixin { /// Initializes a new instance of [RefLog] class from provided [Reference]. /// /// Throws a [LibGit2Error] if error occured. @@ -20,20 +21,6 @@ class RefLog { /// Pointer to memory address for allocated reflog object. late final Pointer _reflogPointer; - /// Returns a list with entries of reference log. - List get entries { - var log = []; - - for (var i = 0; i < count; i++) { - log.add(RefLogEntry(bindings.getByIndex(_reflogPointer, i))); - } - - return log; - } - - /// Returns the number of log entries in a reflog. - int get count => bindings.entryCount(_reflogPointer); - /// Lookup an entry by its index. /// /// Requesting the reflog entry with an index of 0 (zero) will return @@ -44,6 +31,9 @@ class RefLog { /// Releases memory allocated for reflog object. void free() => bindings.free(_reflogPointer); + + @override + Iterator get iterator => _RefLogIterator(_reflogPointer); } class RefLogEntry { @@ -62,3 +52,30 @@ class RefLogEntry { @override String toString() => 'ReflogEntry{message: $message}'; } + +class _RefLogIterator implements Iterator { + _RefLogIterator(this._reflogPointer) { + _count = bindings.entryCount(_reflogPointer); + } + + /// Pointer to memory address for allocated reflog object. + final Pointer _reflogPointer; + + RefLogEntry? _currentEntry; + int _index = 0; + late final int _count; + + @override + RefLogEntry get current => _currentEntry!; + + @override + bool moveNext() { + if (_index == _count) { + return false; + } else { + _currentEntry = RefLogEntry(bindings.getByIndex(_reflogPointer, _index)); + _index++; + return true; + } + } +} diff --git a/lib/src/tag.dart b/lib/src/tag.dart index 38841de..4f77016 100644 --- a/lib/src/tag.dart +++ b/lib/src/tag.dart @@ -1,15 +1,14 @@ import 'dart:ffi'; - -import 'package:libgit2dart/libgit2dart.dart'; - import 'bindings/libgit2_bindings.dart'; import 'bindings/tag.dart' as bindings; import 'bindings/object.dart' as object_bindings; +import 'blob.dart'; import 'commit.dart'; import 'oid.dart'; import 'repository.dart'; import 'signature.dart'; import 'git_types.dart'; +import 'tree.dart'; import 'util.dart'; class Tag { diff --git a/lib/src/tree.dart b/lib/src/tree.dart index c46997b..94829a2 100644 --- a/lib/src/tree.dart +++ b/lib/src/tree.dart @@ -49,8 +49,7 @@ class Tree { /// /// If string [value] is provided, lookup is done by entry filename. /// - /// If provided string [value] is a path to file, lookup is done by path. In that case - /// returned object should be freed explicitly. + /// If provided string [value] is a path to file, lookup is done by path. TreeEntry operator [](Object value) { if (value is int) { return TreeEntry(bindings.getByIndex(_treePointer, value)); diff --git a/test/commit_test.dart b/test/commit_test.dart index 3d14b27..e5e95ce 100644 --- a/test/commit_test.dart +++ b/test/commit_test.dart @@ -60,10 +60,10 @@ void main() { final to = repo['78b8bf123e3952c970ae5c1ce0a3ea1d1336f6e8'] as Commit; final from = repo['821ed6e80627b8769d170a293862f9fc60825226'] as Commit; final index = repo.index; - expect(index.contains('dir/dir_file.txt'), true); + expect(index.find('dir/dir_file.txt'), true); final revertIndex = repo.revertCommit(revertCommit: from, ourCommit: to); - expect(revertIndex.contains('dir/dir_file.txt'), false); + expect(revertIndex.find('dir/dir_file.txt'), false); revertIndex.free(); index.free(); diff --git a/test/index_test.dart b/test/index_test.dart index f8a6e67..6e3d629 100644 --- a/test/index_test.dart +++ b/test/index_test.dart @@ -32,7 +32,7 @@ void main() { const featureFileSha = '9c78c21d6680a7ffebc76f7ac68cacc11d8f48bc'; test('returns number of entries', () { - expect(index.count, 4); + expect(index.length, 4); }); test('returns mode of index entry', () { @@ -40,8 +40,8 @@ void main() { }); test('returns index entry at provided position', () { - expect(index[2].path, 'feature_file'); - expect(index['file'].sha, fileSha); + expect(index[3].path, 'file'); + expect(index[3].sha, fileSha); }); test('returns index entry at provided path', () { @@ -74,9 +74,9 @@ void main() { }); test('clears the contents', () { - expect(index.count, 4); + expect(index.length, 4); index.clear(); - expect(index.count, 0); + expect(index.length, 0); }); group('add()', () { @@ -85,13 +85,13 @@ void main() { index.add(entry); expect(index['file'].sha, fileSha); - expect(index.count, 4); + expect(index.length, 4); }); test('successfully adds with provided path string', () { index.add('file'); expect(index['file'].sha, fileSha); - expect(index.count, 4); + expect(index.length, 4); }); test('throws if file not found at provided path', () { @@ -114,27 +114,27 @@ void main() { index.clear(); index.addAll(['file', 'feature_file']); - expect(index.count, 2); + expect(index.length, 2); expect(index['file'].sha, fileSha); expect(index['feature_file'].sha, featureFileSha); index.clear(); index.addAll(['[f]*']); - expect(index.count, 2); + expect(index.length, 2); expect(index['file'].sha, fileSha); expect(index['feature_file'].sha, featureFileSha); index.clear(); index.addAll(['feature_f???']); - expect(index.count, 1); + expect(index.length, 1); expect(index['feature_file'].sha, featureFileSha); }); }); test('writes to disk', () { - expect(index.count, 4); + expect(index.length, 4); File('$tmpDir/new_file').createSync(); @@ -144,43 +144,43 @@ void main() { index.clear(); index.read(); expect(index['new_file'].path, 'new_file'); - expect(index.count, 5); + expect(index.length, 5); }); test('removes an entry', () { - expect(index.contains('feature_file'), true); + expect(index.find('feature_file'), true); index.remove('feature_file'); - expect(index.contains('feature_file'), false); + expect(index.find('feature_file'), false); }); test('removes all entries with matching pathspec', () { - expect(index.contains('file'), true); - expect(index.contains('feature_file'), true); + expect(index.find('file'), true); + expect(index.find('feature_file'), true); index.removeAll(['[f]*']); - expect(index.contains('file'), false); - expect(index.contains('feature_file'), false); + expect(index.find('file'), false); + expect(index.find('feature_file'), false); }); group('read tree', () { const treeSha = 'df2b8fc99e1c1d4dbc0a854d9f72157f1d6ea078'; test('successfully reads with provided SHA hex', () { - expect(index.count, 4); + expect(index.length, 4); index.readTree(treeSha); - expect(index.count, 1); + expect(index.length, 1); // make sure the index is only modified in memory index.read(); - expect(index.count, 4); + expect(index.length, 4); }); test('successfully reads with provided short SHA hex', () { - expect(index.count, 4); + expect(index.length, 4); index.readTree(treeSha.substring(0, 5)); - expect(index.count, 1); + expect(index.length, 1); }); }); diff --git a/test/reference_test.dart b/test/reference_test.dart index a03b7a0..792fa0b 100644 --- a/test/reference_test.dart +++ b/test/reference_test.dart @@ -343,7 +343,7 @@ void main() { test('returns log for reference', () { final ref = repo.references['refs/heads/master']; final reflog = ref.log; - expect(reflog.entries.last.message, 'commit (initial): init'); + expect(reflog.last.message, 'commit (initial): init'); reflog.free(); ref.free(); @@ -384,9 +384,9 @@ void main() { ref.setTarget('refs/heads/feature', 'log message'); expect(ref.target.sha, '5aecfa0fb97eadaac050ccb99f03c3fb65460ad4'); final reflog = ref.log; - expect(reflog.entries.first.message, 'log message'); - expect(reflog.entries.first.committer.name, 'name'); - expect(reflog.entries.first.committer.email, 'email'); + expect(reflog.first.message, 'log message'); + expect(reflog.first.committer.name, 'name'); + expect(reflog.first.committer.email, 'email'); reflog.free(); ref.free(); diff --git a/test/reflog_test.dart b/test/reflog_test.dart index 0e29f4c..e20b17c 100644 --- a/test/reflog_test.dart +++ b/test/reflog_test.dart @@ -7,6 +7,7 @@ import 'helpers/util.dart'; void main() { late Repository repo; late RefLog reflog; + late Reference head; final tmpDir = '${Directory.systemTemp.path}/reflog_testrepo/'; setUp(() async { @@ -18,12 +19,13 @@ void main() { to: await Directory(tmpDir).create(), ); repo = Repository.open(tmpDir); - reflog = RefLog(repo.head); + head = repo.head; + reflog = RefLog(head); }); tearDown(() async { - repo.head.free(); reflog.free(); + head.free(); repo.free(); await Directory(tmpDir).delete(recursive: true); }); @@ -33,7 +35,7 @@ void main() { }); test('returns correct number of log entries', () { - expect(reflog.count, 4); + expect(reflog.length, 4); }); test('returns the log message', () {