From d6eae1e9ed8677291b958b2cd0845fcfed730cb5 Mon Sep 17 00:00:00 2001 From: Aleksey Kulikov Date: Fri, 15 Oct 2021 17:37:38 +0300 Subject: [PATCH] test: improve coverage --- lib/src/bindings/diff.dart | 47 ++++++-- lib/src/bindings/merge.dart | 8 +- lib/src/bindings/reference.dart | 4 + lib/src/bindings/tree.dart | 4 +- lib/src/blame.dart | 4 - lib/src/credentials.dart | 5 +- lib/src/error.dart | 8 +- lib/src/index.dart | 4 +- lib/src/mailmap.dart | 8 +- lib/src/oid.dart | 4 +- lib/src/packbuilder.dart | 4 +- lib/src/rebase.dart | 14 +-- lib/src/reference.dart | 40 +++---- lib/src/reflog.dart | 2 +- lib/src/remote.dart | 4 - lib/src/repository.dart | 13 ++- lib/src/signature.dart | 5 +- lib/src/submodule.dart | 8 +- lib/src/tag.dart | 4 +- lib/src/tree.dart | 46 +------- lib/src/treebuilder.dart | 4 +- lib/src/util.dart | 16 +-- test/assets/mergerepo/.gitdir/COMMIT_EDITMSG | 2 +- test/assets/mergerepo/.gitdir/index | Bin 485 -> 485 bytes test/assets/mergerepo/.gitdir/logs/HEAD | 11 ++ .../.gitdir/logs/refs/heads/ancestor-conflict | 2 + .../mergerepo/.gitdir/logs/refs/heads/feature | 1 + .../.gitdir/logs/refs/heads/our-conflict | 2 + .../.gitdir/logs/refs/heads/their-conflict | 2 + .../0d/b17b23a1acd67d5e44650d61aac7d4d83ec193 | Bin 0 -> 175 bytes .../0e/409d66f701eea5038fe508ead4c098da699d2c | 2 + .../1e/a09ccce9682b1424ae282d060421876bad7f18 | Bin 0 -> 37 bytes .../2e/e89b2f7124b8e4632bc6a20774a90b795245e4 | Bin 0 -> 176 bytes .../76/06a0d606a74ee5f0761c6e358c2f90405c94ad | Bin 0 -> 176 bytes .../d8/ab96fc96ed0a33b98895e7c5434fe9ee195082 | Bin 0 -> 95 bytes .../d9/9d64a90db7f69fa8cff8c7b01fba011379165f | Bin 0 -> 41 bytes .../dd/20ffc2e349da86f4c5dda87ac8d1602e063f54 | Bin 0 -> 96 bytes .../de/1b22b432b74b48b7dc38bb135ae20abc69ddd8 | Bin 0 -> 69 bytes .../.gitdir/refs/heads/ancestor-conflict | 1 + .../mergerepo/.gitdir/refs/heads/feature | 2 +- .../mergerepo/.gitdir/refs/heads/our-conflict | 1 + .../.gitdir/refs/heads/their-conflict | 1 + test/blame_test.dart | 6 + test/blob_test.dart | 28 +++-- test/branch_test.dart | 6 + test/commit_test.dart | 6 + test/credentials_test.dart | 5 + test/describe_test.dart | 9 ++ test/diff_test.dart | 46 ++++++-- test/helpers/util.dart | 3 +- test/index_test.dart | 103 +++++++++++++++++- test/mailmap_test.dart | 20 ++++ test/merge_test.dart | 38 ++++++- test/note_test.dart | 6 + test/odb_test.dart | 23 ++-- test/oid_test.dart | 17 +++ test/packbuilder_test.dart | 13 ++- test/patch_test.dart | 13 +++ test/rebase_test.dart | 8 +- test/reference_test.dart | 75 +++++++------ test/reflog_test.dart | 4 + test/remote_test.dart | 5 + test/repository_test.dart | 29 +++++ test/revparse_test.dart | 2 + test/signature_test.dart | 4 + test/stash_test.dart | 73 ++++++++++++- test/submodule_test.dart | 5 + test/tag_test.dart | 101 ++++++++++++++++- test/tree_test.dart | 6 + test/treebuilder_test.dart | 1 + test/worktree_test.dart | 1 + 71 files changed, 710 insertions(+), 229 deletions(-) create mode 100644 test/assets/mergerepo/.gitdir/logs/refs/heads/ancestor-conflict create mode 100644 test/assets/mergerepo/.gitdir/logs/refs/heads/our-conflict create mode 100644 test/assets/mergerepo/.gitdir/logs/refs/heads/their-conflict create mode 100644 test/assets/mergerepo/.gitdir/objects/0d/b17b23a1acd67d5e44650d61aac7d4d83ec193 create mode 100644 test/assets/mergerepo/.gitdir/objects/0e/409d66f701eea5038fe508ead4c098da699d2c create mode 100644 test/assets/mergerepo/.gitdir/objects/1e/a09ccce9682b1424ae282d060421876bad7f18 create mode 100644 test/assets/mergerepo/.gitdir/objects/2e/e89b2f7124b8e4632bc6a20774a90b795245e4 create mode 100644 test/assets/mergerepo/.gitdir/objects/76/06a0d606a74ee5f0761c6e358c2f90405c94ad create mode 100644 test/assets/mergerepo/.gitdir/objects/d8/ab96fc96ed0a33b98895e7c5434fe9ee195082 create mode 100644 test/assets/mergerepo/.gitdir/objects/d9/9d64a90db7f69fa8cff8c7b01fba011379165f create mode 100644 test/assets/mergerepo/.gitdir/objects/dd/20ffc2e349da86f4c5dda87ac8d1602e063f54 create mode 100644 test/assets/mergerepo/.gitdir/objects/de/1b22b432b74b48b7dc38bb135ae20abc69ddd8 create mode 100644 test/assets/mergerepo/.gitdir/refs/heads/ancestor-conflict create mode 100644 test/assets/mergerepo/.gitdir/refs/heads/our-conflict create mode 100644 test/assets/mergerepo/.gitdir/refs/heads/their-conflict diff --git a/lib/src/bindings/diff.dart b/lib/src/bindings/diff.dart index 7033552..9856959 100644 --- a/lib/src/bindings/diff.dart +++ b/lib/src/bindings/diff.dart @@ -21,7 +21,16 @@ Pointer indexToWorkdir({ interhunkLines: interhunkLines, ); - libgit2.git_diff_index_to_workdir(out, repoPointer, indexPointer, opts); + final error = libgit2.git_diff_index_to_workdir( + out, + repoPointer, + indexPointer, + opts, + ); + + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } calloc.free(opts); @@ -46,7 +55,7 @@ Pointer treeToIndex({ interhunkLines: interhunkLines, ); - libgit2.git_diff_tree_to_index( + final error = libgit2.git_diff_tree_to_index( out, repoPointer, treePointer, @@ -54,6 +63,10 @@ Pointer treeToIndex({ opts, ); + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } + calloc.free(opts); return out.value; @@ -76,7 +89,16 @@ Pointer treeToWorkdir({ interhunkLines: interhunkLines, ); - libgit2.git_diff_tree_to_workdir(out, repoPointer, treePointer, opts); + final error = libgit2.git_diff_tree_to_workdir( + out, + repoPointer, + treePointer, + opts, + ); + + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } calloc.free(opts); @@ -101,7 +123,7 @@ Pointer treeToTree({ interhunkLines: interhunkLines, ); - libgit2.git_diff_tree_to_tree( + final error = libgit2.git_diff_tree_to_tree( out, repoPointer, oldTreePointer, @@ -109,6 +131,10 @@ Pointer treeToTree({ opts, ); + if (error < 0) { + throw LibGit2Error(libgit2.git_error_last()); + } + calloc.free(opts); return out.value; @@ -351,15 +377,18 @@ Pointer _diffOptionsInit({ required int interhunkLines, }) { final opts = calloc(); - final optsError = - libgit2.git_diff_options_init(opts, GIT_DIFF_OPTIONS_VERSION); - opts.ref.flags = flags; - opts.ref.context_lines = contextLines; - opts.ref.interhunk_lines = interhunkLines; + final optsError = libgit2.git_diff_options_init( + opts, + GIT_DIFF_OPTIONS_VERSION, + ); if (optsError < 0) { + calloc.free(opts); throw LibGit2Error(libgit2.git_error_last()); } else { + opts.ref.flags = flags; + opts.ref.context_lines = contextLines; + opts.ref.interhunk_lines = interhunkLines; return opts; } } diff --git a/lib/src/bindings/merge.dart b/lib/src/bindings/merge.dart index a589a0a..7c73614 100644 --- a/lib/src/bindings/merge.dart +++ b/lib/src/bindings/merge.dart @@ -120,16 +120,16 @@ void merge({ String mergeFileFromIndex({ required Pointer repoPointer, required Pointer? ancestorPointer, - required Pointer? oursPointer, - required Pointer? theirsPointer, + required Pointer oursPointer, + required Pointer theirsPointer, }) { final out = calloc(); final error = libgit2.git_merge_file_from_index( out, repoPointer, ancestorPointer ?? nullptr, - oursPointer ?? nullptr, - theirsPointer ?? nullptr, + oursPointer, + theirsPointer, nullptr, ); diff --git a/lib/src/bindings/reference.dart b/lib/src/bindings/reference.dart index f35b5d5..8555ca2 100644 --- a/lib/src/bindings/reference.dart +++ b/lib/src/bindings/reference.dart @@ -235,6 +235,8 @@ bool isTag(Pointer ref) { /// /// 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 it does not have a reflog. +/// +/// Throws a [LibGit2Error] if error occured. Pointer createDirect({ required Pointer repoPointer, required String name, @@ -288,6 +290,8 @@ Pointer createDirect({ /// /// 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 it does not have a reflog. +/// +/// Throws a [LibGit2Error] if error occured. Pointer createSymbolic({ required Pointer repoPointer, required String name, diff --git a/lib/src/bindings/tree.dart b/lib/src/bindings/tree.dart index d71be43..1ca3889 100644 --- a/lib/src/bindings/tree.dart +++ b/lib/src/bindings/tree.dart @@ -73,7 +73,7 @@ Pointer getByName({ /// Retrieve a tree entry contained in a tree or in any of its subtrees, given its relative path. /// /// Unlike the other lookup functions, the returned tree entry is owned by the user and must be -/// freed explicitly with `entryFree()`. +/// freed explicitly with [entryFree]. /// /// Throws a [LibGit2Error] if error occured. Pointer getByPath({ @@ -122,7 +122,7 @@ int compare({ /// Free a user-owned tree entry. /// /// IMPORTANT: This function is only needed for tree entries owned by the user, -/// such as `getByPath()`. +/// such as [getByPath]. void entryFree(Pointer entry) => libgit2.git_tree_entry_free(entry); diff --git a/lib/src/blame.dart b/lib/src/blame.dart index dc8dd4b..4bf48cc 100644 --- a/lib/src/blame.dart +++ b/lib/src/blame.dart @@ -6,10 +6,6 @@ import 'bindings/libgit2_bindings.dart'; import 'bindings/blame.dart' as bindings; class Blame with IterableMixin { - /// Initializes a new instance of the [Blame] class from - /// provided pointer to blame object in memory. - Blame(this._blamePointer); - /// Initializes a new instance of the [Blame] class by getting /// the blame for a single file. /// diff --git a/lib/src/credentials.dart b/lib/src/credentials.dart index f580dba..705fbcf 100644 --- a/lib/src/credentials.dart +++ b/lib/src/credentials.dart @@ -78,6 +78,9 @@ class KeypairFromAgent implements Credentials { @override GitCredential get credentialType => GitCredential.sshKey; + + @override + String toString() => 'KeypairFromAgent{username: $username}'; } /// Ssh key credential used for reading the keys from memory. @@ -106,7 +109,7 @@ class KeypairFromMemory implements Credentials { @override String toString() { - return 'KeypairFromAgent{username: $username, pubKey: $pubKey, privateKey: $privateKey, ' + return 'KeypairFromMemory{username: $username, pubKey: $pubKey, privateKey: $privateKey, ' 'passPhrase: $passPhrase}'; } } diff --git a/lib/src/error.dart b/lib/src/error.dart index 8fdfb20..b62bddc 100644 --- a/lib/src/error.dart +++ b/lib/src/error.dart @@ -2,12 +2,14 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'bindings/libgit2_bindings.dart'; +/// Details of the last error that occurred. class LibGit2Error { - LibGit2Error(this.errorPointer); - final Pointer errorPointer; + LibGit2Error(this._errorPointer); + + final Pointer _errorPointer; @override String toString() { - return errorPointer.ref.message.cast().toDartString(); + return _errorPointer.ref.message.cast().toDartString(); } } diff --git a/lib/src/index.dart b/lib/src/index.dart index 4108ce1..ee7353e 100644 --- a/lib/src/index.dart +++ b/lib/src/index.dart @@ -67,9 +67,7 @@ class Index with IterableMixin { ? their = null : their = IndexEntry(entry['their']!); - if (ancestor != null) { - path = ancestor.path; - } else if (our != null) { + if (our != null) { path = our.path; } else { path = their!.path; diff --git a/lib/src/mailmap.dart b/lib/src/mailmap.dart index 614130c..79ccc6b 100644 --- a/lib/src/mailmap.dart +++ b/lib/src/mailmap.dart @@ -5,10 +5,6 @@ import 'bindings/mailmap.dart' as bindings; import 'util.dart'; class Mailmap { - /// Initializes a new instance of [Mailmap] class from provided - /// pointer to mailmap object in memory. - Mailmap(this._mailmapPointer); - /// Initializes a new instance of [Mailmap] class. /// /// This object is empty, so you'll have to add a mailmap file before you can @@ -49,10 +45,8 @@ class Mailmap { _mailmapPointer = bindings.fromRepository(repo.pointer); } - late final Pointer _mailmapPointer; - /// Pointer to memory address for allocated mailmap object. - Pointer get pointer => _mailmapPointer; + late final Pointer _mailmapPointer; /// Returns list containing resolved [name] and [email] to the corresponding real name /// and real email respectively. diff --git a/lib/src/oid.dart b/lib/src/oid.dart index 636855c..2d386dd 100644 --- a/lib/src/oid.dart +++ b/lib/src/oid.dart @@ -79,8 +79,8 @@ class Oid { 1); } - @override - int get hashCode => _oidPointer.address.hashCode; + @override // coverage:ignore-line + int get hashCode => _oidPointer.address.hashCode; // coverage:ignore-line @override String toString() => 'Oid{sha: $sha}'; diff --git a/lib/src/packbuilder.dart b/lib/src/packbuilder.dart index 83f9fae..e873723 100644 --- a/lib/src/packbuilder.dart +++ b/lib/src/packbuilder.dart @@ -13,10 +13,8 @@ class PackBuilder { _packbuilderPointer = bindings.init(repo.pointer); } - late final Pointer _packbuilderPointer; - /// Pointer to memory address for allocated packbuilder object. - Pointer get pointer => _packbuilderPointer; + late final Pointer _packbuilderPointer; /// Adds a single object. /// diff --git a/lib/src/rebase.dart b/lib/src/rebase.dart index 0b943fb..87c56d7 100644 --- a/lib/src/rebase.dart +++ b/lib/src/rebase.dart @@ -1,5 +1,4 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; import 'package:libgit2dart/libgit2dart.dart'; import 'bindings/libgit2_bindings.dart'; import 'bindings/rebase.dart' as bindings; @@ -80,7 +79,7 @@ class Rebase { } /// Commits the current patch. You must have resolved any conflicts that were - /// introduced during the patch application from the `next()` invocation. + /// introduced during the patch application from the [next] invocation. /// /// Throws a [LibGit2Error] if error occured. void commit({ @@ -126,18 +125,9 @@ class RebaseOperation { ); } - /// Returns the commit [Oid] being cherry-picked. This will be populated for - /// all operations except those of type [GitRebaseOperation.exec]. + /// Returns the commit [Oid] being cherry-picked. Oid get oid => Oid.fromRaw(_rebaseOperationPointer.ref.id); - /// The executable the user has requested be run. This will only - /// be populated for operations of type [GitRebaseOperation.exec]. - String get exec { - return _rebaseOperationPointer.ref.exec == nullptr - ? '' - : _rebaseOperationPointer.ref.exec.cast().toDartString(); - } - @override String toString() => 'RebaseOperation{type: $type, oid: $oid}'; } diff --git a/lib/src/reference.dart b/lib/src/reference.dart index 82a1085..5adf45c 100644 --- a/lib/src/reference.dart +++ b/lib/src/reference.dart @@ -5,7 +5,6 @@ import 'bindings/reference.dart' as bindings; import 'bindings/object.dart' as object_bindings; import 'bindings/refdb.dart' as refdb_bindings; import 'bindings/repository.dart' as repository_bindings; -import 'util.dart'; class Reference { /// Initializes a new instance of the [Reference] class. @@ -30,6 +29,9 @@ class Reference { /// /// The [logMessage] message for the reflog will be ignored if the reference does not belong in the /// standard set (HEAD, branches and remote-tracking branches) and it does not have a reflog. + /// + /// Throws a [LibGit2Error] if error occured or [ArgumentError] if provided [target] + /// is not Oid or String reference name. Reference.create({ required Repository repo, required String name, @@ -37,35 +39,25 @@ class Reference { bool force = false, String? logMessage, }) { - late final Oid oid; - late final bool isDirect; - if (target is Oid) { - oid = target; - isDirect = true; - } else if (isValidShaHex(target as String)) { - oid = Oid.fromSHA(repo: repo, sha: target); - isDirect = true; - } else { - isDirect = false; - } - - if (isDirect) { _refPointer = bindings.createDirect( repoPointer: repo.pointer, name: name, - oidPointer: oid.pointer, + oidPointer: target.pointer, + force: force, + logMessage: logMessage, + ); + } else if (target is String) { + _refPointer = bindings.createSymbolic( + repoPointer: repo.pointer, + name: name, + target: target, force: force, logMessage: logMessage, ); } else { - _refPointer = bindings.createSymbolic( - repoPointer: repo.pointer, - name: name, - target: target as String, - force: force, - logMessage: logMessage, - ); + throw ArgumentError.value( + '$target must be either Oid or String reference name'); } } @@ -275,8 +267,8 @@ class Reference { /// Releases memory allocated for reference object. void free() => bindings.free(_refPointer); - @override - int get hashCode => _refPointer.address.hashCode; + @override // coverage:ignore-line + int get hashCode => _refPointer.address.hashCode; // coverage:ignore-line @override String toString() { diff --git a/lib/src/reflog.dart b/lib/src/reflog.dart index eb8c183..96d47b0 100644 --- a/lib/src/reflog.dart +++ b/lib/src/reflog.dart @@ -50,7 +50,7 @@ class RefLogEntry { Signature get committer => Signature(bindings.entryCommiter(_entryPointer)); @override - String toString() => 'ReflogEntry{message: $message, committer: $committer}'; + String toString() => 'RefLogEntry{message: $message, committer: $committer}'; } class _RefLogIterator implements Iterator { diff --git a/lib/src/remote.dart b/lib/src/remote.dart index 5a9844c..ef24f86 100644 --- a/lib/src/remote.dart +++ b/lib/src/remote.dart @@ -4,10 +4,6 @@ import 'bindings/libgit2_bindings.dart'; import 'bindings/remote.dart' as bindings; class Remote { - /// Initializes a new instance of [Remote] class from provided pointer - /// to remote object in memory. - Remote(this._remotePointer); - /// Initializes a new instance of [Remote] class by looking up remote with /// provided [name] in a [repo]sitory. /// diff --git a/lib/src/repository.dart b/lib/src/repository.dart index 6a72f33..022897e 100644 --- a/lib/src/repository.dart +++ b/lib/src/repository.dart @@ -375,6 +375,9 @@ class Repository { /// /// The [logMessage] message for the reflog will be ignored if the reference does not belong in the /// standard set (HEAD, branches and remote-tracking branches) and it does not have a reflog. + /// + /// Throws a [LibGit2Error] if error occured or [ArgumentError] if provided [target] + /// is not Oid or String reference name. Reference createReference({ required String name, required Object target, @@ -838,14 +841,14 @@ class Repository { /// Throws a [LibGit2Error] if error occured. String mergeFileFromIndex({ required IndexEntry? ancestor, - required IndexEntry? ours, - required IndexEntry? theirs, + required IndexEntry ours, + required IndexEntry theirs, }) { return merge_bindings.mergeFileFromIndex( repoPointer: _repoPointer, ancestorPointer: ancestor?.pointer, - oursPointer: ours?.pointer, - theirsPointer: theirs?.pointer, + oursPointer: ours.pointer, + theirsPointer: theirs.pointer, ); } @@ -1435,7 +1438,7 @@ class Repository { bool? alwaysUseLongFormat, String? dirtySuffix, }) { - late final Pointer describeResult; + Pointer describeResult = nullptr; if (commit != null) { describeResult = describe_bindings.commit( diff --git a/lib/src/signature.dart b/lib/src/signature.dart index 0324d1d..b3938c4 100644 --- a/lib/src/signature.dart +++ b/lib/src/signature.dart @@ -78,8 +78,9 @@ class Signature { /// Releases memory allocated for signature object. void free() => bindings.free(_signaturePointer); - @override - int get hashCode => _signaturePointer.address.hashCode; + @override // coverage:ignore-line + int get hashCode => + _signaturePointer.address.hashCode; // coverage:ignore-line @override String toString() { diff --git a/lib/src/submodule.dart b/lib/src/submodule.dart index c095924..64077f5 100644 --- a/lib/src/submodule.dart +++ b/lib/src/submodule.dart @@ -4,10 +4,6 @@ import 'bindings/libgit2_bindings.dart'; import 'bindings/submodule.dart' as bindings; class Submodule { - /// Initializes a new instance of [Submodule] class from provided - /// pointer to submodule object in memory. - Submodule(this._submodulePointer); - /// Initializes a new instance of [Submodule] class by looking up /// submodule information by name or path. /// @@ -53,10 +49,8 @@ class Submodule { bindings.addFinalize(_submodulePointer); } - late final Pointer _submodulePointer; - /// Pointer to memory address for allocated submodule object. - Pointer get pointer => _submodulePointer; + late final Pointer _submodulePointer; /// Copies submodule info into ".git/config" file. /// diff --git a/lib/src/tag.dart b/lib/src/tag.dart index 8cf8ac9..1631382 100644 --- a/lib/src/tag.dart +++ b/lib/src/tag.dart @@ -21,10 +21,8 @@ class Tag { ); } - late final Pointer _tagPointer; - /// Pointer to memory address for allocated tag object. - Pointer get pointer => _tagPointer; + late final Pointer _tagPointer; /// Creates a new tag in the repository for provided [target] object. /// diff --git a/lib/src/tree.dart b/lib/src/tree.dart index 8dfb894..602f953 100644 --- a/lib/src/tree.dart +++ b/lib/src/tree.dart @@ -40,7 +40,7 @@ class Tree { return result; } - /// Looksup a tree entry in the tree. + /// Lookups a tree entry in the tree. /// /// If integer [value] is provided, lookup is done by entry position in the tree. /// @@ -158,53 +158,9 @@ class TreeEntry { return GitFilemode.values.singleWhere((mode) => modeInt == mode.value); } - @override - bool operator ==(other) { - return (other is TreeEntry) && - (bindings.compare( - aPointer: _treeEntryPointer, - bPointer: other._treeEntryPointer) == - 0); - } - - bool operator <(other) { - return (other is TreeEntry) && - (bindings.compare( - aPointer: _treeEntryPointer, - bPointer: other._treeEntryPointer) == - -1); - } - - bool operator <=(other) { - return (other is TreeEntry) && - (bindings.compare( - aPointer: _treeEntryPointer, - bPointer: other._treeEntryPointer) == - -1); - } - - bool operator >(other) { - return (other is TreeEntry) && - (bindings.compare( - aPointer: _treeEntryPointer, - bPointer: other._treeEntryPointer) == - 1); - } - - bool operator >=(other) { - return (other is TreeEntry) && - (bindings.compare( - aPointer: _treeEntryPointer, - bPointer: other._treeEntryPointer) == - 1); - } - /// Releases memory allocated for tree entry object. void free() => bindings.entryFree(_treeEntryPointer); - @override - int get hashCode => _treeEntryPointer.address.hashCode; - @override String toString() => 'TreeEntry{oid: $oid, name: $name, filemode: $filemode}'; } diff --git a/lib/src/treebuilder.dart b/lib/src/treebuilder.dart index 6caab11..efd0027 100644 --- a/lib/src/treebuilder.dart +++ b/lib/src/treebuilder.dart @@ -17,10 +17,8 @@ class TreeBuilder { ); } - late final Pointer _treeBuilderPointer; - /// Pointer to memory address for allocated tree builder object. - Pointer get pointer => _treeBuilderPointer; + late final Pointer _treeBuilderPointer; /// Returns the number of entries listed in a tree builder. int get length => bindings.entryCount(_treeBuilderPointer); diff --git a/lib/src/util.dart b/lib/src/util.dart index c44b4db..973abb8 100644 --- a/lib/src/util.dart +++ b/lib/src/util.dart @@ -7,14 +7,14 @@ DynamicLibrary loadLibrary() { return DynamicLibrary.open( '${Directory.current.path}/libgit2/libgit2.so.1.3.0'); } - if (Platform.isMacOS) { - return DynamicLibrary.open( - '${Directory.current.path}/libgit2/libgit2-1.2.0.dylib'); - } - if (Platform.isWindows) { - return DynamicLibrary.open( - '${Directory.current.path}/libgit2/libgit2-1.2.0.dll'); - } + // if (Platform.isMacOS) { + // return DynamicLibrary.open( + // '${Directory.current.path}/libgit2/libgit2-1.2.0.dylib'); + // } + // if (Platform.isWindows) { + // return DynamicLibrary.open( + // '${Directory.current.path}/libgit2/libgit2-1.2.0.dll'); + // } throw Exception('Platform not implemented'); } diff --git a/test/assets/mergerepo/.gitdir/COMMIT_EDITMSG b/test/assets/mergerepo/.gitdir/COMMIT_EDITMSG index d87a0dd..a23963d 100644 --- a/test/assets/mergerepo/.gitdir/COMMIT_EDITMSG +++ b/test/assets/mergerepo/.gitdir/COMMIT_EDITMSG @@ -1 +1 @@ -master conflict commit +delete their for conflict diff --git a/test/assets/mergerepo/.gitdir/index b/test/assets/mergerepo/.gitdir/index index 92efebc444c440a400f7b6d02f2d95844bc68682..470ddcfff0c062e4fde62a99884317dc5f08bc26 100644 GIT binary patch delta 175 zcmaFL{FGV6#WTp6fq{Vuh*=Xe8^pD4EWZS!fnw?m$G25ZRIwDtE>$(L1S0kPl_Xdf zkcR52nRo=3RPAIDMxb21wnFV=?nHz7RyLjW>=12R9!ySQ%oPdMT%UUEhicCcz4w3b M>q|86yKwdv0QU4jxc~qF delta 175 zcmaFL{FGV6#WTp6fq{Vuh*=XYw~6TQ)gHlP(D$`QrvQzn}RWy z2T%!^hDyzuSOSs~)4k$y5~%B{?D`#sP^rp^M<7y|29`}0VZ 1631172155 +0300 commit: conflict branch commit 47af50e6a799d7d0dde6630d2644f9484fb670f7 821ed6e80627b8769d170a293862f9fc60825226 Aleksey Kulikov 1631172159 +0300 checkout: moving from conflict-branch to master 821ed6e80627b8769d170a293862f9fc60825226 14905459d775f3f56a39ebc2ff081163f7da3529 Aleksey Kulikov 1631172175 +0300 commit: master conflict commit +14905459d775f3f56a39ebc2ff081163f7da3529 5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 Aleksey Kulikov 1634223805 +0300 checkout: moving from master to ancestor-conflict +5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 7606a0d606a74ee5f0761c6e358c2f90405c94ad Aleksey Kulikov 1634223835 +0300 commit: conflict with ancestor +7606a0d606a74ee5f0761c6e358c2f90405c94ad 5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 Aleksey Kulikov 1634223845 +0300 checkout: moving from ancestor-conflict to feature +5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 2ee89b2f7124b8e4632bc6a20774a90b795245e4 Aleksey Kulikov 1634223881 +0300 commit: conflict with ancestor +2ee89b2f7124b8e4632bc6a20774a90b795245e4 14905459d775f3f56a39ebc2ff081163f7da3529 Aleksey Kulikov 1634225232 +0300 checkout: moving from feature to master +14905459d775f3f56a39ebc2ff081163f7da3529 2ee89b2f7124b8e4632bc6a20774a90b795245e4 Aleksey Kulikov 1634303915 +0300 checkout: moving from master to our-conflict +2ee89b2f7124b8e4632bc6a20774a90b795245e4 0db17b23a1acd67d5e44650d61aac7d4d83ec193 Aleksey Kulikov 1634303926 +0300 commit: delete our for conflict +0db17b23a1acd67d5e44650d61aac7d4d83ec193 14905459d775f3f56a39ebc2ff081163f7da3529 Aleksey Kulikov 1634303933 +0300 checkout: moving from our-conflict to master +14905459d775f3f56a39ebc2ff081163f7da3529 7606a0d606a74ee5f0761c6e358c2f90405c94ad Aleksey Kulikov 1634304003 +0300 checkout: moving from master to their-conflict +7606a0d606a74ee5f0761c6e358c2f90405c94ad 0e409d66f701eea5038fe508ead4c098da699d2c Aleksey Kulikov 1634304018 +0300 commit: delete their for conflict +0e409d66f701eea5038fe508ead4c098da699d2c 14905459d775f3f56a39ebc2ff081163f7da3529 Aleksey Kulikov 1634304023 +0300 checkout: moving from their-conflict to master diff --git a/test/assets/mergerepo/.gitdir/logs/refs/heads/ancestor-conflict b/test/assets/mergerepo/.gitdir/logs/refs/heads/ancestor-conflict new file mode 100644 index 0000000..b9ed227 --- /dev/null +++ b/test/assets/mergerepo/.gitdir/logs/refs/heads/ancestor-conflict @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 Aleksey Kulikov 1634223805 +0300 branch: Created from 5aecfa0 +5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 7606a0d606a74ee5f0761c6e358c2f90405c94ad Aleksey Kulikov 1634223835 +0300 commit: conflict with ancestor diff --git a/test/assets/mergerepo/.gitdir/logs/refs/heads/feature b/test/assets/mergerepo/.gitdir/logs/refs/heads/feature index 44be747..c2e74cc 100644 --- a/test/assets/mergerepo/.gitdir/logs/refs/heads/feature +++ b/test/assets/mergerepo/.gitdir/logs/refs/heads/feature @@ -2,3 +2,4 @@ f17d0d48eae3aa08cecf29128a35e310c97b3521 6cbc22e509d72758ab4c8d9f287ea846b90c448b Aleksey Kulikov 1626091020 +0300 commit: add feature file 6cbc22e509d72758ab4c8d9f287ea846b90c448b fc38877b2552ab554752d9a77e1f48f738cca79b Aleksey Kulikov 1626091054 +0300 commit: edit feature file fc38877b2552ab554752d9a77e1f48f738cca79b 5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 Aleksey Kulikov 1626091274 +0300 commit: add another feature file +5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 2ee89b2f7124b8e4632bc6a20774a90b795245e4 Aleksey Kulikov 1634223881 +0300 commit: conflict with ancestor diff --git a/test/assets/mergerepo/.gitdir/logs/refs/heads/our-conflict b/test/assets/mergerepo/.gitdir/logs/refs/heads/our-conflict new file mode 100644 index 0000000..423d153 --- /dev/null +++ b/test/assets/mergerepo/.gitdir/logs/refs/heads/our-conflict @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 2ee89b2f7124b8e4632bc6a20774a90b795245e4 Aleksey Kulikov 1634303915 +0300 branch: Created from 2ee89b2 +2ee89b2f7124b8e4632bc6a20774a90b795245e4 0db17b23a1acd67d5e44650d61aac7d4d83ec193 Aleksey Kulikov 1634303926 +0300 commit: delete our for conflict diff --git a/test/assets/mergerepo/.gitdir/logs/refs/heads/their-conflict b/test/assets/mergerepo/.gitdir/logs/refs/heads/their-conflict new file mode 100644 index 0000000..bad0a5b --- /dev/null +++ b/test/assets/mergerepo/.gitdir/logs/refs/heads/their-conflict @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 7606a0d606a74ee5f0761c6e358c2f90405c94ad Aleksey Kulikov 1634304003 +0300 branch: Created from 7606a0d +7606a0d606a74ee5f0761c6e358c2f90405c94ad 0e409d66f701eea5038fe508ead4c098da699d2c Aleksey Kulikov 1634304018 +0300 commit: delete their for conflict diff --git a/test/assets/mergerepo/.gitdir/objects/0d/b17b23a1acd67d5e44650d61aac7d4d83ec193 b/test/assets/mergerepo/.gitdir/objects/0d/b17b23a1acd67d5e44650d61aac7d4d83ec193 new file mode 100644 index 0000000000000000000000000000000000000000..c44e97f1db3751aecf645c800d68b6b8516d7179 GIT binary patch literal 175 zcmV;g08syU0i}*fY6CG40Daag`W`TvmPQL0lbrJkwbT=f(PGA$fPWwTA=iQ`D)w6Q z09@r|9L$h-Aw<#&$!gM$Y>LVeEou#nGEg)=rR2mj9NebJ>^$LS7u4ifn<+*UP+F^l zmt_5ldSxxbIUfChufqF_-|&5wy!T(Yz4qMN`&x5LpFcI^a*e&-VKGW8sXQ9^kV;B1 d=^P#WkAz5Ecrf(yfNj3S-nNqC5P!`uQ2A@!SG@oL literal 0 HcmV?d00001 diff --git a/test/assets/mergerepo/.gitdir/objects/0e/409d66f701eea5038fe508ead4c098da699d2c b/test/assets/mergerepo/.gitdir/objects/0e/409d66f701eea5038fe508ead4c098da699d2c new file mode 100644 index 0000000..83c2979 --- /dev/null +++ b/test/assets/mergerepo/.gitdir/objects/0e/409d66f701eea5038fe508ead4c098da699d2c @@ -0,0 +1,2 @@ +xKj1)z0K$Bcr A= +Gkevc@6@hbʸZ~!(ni>!x铤ev ^g"uV:\l":v ?ZVzZR'k[EFJqG7.q0\vX}Q \ No newline at end of file diff --git a/test/assets/mergerepo/.gitdir/objects/1e/a09ccce9682b1424ae282d060421876bad7f18 b/test/assets/mergerepo/.gitdir/objects/1e/a09ccce9682b1424ae282d060421876bad7f18 new file mode 100644 index 0000000000000000000000000000000000000000..97bcd4ad6b1d9de84826bf1838818f07d7bb2ac7 GIT binary patch literal 37 tcmbf;#r;fHU!w#(+jJSoLnW(RoBcN{&T+pRhGTCZFm8{h*Fvp_*n=5 literal 0 HcmV?d00001 diff --git a/test/assets/mergerepo/.gitdir/objects/76/06a0d606a74ee5f0761c6e358c2f90405c94ad b/test/assets/mergerepo/.gitdir/objects/76/06a0d606a74ee5f0761c6e358c2f90405c94ad new file mode 100644 index 0000000000000000000000000000000000000000..d8e2dfff6a731fd3e6096a049ee51540dacc51ff GIT binary patch literal 176 zcmV;h08jsT0j178Zo@DPK;h0l1@`~}WBo(~f})*!3W}l{!Io6mN{ZaRzC+hHe0b7p zEdyptZ(~!16gZO4LS7THF_A(br&n>-*sP>_A%|g}et6S1z_ChZ%#p6jiCNI0NF>T= z#N_Cm^~lLi{22GX!RM;Wt}pm{tYzs>xa~`6?RBoDrH}8*Wj#x;?{M+P&a(-|!3hoG ebkt*X=s$?VXn8F%;J1uBa1-4}-=;raKT;|=En7nX literal 0 HcmV?d00001 diff --git a/test/assets/mergerepo/.gitdir/objects/d8/ab96fc96ed0a33b98895e7c5434fe9ee195082 b/test/assets/mergerepo/.gitdir/objects/d8/ab96fc96ed0a33b98895e7c5434fe9ee195082 new file mode 100644 index 0000000000000000000000000000000000000000..59370548ae6bddf4d9171a9ad1014fdf843f35df GIT binary patch literal 95 zcmV-l0HFVP0V^p=O;s>7GGH(?FfcPQQAo_oFUd$Picd>TEGaEYjZe$WNo9C8_tET4 z7q2;ccWbUIkGgT_Nl)-ZsCpE2atr31d6}UtqOwjymyJcSJ$r4v1WX++a{!MKG-bTZ BCD#A| literal 0 HcmV?d00001 diff --git a/test/assets/mergerepo/.gitdir/objects/d9/9d64a90db7f69fa8cff8c7b01fba011379165f b/test/assets/mergerepo/.gitdir/objects/d9/9d64a90db7f69fa8cff8c7b01fba011379165f new file mode 100644 index 0000000000000000000000000000000000000000..043e044fae8ab84ff8d0b6391cfec57261510190 GIT binary patch literal 41 xcmbk45MuxU literal 0 HcmV?d00001 diff --git a/test/assets/mergerepo/.gitdir/objects/dd/20ffc2e349da86f4c5dda87ac8d1602e063f54 b/test/assets/mergerepo/.gitdir/objects/dd/20ffc2e349da86f4c5dda87ac8d1602e063f54 new file mode 100644 index 0000000000000000000000000000000000000000..1908b818b7b2c9916cccaaaf77b683cef9145bdf GIT binary patch literal 96 zcmV-m0H6PO0V^p=O;s>7GGH(?FfcPQQAo_oFUd$Picd>TEGaEYjZe$WNo9C8_tET4 z7q2;ccWbUIkGgT_Nl)-ZsCpE2H|M6Th#ae<>X7 literal 0 HcmV?d00001 diff --git a/test/assets/mergerepo/.gitdir/refs/heads/ancestor-conflict b/test/assets/mergerepo/.gitdir/refs/heads/ancestor-conflict new file mode 100644 index 0000000..bcb6139 --- /dev/null +++ b/test/assets/mergerepo/.gitdir/refs/heads/ancestor-conflict @@ -0,0 +1 @@ +7606a0d606a74ee5f0761c6e358c2f90405c94ad diff --git a/test/assets/mergerepo/.gitdir/refs/heads/feature b/test/assets/mergerepo/.gitdir/refs/heads/feature index 3584be2..578afe6 100644 --- a/test/assets/mergerepo/.gitdir/refs/heads/feature +++ b/test/assets/mergerepo/.gitdir/refs/heads/feature @@ -1 +1 @@ -5aecfa0fb97eadaac050ccb99f03c3fb65460ad4 +2ee89b2f7124b8e4632bc6a20774a90b795245e4 diff --git a/test/assets/mergerepo/.gitdir/refs/heads/our-conflict b/test/assets/mergerepo/.gitdir/refs/heads/our-conflict new file mode 100644 index 0000000..2bb55de --- /dev/null +++ b/test/assets/mergerepo/.gitdir/refs/heads/our-conflict @@ -0,0 +1 @@ +0db17b23a1acd67d5e44650d61aac7d4d83ec193 diff --git a/test/assets/mergerepo/.gitdir/refs/heads/their-conflict b/test/assets/mergerepo/.gitdir/refs/heads/their-conflict new file mode 100644 index 0000000..486ea72 --- /dev/null +++ b/test/assets/mergerepo/.gitdir/refs/heads/their-conflict @@ -0,0 +1 @@ +0e409d66f701eea5038fe508ead4c098da699d2c diff --git a/test/blame_test.dart b/test/blame_test.dart index 4d59267..248ad14 100644 --- a/test/blame_test.dart +++ b/test/blame_test.dart @@ -142,5 +142,11 @@ void main() { blame.free(); }); + + test('returns string representation of BlameHunk object', () { + final blame = repo.blame(path: 'feature_file'); + expect(blame.toString(), contains('BlameHunk{')); + blame.free(); + }); }); } diff --git a/test/blob_test.dart b/test/blob_test.dart index c3c7274..68db322 100644 --- a/test/blob_test.dart +++ b/test/blob_test.dart @@ -63,7 +63,13 @@ void main() { test('throws when creating new blob from invalid path', () { expect( () => repo.createBlobFromWorkdir('invalid/path.txt'), - throwsA(isA()), + throwsA( + isA().having( + (e) => e.toString(), + 'message', + "could not find '${repo.workdir}invalid/path.txt' to stat: No such file or directory", + ), + ), ); }); @@ -128,10 +134,10 @@ index e69de29..0000000 }); test('successfully creates from one blob (delete)', () { - final a = repo.lookupBlob( + final _blob = repo.lookupBlob( repo['e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'], ); - final patch = a.diff( + final patch = _blob.diff( newBlob: null, oldAsPath: path, newAsPath: path, @@ -143,16 +149,14 @@ index e69de29..0000000 }); test('successfully creates from blob and buffer', () { - final a = repo.lookupBlob( + final _blob = repo.lookupBlob( repo['e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'], ); - final patch = Patch.create( - a: a, - b: 'Feature edit\n', - aPath: path, - bPath: path, - ); + final patch = _blob.diffToBuffer( + buffer: 'Feature edit\n', + oldAsPath: path, + ); expect(patch.text, blobPatch); patch.free(); @@ -174,5 +178,9 @@ index e69de29..0000000 patch.free(); }); }); + + test('returns string representation of Blob object', () { + expect(blob.toString(), contains('Blob{')); + }); }); } diff --git a/test/branch_test.dart b/test/branch_test.dart index dd226f5..1c9a24f 100644 --- a/test/branch_test.dart +++ b/test/branch_test.dart @@ -186,5 +186,11 @@ void main() { ); }); }); + + test('returns string representation of Branch object', () { + final branch = repo.lookupBranch('master'); + expect(branch.toString(), contains('Branch{')); + branch.free(); + }); }); } diff --git a/test/commit_test.dart b/test/commit_test.dart index da1fabf..68cd1e2 100644 --- a/test/commit_test.dart +++ b/test/commit_test.dart @@ -147,5 +147,11 @@ void main() { parent2.free(); commit.free(); }); + + test('returns string representation of Commit object', () { + final commit = repo.lookupCommit(mergeCommit); + expect(commit.toString(), contains('Commit{')); + commit.free(); + }); }); } diff --git a/test/credentials_test.dart b/test/credentials_test.dart index 5388f92..3bbf41f 100644 --- a/test/credentials_test.dart +++ b/test/credentials_test.dart @@ -23,6 +23,7 @@ void main() { expect(credentials, isA()); expect(credentials.username, 'user'); expect(credentials.credentialType, GitCredential.username); + expect(credentials.toString(), contains('Username{')); }); test('successfully initializes username/password credentials', () { @@ -35,6 +36,7 @@ void main() { expect(credentials.username, 'user'); expect(credentials.password, 'password'); expect(credentials.credentialType, GitCredential.userPassPlainText); + expect(credentials.toString(), contains('UserPass{')); }); test('successfully initializes keypair credentials', () { @@ -51,6 +53,7 @@ void main() { expect(credentials.privateKey, 'id_rsa'); expect(credentials.passPhrase, 'passphrase'); expect(credentials.credentialType, GitCredential.sshKey); + expect(credentials.toString(), contains('Keypair{')); }); test('successfully initializes keypair from memory credentials', () { @@ -67,6 +70,7 @@ void main() { expect(credentials.privateKey, 'private key data'); expect(credentials.passPhrase, 'passphrase'); expect(credentials.credentialType, GitCredential.sshMemory); + expect(credentials.toString(), contains('KeypairFromMemory{')); }); test('successfully initializes keypair from agent credentials', () { @@ -75,6 +79,7 @@ void main() { expect(credentials, isA()); expect(credentials.username, 'user'); expect(credentials.credentialType, GitCredential.sshKey); + expect(credentials.toString(), contains('KeypairFromAgent{')); }); test('sucessfully clones repository with provided keypair', () { diff --git a/test/describe_test.dart b/test/describe_test.dart index 99328cf..1a70d6a 100644 --- a/test/describe_test.dart +++ b/test/describe_test.dart @@ -131,5 +131,14 @@ void main() { index.free(); }); + + test('successfully describes with max candidates tags flag set', () { + final index = repo.index; + index.clear(); + + expect(repo.describe(maxCandidatesTags: 0), 'v0.2'); + + index.free(); + }); }); } diff --git a/test/diff_test.dart b/test/diff_test.dart index c59c2e7..0a4bac9 100644 --- a/test/diff_test.dart +++ b/test/diff_test.dart @@ -103,17 +103,24 @@ index e69de29..c217c63 100644 final head = repo.head; final commit = repo.lookupCommit(head.target); final tree = commit.tree; - final diff = index.diffToTree(tree: tree); + final diff1 = index.diffToTree(tree: tree); + final diff2 = tree.diffToIndex(index: index); - expect(diff.length, 8); - for (var i = 0; i < diff.deltas.length; i++) { - expect(diff.deltas[i].newFile.path, indexToTree[i]); + expect(diff1.length, 8); + for (var i = 0; i < diff1.deltas.length; i++) { + expect(diff1.deltas[i].newFile.path, indexToTree[i]); + } + + expect(diff2.length, 8); + for (var i = 0; i < diff2.deltas.length; i++) { + expect(diff2.deltas[i].newFile.path, indexToTree[i]); } commit.free(); head.free(); tree.free(); - diff.free(); + diff1.free(); + diff2.free(); index.free(); }); @@ -157,9 +164,7 @@ index e69de29..c217c63 100644 final head = repo.head; final commit = repo.lookupCommit(head.target); final tree1 = commit.tree; - final tree2 = repo.lookupTree( - repo['b85d53c9236e89aff2b62558adaa885fd1d6ff1c'], - ); + final tree2 = repo.lookupTree(repo['b85d53c']); final diff = repo.diff(a: tree1, b: tree2); expect(diff.length, 10); @@ -174,6 +179,12 @@ index e69de29..c217c63 100644 diff.free(); }); + test('throws when trying to diff between null and tree', () { + final tree = repo.lookupTree(repo['b85d53c']); + expect(() => repo.diff(a: null, b: tree), throwsA(isA())); + tree.free(); + }); + test('successfully merges diffs', () { final head = repo.head; final commit = repo.lookupCommit(head.target); @@ -377,5 +388,24 @@ index e69de29..c217c63 100644 patch.free(); diff.free(); }); + + test( + 'returns string representation of Diff, DiffDelta, DiffFile, ' + 'DiffHunk, DiffLine and DiffStats objects', () { + final diff = Diff.parse(patchText); + final patch = Patch.fromDiff(diff: diff, index: 0); + final stats = diff.stats; + + expect(diff.toString(), contains('Diff{')); + expect(patch.delta.toString(), contains('DiffDelta{')); + expect(patch.delta.oldFile.toString(), contains('DiffFile{')); + expect(patch.hunks[0].toString(), contains('DiffHunk{')); + expect(patch.hunks[0].lines[0].toString(), contains('DiffLine{')); + expect(stats.toString(), contains('DiffStats{')); + + stats.free(); + patch.free(); + diff.free(); + }); }); } diff --git a/test/helpers/util.dart b/test/helpers/util.dart index 0d10c3a..d1862e0 100644 --- a/test/helpers/util.dart +++ b/test/helpers/util.dart @@ -1,9 +1,8 @@ import 'dart:io'; import 'package:path/path.dart' as p; -final tmpDir = Directory.systemTemp.createTempSync('testrepo'); - Directory setupRepo(Directory repoDir) { + final tmpDir = Directory.systemTemp.createTempSync('testrepo'); if (tmpDir.existsSync()) { tmpDir.deleteSync(recursive: true); } diff --git a/test/index_test.dart b/test/index_test.dart index 45d9f62..6dc85b3 100644 --- a/test/index_test.dart +++ b/test/index_test.dart @@ -29,7 +29,9 @@ void main() { }); test('returns mode of index entry', () { - expect(index['file'].mode, GitFilemode.blob); + for (final entry in index) { + expect(entry.mode, GitFilemode.blob); + } }); test('returns index entry at provided position', () { @@ -174,5 +176,104 @@ void main() { final oid = index.writeTree(); expect(oid.sha, 'a8ae3dd59e6e1802c6f78e05e301bfd57c9f334f'); }); + + test('returns conflicts with ancestor, our and their present', () { + final repoDir = setupRepo(Directory('test/assets/mergerepo/')); + final conflictRepo = Repository.open(repoDir.path); + + final conflictBranch = conflictRepo.lookupBranch('ancestor-conflict'); + + conflictRepo.checkout(refName: 'refs/heads/feature'); + + conflictRepo.merge(conflictBranch.target); + + final index = conflictRepo.index; + final conflictedFile = index.conflicts['feature_file']!; + expect(conflictedFile.ancestor?.path, 'feature_file'); + expect(conflictedFile.our?.path, 'feature_file'); + expect(conflictedFile.their?.path, 'feature_file'); + expect(conflictedFile.toString(), contains('ConflictEntry{')); + + index.free(); + conflictBranch.free(); + conflictRepo.free(); + repoDir.deleteSync(recursive: true); + }); + + test('returns conflicts with our and their present and null ancestor', () { + final repoDir = setupRepo(Directory('test/assets/mergerepo/')); + final conflictRepo = Repository.open(repoDir.path); + + final conflictBranch = conflictRepo.lookupBranch('conflict-branch'); + + conflictRepo.merge(conflictBranch.target); + + final index = conflictRepo.index; + final conflictedFile = index.conflicts['conflict_file']!; + expect(conflictedFile.ancestor?.path, null); + expect(conflictedFile.our?.path, 'conflict_file'); + expect(conflictedFile.their?.path, 'conflict_file'); + expect(conflictedFile.toString(), contains('ConflictEntry{')); + + index.free(); + conflictBranch.free(); + conflictRepo.free(); + repoDir.deleteSync(recursive: true); + }); + + test('returns conflicts with ancestor and their present and null our', () { + final repoDir = setupRepo(Directory('test/assets/mergerepo/')); + final conflictRepo = Repository.open(repoDir.path); + + final conflictBranch = conflictRepo.lookupBranch('ancestor-conflict'); + + conflictRepo.checkout(refName: 'refs/heads/our-conflict'); + + conflictRepo.merge(conflictBranch.target); + + final index = conflictRepo.index; + final conflictedFile = index.conflicts['feature_file']!; + expect(conflictedFile.ancestor?.path, 'feature_file'); + expect(conflictedFile.our?.path, null); + expect(conflictedFile.their?.path, 'feature_file'); + expect(conflictedFile.toString(), contains('ConflictEntry{')); + + index.free(); + conflictBranch.free(); + conflictRepo.free(); + repoDir.deleteSync(recursive: true); + }); + + test('returns conflicts with ancestor and our present and null their', () { + final repoDir = setupRepo(Directory('test/assets/mergerepo/')); + final conflictRepo = Repository.open(repoDir.path); + + final conflictBranch = conflictRepo.lookupBranch('their-conflict'); + + conflictRepo.checkout(refName: 'refs/heads/feature'); + + conflictRepo.merge(conflictBranch.target); + + final index = conflictRepo.index; + final conflictedFile = index.conflicts['feature_file']!; + expect(conflictedFile.ancestor?.path, 'feature_file'); + expect(conflictedFile.our?.path, 'feature_file'); + expect(conflictedFile.their?.path, null); + expect(conflictedFile.toString(), contains('ConflictEntry{')); + + index.free(); + conflictBranch.free(); + conflictRepo.free(); + repoDir.deleteSync(recursive: true); + }); + + test('returns string representation of Index and IndexEntry objects', () { + final index = repo.index; + + expect(index.toString(), contains('Index{')); + expect(index['file'].toString(), contains('IndexEntry{')); + + index.free(); + }); }); } diff --git a/test/mailmap_test.dart b/test/mailmap_test.dart index d66a07e..5f08366 100644 --- a/test/mailmap_test.dart +++ b/test/mailmap_test.dart @@ -206,5 +206,25 @@ Santa Claus mailmap.free(); }); + + test('successfully resolves signature', () { + final signature = Signature.create( + name: 'nick1', + email: 'bugs@company.xx', + ); + final realSignature = Signature.create( + name: 'Some Dude', + email: 'some@dude.xx', + ); + final mailmap = Mailmap.empty(); + mailmap.addEntry( + realName: 'Some Dude', + realEmail: 'some@dude.xx', + replaceName: 'nick1', + replaceEmail: 'bugs@company.xx', + ); + + expect(mailmap.resolveSignature(signature), realSignature); + }); }); } diff --git a/test/merge_test.dart b/test/merge_test.dart index 215b62e..45af540 100644 --- a/test/merge_test.dart +++ b/test/merge_test.dart @@ -148,7 +148,7 @@ void main() { }); group('merge file from index', () { - test('successfully merges', () { + test('successfully merges without ancestor', () { const diffExpected = """ \<<<<<<< conflict_file master conflict edit @@ -160,10 +160,40 @@ conflict branch edit final index = repo.index; repo.merge(conflictBranch.target); + final conflictedFile = index.conflicts['conflict_file']!; final diff = repo.mergeFileFromIndex( - ancestor: index.conflicts['conflict_file']!.ancestor, - ours: index.conflicts['conflict_file']!.our, - theirs: index.conflicts['conflict_file']!.their, + ancestor: null, + ours: conflictedFile.our!, + theirs: conflictedFile.their!, + ); + + expect( + diff, + diffExpected, + ); + + index.free(); + conflictBranch.free(); + }); + + test('successfully merges with ancestor', () { + const diffExpected = """ +\<<<<<<< feature_file +Feature edit on feature branch +======= +Another feature edit +>>>>>>> feature_file +"""; + final conflictBranch = repo.lookupBranch('ancestor-conflict'); + repo.checkout(refName: 'refs/heads/feature'); + final index = repo.index; + repo.merge(conflictBranch.target); + + final conflictedFile = index.conflicts['feature_file']!; + final diff = repo.mergeFileFromIndex( + ancestor: conflictedFile.ancestor, + ours: conflictedFile.our!, + theirs: conflictedFile.their!, ); expect( diff --git a/test/note_test.dart b/test/note_test.dart index 5413ab6..dad9d87 100644 --- a/test/note_test.dart +++ b/test/note_test.dart @@ -93,5 +93,11 @@ void main() { head.free(); signature.free(); }); + + test('returns string representation of Note object', () { + final note = repo.lookupNote(annotatedOid: repo['821ed6e']); + expect(note.toString(), contains('Note{')); + note.free(); + }); }); } diff --git a/test/odb_test.dart b/test/odb_test.dart index a6c586c..6fed9fb 100644 --- a/test/odb_test.dart +++ b/test/odb_test.dart @@ -34,17 +34,16 @@ void main() { }); test('successfully adds disk alternate', () { - final oid = Oid.fromSHA(repo: repo, sha: blobSha); final odb = Odb.create(); odb.addDiskAlternate('${repo.workdir}.git/objects/'); - expect(odb.contains(oid), true); + expect(odb.contains(repo[blobSha]), true); odb.free(); }); test('successfully reads object', () { - final oid = Oid.fromSHA(repo: repo, sha: blobSha); + final oid = repo[blobSha]; final odb = repo.odb; final object = odb.read(oid); @@ -58,23 +57,14 @@ void main() { }); test('returns list of all objects oid\'s in database', () { - final oid = Oid.fromSHA(repo: repo, sha: commitSha); final odb = repo.odb; expect(odb.objects, isNot(isEmpty)); - expect(odb.objects.contains(oid), true); + expect(odb.objects.contains(repo[commitSha]), true); odb.free(); }); - test('finds object by short oid', () { - final oid = Oid.fromSHA( - repo: repo, - sha: commitSha.substring(0, 5), - ); - expect(oid.sha, commitSha); - }); - test('successfully writes data', () { final odb = repo.odb; final oid = odb.write(type: GitObject.blob, data: 'testing'); @@ -96,5 +86,12 @@ void main() { odb.free(); }); + + test('returns string representation of OdbObject object', () { + final odb = repo.odb; + final object = odb.read(repo[blobSha]); + expect(object.toString(), contains('OdbObject{')); + odb.free(); + }); }); } diff --git a/test/oid_test.dart b/test/oid_test.dart index 29f33df..0167fdd 100644 --- a/test/oid_test.dart +++ b/test/oid_test.dart @@ -35,6 +35,19 @@ void main() { expect(oid, isA()); expect(oid.sha, sha); }); + + test('throws when sha hex string is too short', () { + expect( + () => Oid.fromSHA(repo: repo, sha: 'sha'), + throwsA( + isA().having( + (e) => e.invalidValue, + 'value', + 'sha is not a valid sha hex string', + ), + ), + ); + }); }); group('fromRaw()', () { @@ -72,5 +85,9 @@ void main() { expect(oid1 >= oid2, true); }); }); + + test('returns string representation of Oid object', () { + expect(repo[sha].toString(), contains('Oid{')); + }); }); } diff --git a/test/packbuilder_test.dart b/test/packbuilder_test.dart index 6dd3c34..3db6669 100644 --- a/test/packbuilder_test.dart +++ b/test/packbuilder_test.dart @@ -69,12 +69,15 @@ void main() { odb.free(); }); - test('successfully packs into provided path', () { + test('successfully packs into provided path with threads set', () { final odb = repo.odb; final objectsCount = odb.objects.length; Directory('${repo.workdir}test-pack').createSync(); - final writtenCount = repo.pack(path: '${repo.workdir}test-pack'); + final writtenCount = repo.pack( + path: '${repo.workdir}test-pack', + threads: 1, + ); expect(writtenCount, objectsCount); expect( Directory('${repo.workdir}test-pack').listSync().isNotEmpty, @@ -101,5 +104,11 @@ void main() { final writtenCount = repo.pack(packDelegate: packDelegate); expect(writtenCount, 18); }); + + test('returns string representation of PackBuilder object', () { + final packbuilder = PackBuilder(repo); + expect(packbuilder.toString(), contains('PackBuilder{')); + packbuilder.free(); + }); }); } diff --git a/test/patch_test.dart b/test/patch_test.dart index 2d379d0..e5e1fed 100644 --- a/test/patch_test.dart +++ b/test/patch_test.dart @@ -174,5 +174,18 @@ index e69de29..0000000 commit.free(); }); + + test('returns string representation of Patch object', () { + final patch = Patch.create( + a: oldBlob, + b: newBlob, + aPath: path, + bPath: path, + ); + + expect(patch.toString(), contains('Patch{')); + + patch.free(); + }); }); } diff --git a/test/rebase_test.dart b/test/rebase_test.dart index 8034440..f62fccc 100644 --- a/test/rebase_test.dart +++ b/test/rebase_test.dart @@ -44,9 +44,13 @@ void main() { final operation = rebase.next(); expect(operation.type, GitRebaseOperation.pick); expect(operation.oid.sha, shas[i]); - expect(operation.exec, ''); + expect(operation.toString(), contains('RebaseOperation{')); - rebase.commit(committer: signature); + rebase.commit( + committer: signature, + author: signature, + message: 'rebase message', + ); } rebase.finish(); diff --git a/test/reference_test.dart b/test/reference_test.dart index 862dfd2..9116429 100644 --- a/test/reference_test.dart +++ b/test/reference_test.dart @@ -64,7 +64,7 @@ void main() { test('returns the short name', () { final ref = repo.createReference( name: 'refs/remotes/origin/master', - target: lastCommit, + target: repo[lastCommit], ); final head = repo.head; @@ -91,7 +91,7 @@ void main() { test('checks if reference is a remote branch', () { final ref = repo.createReference( name: 'refs/remotes/origin/master', - target: lastCommit, + target: repo[lastCommit], ); expect(ref.isRemote, true); @@ -129,33 +129,11 @@ void main() { ref.free(); }); - test('successfully creates with SHA hash as target', () { - final refFromHash = repo.createReference( - name: 'refs/tags/from.hash', - target: lastCommit, - ); - - expect(repo.references, contains('refs/tags/from.hash')); - - refFromHash.free(); - }); - - test('successfully creates with short SHA hash as target', () { - final refFromHash = repo.createReference( - name: 'refs/tags/from.short.hash', - target: '78b8bf', - ); - - expect(repo.references, contains('refs/tags/from.short.hash')); - - refFromHash.free(); - }); - test('successfully creates with log message', () { repo.setIdentity(name: 'name', email: 'email'); final ref = repo.createReference( name: 'refs/heads/log.message', - target: lastCommit, + target: repo[lastCommit], logMessage: 'log message', ); @@ -178,13 +156,21 @@ void main() { ), throwsA(isA()), ); + + expect( + () => repo.createReference( + name: 'refs/tags/invalid', + target: 0, + ), + throwsA(isA()), + ); }); test('throws if name is not valid', () { expect( () => repo.createReference( name: 'refs/tags/invalid~', - target: lastCommit, + target: repo[lastCommit], ), throwsA(isA()), ); @@ -193,12 +179,12 @@ void main() { test('successfully creates with force flag if name already exists', () { final ref = repo.createReference( name: 'refs/tags/test', - target: lastCommit, + target: repo[lastCommit], ); final forceRef = repo.createReference( name: 'refs/tags/test', - target: lastCommit, + target: repo[lastCommit], force: true, ); @@ -211,13 +197,13 @@ void main() { test('throws if name already exists', () { final ref = repo.createReference( name: 'refs/tags/test', - target: lastCommit, + target: repo[lastCommit], ); expect( () => repo.createReference( name: 'refs/tags/test', - target: lastCommit, + target: repo[lastCommit], ), throwsA(isA()), ); @@ -309,7 +295,7 @@ void main() { test('successfully deletes reference', () { final ref = repo.createReference( name: 'refs/tags/test', - target: lastCommit, + target: repo[lastCommit], ); expect(repo.references, contains('refs/tags/test')); @@ -384,6 +370,10 @@ void main() { () => ref.setTarget(target: 'refs/heads/invalid~'), throwsA(isA()), ); + expect( + () => ref.setTarget(target: 0), + throwsA(isA()), + ); ref.free(); }); @@ -476,15 +466,32 @@ void main() { test('successfully peels to object of provided type', () { final ref = repo.lookupReference('refs/heads/master'); + final blob = repo.lookupBlob(repo['9c78c21']); + final blobRef = repo.createReference( + name: 'refs/tags/blob', + target: blob.oid, + ); + final tagRef = repo.lookupReference('refs/tags/v0.2'); final commit = repo.lookupCommit(ref.target); final tree = commit.tree; + final peeledCommit = ref.peel(GitObject.commit) as Commit; final peeledTree = ref.peel(GitObject.tree) as Tree; + final peeledBlob = blobRef.peel(GitObject.blob) as Blob; + final peeledTag = tagRef.peel(GitObject.tag) as Tag; expect(peeledCommit.oid, commit.oid); expect(peeledTree.oid, tree.oid); + expect(peeledBlob.content, 'Feature edit\n'); + expect(peeledTag.name, 'v0.2'); + peeledTag.free(); + peeledBlob.free(); + peeledTree.free(); peeledCommit.free(); + tagRef.free(); + blobRef.free(); + blob.free(); commit.free(); tree.free(); ref.free(); @@ -501,5 +508,11 @@ void main() { final newRefs = repo.references; expect(newRefs, oldRefs); }); + + test('returns string representation of Reference object', () { + final ref = repo.lookupReference('refs/heads/master'); + expect(ref.toString(), contains('Reference{')); + ref.free(); + }); }); } diff --git a/test/reflog_test.dart b/test/reflog_test.dart index 02f106c..f2049fa 100644 --- a/test/reflog_test.dart +++ b/test/reflog_test.dart @@ -41,5 +41,9 @@ void main() { expect(reflog[0].committer.email, 'skinny.mind@gmail.com'); expect(reflog[0].committer.time, 1630568461); }); + + test('returns string representation of RefLogEntry object', () { + expect(reflog[0].toString(), contains('RefLogEntry{')); + }); }); } diff --git a/test/remote_test.dart b/test/remote_test.dart index 70a4162..1d18750 100644 --- a/test/remote_test.dart +++ b/test/remote_test.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:libgit2dart/src/git_types.dart'; import 'package:test/test.dart'; import 'package:libgit2dart/libgit2dart.dart'; import 'helpers/util.dart'; @@ -30,6 +31,7 @@ void main() { expect(remote.name, remoteName); expect(remote.url, remoteUrl); expect(remote.pushUrl, ''); + expect(remote.toString(), contains('Remote{')); remote.free(); }); @@ -143,7 +145,9 @@ void main() { expect(refspec.source, 'refs/heads/*'); expect(refspec.destination, 'refs/remotes/origin/*'); expect(refspec.force, true); + expect(refspec.direction, GitDirection.fetch); expect(refspec.string, '+refs/heads/*:refs/remotes/origin/*'); + expect(refspec.toString(), contains('Refspec{')); expect(remote.fetchRefspecs, ['+refs/heads/*:refs/remotes/origin/*']); expect(refspec.matchesSource('refs/heads/master'), true); @@ -231,6 +235,7 @@ void main() { expect(stats.totalDeltas, 3); expect(stats.indexedDeltas, 3); expect(stats.receivedBytes, 0); + expect(stats.toString(), contains('TransferProgress{')); remote.free(); }); diff --git a/test/repository_test.dart b/test/repository_test.dart index 2325495..06d8959 100644 --- a/test/repository_test.dart +++ b/test/repository_test.dart @@ -30,6 +30,15 @@ void main() { config.free(); }); + test('returns snapshot of repository config', () { + final snapshot = repo.configSnapshot; + expect( + snapshot['remote.origin.url'].value, + 'git://github.com/SkinnyMind/libgit2dart.git', + ); + snapshot.free(); + }); + test('returns list of commits by walking from provided starting oid', () { const log = [ '821ed6e80627b8769d170a293862f9fc60825226', @@ -111,6 +120,10 @@ void main() { repo.setHead('refs/heads/not.there'); expect(repo.isBranchUnborn, true); }); + + test('throws when target is invalid', () { + expect(() => repo.setHead(0), throwsA(isA())); + }); }); group('createBlob', () { @@ -196,6 +209,18 @@ void main() { index.free(); }); + test('cleans up state', () { + expect(repo.state, GitRepositoryState.none); + final commit = repo.lookupCommit(repo['5aecfa0']); + repo.cherryPick(commit); + + expect(repo.state, GitRepositoryState.cherrypick); + repo.stateCleanup(); + expect(repo.state, GitRepositoryState.none); + + commit.free(); + }); + test('returns status of a single file for provided path', () { final index = repo.index; index.remove('file'); @@ -284,5 +309,9 @@ void main() { commit1.free(); commit2.free(); }); + + test('returns string representation of Repository object', () { + expect(repo.toString(), contains('Repository{')); + }); }); } diff --git a/test/revparse_test.dart b/test/revparse_test.dart index 93a6aa2..6d38ae1 100644 --- a/test/revparse_test.dart +++ b/test/revparse_test.dart @@ -41,6 +41,7 @@ void main() { expect(headParse.object.oid.sha, headSHA); expect(headParse.reference, masterRef); + expect(headParse.toString(), contains('RevParse{')); masterRef.free(); headParse.object.free(); @@ -77,6 +78,7 @@ void main() { expect(revspec.from.oid.sha, headSHA); expect(revspec.to, isNull); expect(revspec.flags, {GitRevSpec.single}); + expect(revspec.toString(), contains('RevSpec{')); revspec.from.free(); diff --git a/test/signature_test.dart b/test/signature_test.dart index a152705..987bad7 100644 --- a/test/signature_test.dart +++ b/test/signature_test.dart @@ -56,5 +56,9 @@ void main() { otherSignature.free(); }); + + test('returns string representation of Signature object', () { + expect(signature.toString(), contains('Signature{')); + }); }); } diff --git a/test/stash_test.dart b/test/stash_test.dart index ff5aa56..ac7f25f 100644 --- a/test/stash_test.dart +++ b/test/stash_test.dart @@ -30,10 +30,41 @@ void main() { mode: FileMode.append, ); - repo.createStash(stasher: stasher, includeUntracked: true); + repo.createStash(stasher: stasher); expect(repo.status.isEmpty, true); }); + test('successfully saves changes to stash including ignored', () { + final swpPath = File('${tmpDir.path}/some.swp'); + swpPath.writeAsStringSync('ignored'); + + repo.createStash( + stasher: stasher, + includeUntracked: true, + includeIgnored: true, + ); + expect(repo.status.isEmpty, true); + expect(swpPath.existsSync(), false); + + repo.applyStash(); + expect(swpPath.existsSync(), true); + }); + + test('leaves changes added to index intact', () { + File('${tmpDir.path}/file').writeAsStringSync( + 'edit', + mode: FileMode.append, + ); + final index = repo.index; + index.add('file'); + + repo.createStash(stasher: stasher, keepIndex: true); + expect(repo.status.isEmpty, false); + expect(repo.stashes.length, 1); + + index.free(); + }); + test('successfully applies changes from stash', () { File('${tmpDir.path}/file').writeAsStringSync( 'edit', @@ -47,6 +78,23 @@ void main() { expect(repo.status, contains('file')); }); + test('successfully applies changes from stash including index changes', () { + File('${tmpDir.path}/stash.this').writeAsStringSync('stash'); + final index = repo.index; + index.add('stash.this'); + expect(index.find('stash.this'), true); + + repo.createStash(stasher: stasher, includeUntracked: true); + expect(repo.status.isEmpty, true); + expect(index.find('stash.this'), false); + + repo.applyStash(reinstateIndex: true); + expect(repo.status, contains('stash.this')); + expect(index.find('stash.this'), true); + + index.free(); + }); + test('successfully drops stash', () { File('${tmpDir.path}/file').writeAsStringSync( 'edit', @@ -71,6 +119,23 @@ void main() { expect(() => repo.applyStash(), throwsA(isA())); }); + test('successfully pops from stash including index changes', () { + File('${tmpDir.path}/stash.this').writeAsStringSync('stash'); + final index = repo.index; + index.add('stash.this'); + expect(index.find('stash.this'), true); + + repo.createStash(stasher: stasher, includeUntracked: true); + expect(repo.status.isEmpty, true); + expect(index.find('stash.this'), false); + + repo.popStash(reinstateIndex: true); + expect(repo.status, contains('stash.this')); + expect(index.find('stash.this'), true); + + index.free(); + }); + test('returns list of stashes', () { File('${tmpDir.path}/file').writeAsStringSync( 'edit', @@ -85,5 +150,11 @@ void main() { expect(stash.index, 0); expect(stash.message, 'On master: WIP'); }); + + test('returns string representation of Stash object', () { + File('${tmpDir.path}/stash.this').writeAsStringSync('stash'); + repo.createStash(stasher: stasher, includeUntracked: true); + expect(repo.stashes[0].toString(), contains('Stash{')); + }); }); } diff --git a/test/submodule_test.dart b/test/submodule_test.dart index de483cd..70e49ab 100644 --- a/test/submodule_test.dart +++ b/test/submodule_test.dart @@ -38,6 +38,7 @@ void main() { expect(submodule.workdirOid?.sha, null); expect(submodule.ignore, GitSubmoduleIgnore.none); expect(submodule.updateRule, GitSubmoduleUpdate.checkout); + expect(submodule.toString(), contains('Submodule{')); submodule.free(); }); @@ -70,6 +71,10 @@ void main() { final subHead = submoduleRepo.head; expect(submoduleRepo, isA()); expect(subHead.target.sha, submoduleHeadSha); + expect( + submodule.workdirOid?.sha, + '49322bb17d3acc9146f98c97d078513228bbf3c0', + ); subHead.free(); submoduleRepo.free(); diff --git a/test/tag_test.dart b/test/tag_test.dart index cee25da..b12cffc 100644 --- a/test/tag_test.dart +++ b/test/tag_test.dart @@ -42,12 +42,13 @@ void main() { expect(tag.message, 'annotated tag\n'); expect(target.message, 'add subdirectory file\n'); expect(tagger, signature); + expect(tag.toString(), contains('Tag{')); signature.free(); target.free(); }); - test('successfully creates new tag', () { + test('successfully creates new tag with commit as target', () { final signature = Signature.create( name: 'Author', email: 'author@email.com', @@ -80,6 +81,104 @@ void main() { signature.free(); }); + test('successfully creates new tag with tree as target', () { + final signature = Signature.create( + name: 'Author', + email: 'author@email.com', + time: 1234, + ); + const tagName = 'tag'; + final target = repo['a8ae3dd59e6e1802c6f78e05e301bfd57c9f334f']; + const message = 'init tag\n'; + + final oid = repo.createTag( + tagName: tagName, + target: target, + targetType: GitObject.tree, + tagger: signature, + message: message, + ); + + final newTag = repo.lookupTag(oid); + final tagger = newTag.tagger; + final newTagTarget = newTag.target as Tree; + + expect(newTag.oid.sha, 'ca715c0bafad5d39d568675aad69f71a82178416'); + expect(newTag.name, tagName); + expect(newTag.message, message); + expect(tagger, signature); + expect(newTagTarget.oid, target); + + newTag.free(); + newTagTarget.free(); + signature.free(); + }); + + test('successfully creates new tag with blob as target', () { + final signature = Signature.create( + name: 'Author', + email: 'author@email.com', + time: 1234, + ); + const tagName = 'tag'; + final target = repo['9c78c21d6680a7ffebc76f7ac68cacc11d8f48bc']; + const message = 'init tag\n'; + + final oid = repo.createTag( + tagName: tagName, + target: target, + targetType: GitObject.blob, + tagger: signature, + message: message, + ); + + final newTag = repo.lookupTag(oid); + final tagger = newTag.tagger; + final newTagTarget = newTag.target as Blob; + + expect(newTag.oid.sha, '8b1edabda95e934d2252e563219315b08e38dce5'); + expect(newTag.name, tagName); + expect(newTag.message, message); + expect(tagger, signature); + expect(newTagTarget.oid, target); + + newTag.free(); + newTagTarget.free(); + signature.free(); + }); + + test('successfully creates new tag with tag as target', () { + final signature = Signature.create( + name: 'Author', + email: 'author@email.com', + time: 1234, + ); + const tagName = 'tag'; + const message = 'init tag\n'; + + final oid = repo.createTag( + tagName: tagName, + target: tag.oid, + targetType: GitObject.tag, + tagger: signature, + message: message, + ); + + final newTag = repo.lookupTag(oid); + final tagger = newTag.tagger; + final newTagTarget = newTag.target as Tag; + + expect(newTag.oid.sha, '20286cf6c3b150b58b6c419814b0931d9b17c2ba'); + expect(newTag.name, tagName); + expect(newTag.message, message); + expect(tagger, signature); + expect(newTagTarget.oid, tag.oid); + + newTag.free(); + newTagTarget.free(); + signature.free(); + }); + test('returns list of tags in repository', () { expect(Tag.list(repo), ['v0.1', 'v0.2']); }); diff --git a/test/tree_test.dart b/test/tree_test.dart index 963b5bd..c76548d 100644 --- a/test/tree_test.dart +++ b/test/tree_test.dart @@ -26,6 +26,7 @@ void main() { group('Tree', () { test('successfully initializes tree from provided Oid', () { expect(tree, isA()); + expect(tree.toString(), contains('Tree{')); }); test('returns correct values', () { @@ -55,6 +56,7 @@ void main() { test('returns tree entry with provided path to file', () { final entry = tree['dir/dir_file.txt']; expect(entry.oid.sha, 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'); + expect(entry.toString(), contains('TreeEntry{')); entry.free(); }); @@ -62,6 +64,10 @@ void main() { expect(() => tree['invalid/path'], throwsA(isA())); }); + test('throws when looking up with invalid argument type', () { + expect(() => tree[true], throwsA(isA())); + }); + test('successfully creates tree', () { final fileOid = repo.createBlob('blob content'); final builder = TreeBuilder(repo: repo); diff --git a/test/treebuilder_test.dart b/test/treebuilder_test.dart index 72aa394..5ce8d33 100644 --- a/test/treebuilder_test.dart +++ b/test/treebuilder_test.dart @@ -24,6 +24,7 @@ void main() { test('successfully initializes tree builder when no tree is provided', () { final builder = TreeBuilder(repo: repo); expect(builder, isA()); + expect(builder.toString(), contains('TreeBuilder{')); builder.free(); }); diff --git a/test/worktree_test.dart b/test/worktree_test.dart index f1e0da1..7d831c0 100644 --- a/test/worktree_test.dart +++ b/test/worktree_test.dart @@ -40,6 +40,7 @@ void main() { expect(worktree.name, worktreeName); expect(worktree.path, worktreeDir.path); expect(worktree.isLocked, false); + expect(worktree.toString(), contains('Worktree{')); expect(File('${worktreeDir.path}/.git').existsSync(), true); for (final branch in branches) {