diff --git a/include/git2/tag.h b/include/git2/tag.h index 469b1d72b..c822cee7c 100644 --- a/include/git2/tag.h +++ b/include/git2/tag.h @@ -177,6 +177,37 @@ GIT_EXTERN(int) git_tag_create( const char *message, int force); +/** + * Create a new tag in the object database pointing to a git_object + * + * The message will not be cleaned up. This can be achieved + * through `git_message_prettify()`. + * + * @param oid Pointer where to store the OID of the + * newly created tag + * + * @param repo Repository where to store the tag + * + * @param tag_name Name for the tag + * + * @param target Object to which this tag points. This object + * must belong to the given `repo`. + * + * @param tagger Signature of the tagger for this tag, and + * of the tagging time + * + * @param message Full message for this tag + * + * @return 0 on success or an error code + */ +GIT_EXTERN(int) git_tag_annotation_create( + git_oid *oid, + git_repository *repo, + const char *tag_name, + const git_object *target, + const git_signature *tagger, + const char *message); + /** * Create a new tag in the repository from a buffer * diff --git a/src/tag.c b/src/tag.c index f81956de7..ecf3876cb 100644 --- a/src/tag.c +++ b/src/tag.c @@ -291,6 +291,19 @@ int git_tag_create( return git_tag_create__internal(oid, repo, tag_name, target, tagger, message, allow_ref_overwrite, 1); } +int git_tag_annotation_create( + git_oid *oid, + git_repository *repo, + const char *tag_name, + const git_object *target, + const git_signature *tagger, + const char *message) +{ + assert(oid && repo && tag_name && target && tagger && message); + + return write_tag_annotation(oid, repo, tag_name, target, tagger, message); +} + int git_tag_create_lightweight( git_oid *oid, git_repository *repo, diff --git a/tests-clar/object/tag/write.c b/tests-clar/object/tag/write.c index cd69bea89..68e4b6c61 100644 --- a/tests-clar/object/tag/write.c +++ b/tests-clar/object/tag/write.c @@ -220,3 +220,41 @@ void test_object_tag_write__deleting_with_an_invalid_name_returns_EINVALIDSPEC(v { cl_assert_equal_i(GIT_EINVALIDSPEC, git_tag_delete(g_repo, "Inv@{id")); } + +void create_annotation(git_oid *tag_id, const char *name) +{ + git_object *target; + git_oid target_id; + git_signature *tagger; + + cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + cl_git_pass(git_tag_annotation_create(tag_id, g_repo, name, target, tagger, "boom!")); + git_object_free(target); + git_signature_free(tagger); +} + +void test_object_tag_write__creating_an_annotation_stores_the_new_object_in_the_odb(void) +{ + git_oid tag_id; + git_tag *tag; + + create_annotation(&tag_id, "new_tag"); + + cl_git_pass(git_tag_lookup(&tag, g_repo, &tag_id)); + cl_assert_equal_s("new_tag", git_tag_name(tag)); + + git_tag_free(tag); +} + +void test_object_tag_write__creating_an_annotation_does_not_create_a_reference(void) +{ + git_oid tag_id; + git_reference *tag_ref; + + create_annotation(&tag_id, "new_tag"); + cl_git_fail_with(git_reference_lookup(&tag_ref, g_repo, "refs/tags/new_tag"), GIT_ENOTFOUND); +}