mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-04 20:29:08 -04:00
feat(tag): add bindings and api
This commit is contained in:
parent
f0803298c8
commit
0cdaa6f8f4
10 changed files with 392 additions and 1 deletions
|
@ -10,5 +10,6 @@ export 'src/tree.dart';
|
||||||
export 'src/signature.dart';
|
export 'src/signature.dart';
|
||||||
export 'src/revwalk.dart';
|
export 'src/revwalk.dart';
|
||||||
export 'src/blob.dart';
|
export 'src/blob.dart';
|
||||||
|
export 'src/tag.dart';
|
||||||
export 'src/error.dart';
|
export 'src/error.dart';
|
||||||
export 'src/enums.dart';
|
export 'src/enums.dart';
|
||||||
|
|
|
@ -1,6 +1,41 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
|
import 'package:ffi/ffi.dart';
|
||||||
import 'libgit2_bindings.dart';
|
import 'libgit2_bindings.dart';
|
||||||
|
import '../error.dart';
|
||||||
import '../util.dart';
|
import '../util.dart';
|
||||||
|
|
||||||
/// Get the object type of an object.
|
/// Get the object type of an object.
|
||||||
int type(Pointer<git_object> obj) => libgit2.git_object_type(obj);
|
int type(Pointer<git_object> obj) => libgit2.git_object_type(obj);
|
||||||
|
|
||||||
|
/// Lookup a reference to one of the objects in a repository.
|
||||||
|
///
|
||||||
|
/// The generated reference is owned by the repository and should be closed with
|
||||||
|
/// the `free()` method instead of free'd manually.
|
||||||
|
///
|
||||||
|
/// The 'type' parameter must match the type of the object in the odb; the method will
|
||||||
|
/// fail otherwise. The special value 'GIT_OBJECT_ANY' may be passed to let the method
|
||||||
|
/// guess the object's type.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_object> lookup(
|
||||||
|
Pointer<git_repository> repo,
|
||||||
|
Pointer<git_oid> id,
|
||||||
|
int type,
|
||||||
|
) {
|
||||||
|
final out = calloc<Pointer<git_object>>();
|
||||||
|
final error = libgit2.git_object_lookup(out, repo, id, type);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close an open object to release memory.
|
||||||
|
///
|
||||||
|
/// This method instructs the library to close an existing object; note that git_objects
|
||||||
|
/// are owned and cached by the repository so the object may or may not be freed after
|
||||||
|
/// this library call, depending on how aggressive is the caching mechanism used by
|
||||||
|
/// the repository.
|
||||||
|
void free(Pointer<git_object> object) => libgit2.git_object_free(object);
|
||||||
|
|
97
lib/src/bindings/tag.dart
Normal file
97
lib/src/bindings/tag.dart
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
import 'package:ffi/ffi.dart';
|
||||||
|
import '../error.dart';
|
||||||
|
import 'libgit2_bindings.dart';
|
||||||
|
import '../util.dart';
|
||||||
|
|
||||||
|
/// Lookup a tag object from the repository.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_tag> lookup(Pointer<git_repository> repo, Pointer<git_oid> id) {
|
||||||
|
final out = calloc<Pointer<git_tag>>();
|
||||||
|
final error = libgit2.git_tag_lookup(out, repo, id);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the tagged object of a tag.
|
||||||
|
///
|
||||||
|
/// This method performs a repository lookup for the given object and returns it.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_object> target(Pointer<git_tag> tag) {
|
||||||
|
final out = calloc<Pointer<git_object>>();
|
||||||
|
final error = libgit2.git_tag_target(out, tag);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the id of a tag.
|
||||||
|
Pointer<git_oid> id(Pointer<git_tag> tag) => libgit2.git_tag_id(tag);
|
||||||
|
|
||||||
|
/// Get the name of a tag.
|
||||||
|
String name(Pointer<git_tag> tag) =>
|
||||||
|
libgit2.git_tag_name(tag).cast<Utf8>().toDartString();
|
||||||
|
|
||||||
|
/// Get the message of a tag.
|
||||||
|
String message(Pointer<git_tag> tag) =>
|
||||||
|
libgit2.git_tag_message(tag).cast<Utf8>().toDartString();
|
||||||
|
|
||||||
|
/// Get the tagger (author) of a tag.
|
||||||
|
Pointer<git_signature> tagger(Pointer<git_tag> tag) =>
|
||||||
|
libgit2.git_tag_tagger(tag);
|
||||||
|
|
||||||
|
/// Create a new tag in the repository from an object.
|
||||||
|
///
|
||||||
|
/// A new reference will also be created pointing to this tag object. If force is true
|
||||||
|
/// and a reference already exists with the given name, it'll be replaced.
|
||||||
|
///
|
||||||
|
/// The message will not be cleaned up.
|
||||||
|
///
|
||||||
|
/// The tag name will be checked for validity. You must avoid the characters
|
||||||
|
/// '~', '^', ':', '\', '?', '[', and '*', and the sequences ".." and "@{" which have
|
||||||
|
/// special meaning to revparse.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_oid> create(
|
||||||
|
Pointer<git_repository> repo,
|
||||||
|
String tagName,
|
||||||
|
Pointer<git_object> target,
|
||||||
|
Pointer<git_signature> tagger,
|
||||||
|
String message,
|
||||||
|
bool force,
|
||||||
|
) {
|
||||||
|
final out = calloc<git_oid>();
|
||||||
|
final tagNameC = tagName.toNativeUtf8().cast<Int8>();
|
||||||
|
final messageC = message.toNativeUtf8().cast<Int8>();
|
||||||
|
final forceC = force ? 1 : 0;
|
||||||
|
final error = libgit2.git_tag_create(
|
||||||
|
out,
|
||||||
|
repo,
|
||||||
|
tagNameC,
|
||||||
|
target,
|
||||||
|
tagger,
|
||||||
|
messageC,
|
||||||
|
forceC,
|
||||||
|
);
|
||||||
|
|
||||||
|
calloc.free(tagNameC);
|
||||||
|
calloc.free(messageC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close an open tag to release memory.
|
||||||
|
void free(Pointer<git_tag> tag) => libgit2.git_tag_free(tag);
|
|
@ -12,6 +12,8 @@ import 'revwalk.dart';
|
||||||
import 'revparse.dart';
|
import 'revparse.dart';
|
||||||
import 'blob.dart';
|
import 'blob.dart';
|
||||||
import 'enums.dart';
|
import 'enums.dart';
|
||||||
|
import 'signature.dart';
|
||||||
|
import 'tag.dart';
|
||||||
import 'util.dart';
|
import 'util.dart';
|
||||||
|
|
||||||
class Repository {
|
class Repository {
|
||||||
|
@ -397,4 +399,34 @@ class Repository {
|
||||||
///
|
///
|
||||||
/// Throws a [LibGit2Error] if error occured.
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
Oid createBlobFromDisk(String path) => Blob.createFromDisk(this, path);
|
Oid createBlobFromDisk(String path) => Blob.createFromDisk(this, path);
|
||||||
|
|
||||||
|
/// Creates a new tag in the repository from provided Oid object.
|
||||||
|
///
|
||||||
|
/// A new reference will also be created pointing to this tag object. If force is true
|
||||||
|
/// and a reference already exists with the given name, it'll be replaced.
|
||||||
|
///
|
||||||
|
/// The message will not be cleaned up.
|
||||||
|
///
|
||||||
|
/// The tag name will be checked for validity. You must avoid the characters
|
||||||
|
/// '~', '^', ':', '\', '?', '[', and '*', and the sequences ".." and "@{" which have
|
||||||
|
/// special meaning to revparse.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Oid createTag({
|
||||||
|
required String tagName,
|
||||||
|
required Oid target,
|
||||||
|
required GitObject targetType,
|
||||||
|
required Signature tagger,
|
||||||
|
required String message,
|
||||||
|
bool force = false,
|
||||||
|
}) {
|
||||||
|
return Tag.create(
|
||||||
|
repository: this,
|
||||||
|
tagName: tagName,
|
||||||
|
target: target,
|
||||||
|
targetType: targetType,
|
||||||
|
tagger: tagger,
|
||||||
|
message: message,
|
||||||
|
force: force);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
94
lib/src/tag.dart
Normal file
94
lib/src/tag.dart
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
import 'dart:ffi';
|
||||||
|
|
||||||
|
import 'bindings/libgit2_bindings.dart';
|
||||||
|
import 'bindings/tag.dart' as bindings;
|
||||||
|
import 'bindings/object.dart' as object_bindings;
|
||||||
|
import 'commit.dart';
|
||||||
|
import 'oid.dart';
|
||||||
|
import 'repository.dart';
|
||||||
|
import 'signature.dart';
|
||||||
|
import 'enums.dart';
|
||||||
|
|
||||||
|
class Tag {
|
||||||
|
/// Initializes a new instance of [Tag] class from provided
|
||||||
|
/// [Repository] and [Oid] objects.
|
||||||
|
///
|
||||||
|
/// Should be freed with `free()` to release allocated memory.
|
||||||
|
Tag.lookup(Repository repo, Oid oid) {
|
||||||
|
_tagPointer = bindings.lookup(repo.pointer, oid.pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final Pointer<git_tag> _tagPointer;
|
||||||
|
|
||||||
|
/// Pointer to memory address for allocated tag object.
|
||||||
|
Pointer<git_tag> get pointer => _tagPointer;
|
||||||
|
|
||||||
|
/// Creates a new tag in the repository from provided Oid object.
|
||||||
|
///
|
||||||
|
/// A new reference will also be created pointing to this tag object. If force is true
|
||||||
|
/// and a reference already exists with the given name, it'll be replaced.
|
||||||
|
///
|
||||||
|
/// The message will not be cleaned up.
|
||||||
|
///
|
||||||
|
/// The tag name will be checked for validity. You must avoid the characters
|
||||||
|
/// '~', '^', ':', '\', '?', '[', and '*', and the sequences ".." and "@{" which have
|
||||||
|
/// special meaning to revparse.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
static Oid create({
|
||||||
|
required Repository repository,
|
||||||
|
required String tagName,
|
||||||
|
required Oid target,
|
||||||
|
required GitObject targetType,
|
||||||
|
required Signature tagger,
|
||||||
|
required String message,
|
||||||
|
bool force = false,
|
||||||
|
}) {
|
||||||
|
// add 1 to GitObject enum index to match libgit2
|
||||||
|
final object = object_bindings.lookup(
|
||||||
|
repository.pointer,
|
||||||
|
target.pointer,
|
||||||
|
targetType.index + 1,
|
||||||
|
);
|
||||||
|
final result = bindings.create(
|
||||||
|
repository.pointer,
|
||||||
|
tagName,
|
||||||
|
object,
|
||||||
|
tagger.pointer,
|
||||||
|
message,
|
||||||
|
force,
|
||||||
|
);
|
||||||
|
|
||||||
|
object_bindings.free(object);
|
||||||
|
return Oid(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the tagged object of a tag.
|
||||||
|
///
|
||||||
|
/// This method performs a repository lookup for the given object and returns it.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Commit get target => Commit(bindings.target(_tagPointer).cast());
|
||||||
|
|
||||||
|
/// Get the id of a tag.
|
||||||
|
Oid get id => Oid(bindings.id(_tagPointer));
|
||||||
|
|
||||||
|
/// Returns the name of a tag.
|
||||||
|
String get name => bindings.name(_tagPointer);
|
||||||
|
|
||||||
|
/// Returns the message of a tag.
|
||||||
|
String get message => bindings.message(_tagPointer);
|
||||||
|
|
||||||
|
/// Returns the tagger (author) of a tag if there is one.
|
||||||
|
Signature? get tagger {
|
||||||
|
final sigPointer = bindings.tagger(_tagPointer);
|
||||||
|
if (sigPointer != nullptr) {
|
||||||
|
return Signature(sigPointer);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases memory allocated for tag object.
|
||||||
|
void free() => bindings.free(_tagPointer);
|
||||||
|
}
|
Binary file not shown.
1
test/assets/testrepo/.gitdir/refs/tags/v0.2
Normal file
1
test/assets/testrepo/.gitdir/refs/tags/v0.2
Normal file
|
@ -0,0 +1 @@
|
||||||
|
f0fdbf506397e9f58c59b88dfdd72778ec06cc0c
|
|
@ -30,7 +30,12 @@ void main() {
|
||||||
test('returns a list', () {
|
test('returns a list', () {
|
||||||
expect(
|
expect(
|
||||||
repo.references.list(),
|
repo.references.list(),
|
||||||
['refs/heads/feature', 'refs/heads/master', 'refs/tags/v0.1'],
|
[
|
||||||
|
'refs/heads/feature',
|
||||||
|
'refs/heads/master',
|
||||||
|
'refs/tags/v0.1',
|
||||||
|
'refs/tags/v0.2',
|
||||||
|
],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -304,6 +304,41 @@ void main() {
|
||||||
newBlob.free();
|
newBlob.free();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('successfully creates tag with provided Oid', () {
|
||||||
|
final signature = Signature.create(
|
||||||
|
name: 'Author',
|
||||||
|
email: 'author@email.com',
|
||||||
|
time: 1234,
|
||||||
|
);
|
||||||
|
const tagName = 'tag';
|
||||||
|
final target =
|
||||||
|
Oid.fromSHA(repo, 'f17d0d48eae3aa08cecf29128a35e310c97b3521');
|
||||||
|
const message = 'init tag\n';
|
||||||
|
|
||||||
|
final oid = Tag.create(
|
||||||
|
repository: repo,
|
||||||
|
tagName: tagName,
|
||||||
|
target: target,
|
||||||
|
targetType: GitObject.commit,
|
||||||
|
tagger: signature,
|
||||||
|
message: message,
|
||||||
|
);
|
||||||
|
|
||||||
|
final newTag = Tag.lookup(repo, oid);
|
||||||
|
final tagger = newTag.tagger;
|
||||||
|
final newTagTarget = newTag.target;
|
||||||
|
|
||||||
|
expect(newTag.id.sha, '131a5eb6b7a880b5096c550ee7351aeae7b95a42');
|
||||||
|
expect(newTag.name, tagName);
|
||||||
|
expect(newTag.message, message);
|
||||||
|
expect(tagger, signature);
|
||||||
|
expect(newTagTarget.id, target);
|
||||||
|
|
||||||
|
newTag.free();
|
||||||
|
newTagTarget.free();
|
||||||
|
signature.free();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
91
test/tag_test.dart
Normal file
91
test/tag_test.dart
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:libgit2dart/libgit2dart.dart';
|
||||||
|
import 'helpers/util.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late Repository repo;
|
||||||
|
late Tag tag;
|
||||||
|
final tmpDir = '${Directory.systemTemp.path}/tag_testrepo/';
|
||||||
|
const tagSHA = 'f0fdbf506397e9f58c59b88dfdd72778ec06cc0c';
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
if (await Directory(tmpDir).exists()) {
|
||||||
|
await Directory(tmpDir).delete(recursive: true);
|
||||||
|
}
|
||||||
|
await copyRepo(
|
||||||
|
from: Directory('test/assets/testrepo/'),
|
||||||
|
to: await Directory(tmpDir).create(),
|
||||||
|
);
|
||||||
|
repo = Repository.open(tmpDir);
|
||||||
|
tag = Tag.lookup(repo, Oid.fromSHA(repo, tagSHA));
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() async {
|
||||||
|
tag.free();
|
||||||
|
repo.free();
|
||||||
|
await Directory(tmpDir).delete(recursive: true);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Tag', () {
|
||||||
|
test('successfully initializes tag from provided Oid', () {
|
||||||
|
expect(tag, isA<Tag>());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns correct values', () {
|
||||||
|
final signature = Signature.create(
|
||||||
|
name: 'Aleksey Kulikov',
|
||||||
|
email: 'skinny.mind@gmail.com',
|
||||||
|
time: 1630599723,
|
||||||
|
offset: 180,
|
||||||
|
);
|
||||||
|
final target = tag.target;
|
||||||
|
final tagger = tag.tagger;
|
||||||
|
|
||||||
|
expect(tag.id.sha, tagSHA);
|
||||||
|
expect(tag.name, 'v0.2');
|
||||||
|
expect(tag.message, 'annotated tag\n');
|
||||||
|
expect(target.message, 'add subdirectory file\n');
|
||||||
|
expect(tagger, signature);
|
||||||
|
|
||||||
|
signature.free();
|
||||||
|
target.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully creates new tag', () {
|
||||||
|
final signature = Signature.create(
|
||||||
|
name: 'Author',
|
||||||
|
email: 'author@email.com',
|
||||||
|
time: 1234,
|
||||||
|
);
|
||||||
|
const tagName = 'tag';
|
||||||
|
final target =
|
||||||
|
Oid.fromSHA(repo, 'f17d0d48eae3aa08cecf29128a35e310c97b3521');
|
||||||
|
const message = 'init tag\n';
|
||||||
|
|
||||||
|
final oid = Tag.create(
|
||||||
|
repository: repo,
|
||||||
|
tagName: tagName,
|
||||||
|
target: target,
|
||||||
|
targetType: GitObject.commit,
|
||||||
|
tagger: signature,
|
||||||
|
message: message,
|
||||||
|
);
|
||||||
|
|
||||||
|
final newTag = Tag.lookup(repo, oid);
|
||||||
|
final tagger = newTag.tagger;
|
||||||
|
final newTagTarget = newTag.target;
|
||||||
|
|
||||||
|
expect(newTag.id.sha, '131a5eb6b7a880b5096c550ee7351aeae7b95a42');
|
||||||
|
expect(newTag.name, tagName);
|
||||||
|
expect(newTag.message, message);
|
||||||
|
expect(tagger, signature);
|
||||||
|
expect(newTagTarget.id, target);
|
||||||
|
|
||||||
|
newTag.free();
|
||||||
|
newTagTarget.free();
|
||||||
|
signature.free();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue