diff options
| -rw-r--r-- | include/git2/tag.h | 40 | ||||
| -rw-r--r-- | src/tag.c | 85 | ||||
| -rw-r--r-- | tests/t08-tag.c | 64 |
3 files changed, 163 insertions, 26 deletions
diff --git a/include/git2/tag.h b/include/git2/tag.h index 71b27bb3e..3c3266183 100644 --- a/include/git2/tag.h +++ b/include/git2/tag.h @@ -149,7 +149,7 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *tag); /** - * Create a new tag in the repository from an OID + * 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 @@ -157,7 +157,7 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *tag); * * @param oid Pointer where to store the OID of the * newly created tag. If the tag already exists, this parameter - * will be the oid of the existed tag, and the function will + * will be the oid of the existing tag, and the function will * return a GIT_EEXISTS error code. * * @param repo Repository where to store the tag @@ -174,7 +174,7 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *tag); * * @param message Full message for this tag * - * @param force Overwritte existing references + * @param force Overwrite existing references * * @return 0 on success; error code otherwise. * A tag object is written to the ODB, and a proper reference @@ -205,6 +205,40 @@ GIT_EXTERN(int) git_tag_create_frombuffer( int force); /** + * Create a new lightweight tag pointing at a target object + * + * A new direct reference will be created pointing to + * this target object. If `force` is true and a reference + * already exists with the given name, it'll be replaced. + * + * @param oid Pointer where to store the OID of the provided + * target object. If the tag already exists, this parameter + * will be filled with the oid of the existing pointed object + * and the function will return a GIT_EEXISTS error code. + * + * @param repo Repository where to store the lightweight tag + * + * @param tag_name Name for the tag; this name is validated + * for consistency. It should also not conflict with an + * already existing tag name + * + * @param target Object to which this tag points. This object + * must belong to the given `repo`. + * + * @param force Overwrite existing references + * + * @return 0 on success; error code otherwise. + * A proper reference is written in the /refs/tags folder, + * pointing to the provided target object + */ +int git_tag_create_lightweight( + git_oid *oid, + git_repository *repo, + const char *tag_name, + const git_object *target, + int force); + +/** * Delete an existing tag reference. * * @param repo Repository where lives the tag @@ -180,21 +180,56 @@ static int retreive_tag_reference(git_reference **tag_reference_out, char *ref_n return GIT_SUCCESS; } -int git_tag_create( +static int write_tag_annotation( + git_oid *oid, + git_repository *repo, + const char *tag_name, + const git_object *target, + const git_signature *tagger, + const char *message) +{ + int error = GIT_SUCCESS; + git_buf tag = GIT_BUF_INIT; + + git_oid__writebuf(&tag, "object ", git_object_id(target)); + git_buf_printf(&tag, "type %s\n", git_object_type2string(git_object_type(target))); + git_buf_printf(&tag, "tag %s\n", tag_name); + git_signature__writebuf(&tag, "tagger ", tagger); + git_buf_putc(&tag, '\n'); + git_buf_puts(&tag, message); + + if (git_buf_oom(&tag)) { + git_buf_free(&tag); + return git__throw(GIT_ENOMEM, "Not enough memory to build the tag data"); + } + + error = git_odb_write(oid, git_repository_database(repo), tag.ptr, tag.size, GIT_OBJ_TAG); + git_buf_free(&tag); + + if (error < GIT_SUCCESS) + return git__rethrow(error, "Failed to create tag annotation"); + + return error; +} + +static int git_tag_create__internal( git_oid *oid, git_repository *repo, const char *tag_name, const git_object *target, const git_signature *tagger, const char *message, - int allow_ref_overwrite) + int allow_ref_overwrite, + int create_tag_annotation) { git_reference *new_ref = NULL; char ref_name[GIT_REFNAME_MAX]; - git_buf tag = GIT_BUF_INIT; int error, should_update_ref = 0; + assert(repo && tag_name && target); + assert(!create_tag_annotation || (tagger && message)); + if (git_object_owner(target) != repo) return git__throw(GIT_EINVALIDARGS, "The given target does not belong to this repository"); @@ -220,23 +255,11 @@ int git_tag_create( } } - git_oid__writebuf(&tag, "object ", git_object_id(target)); - git_buf_printf(&tag, "type %s\n", git_object_type2string(git_object_type(target))); - git_buf_printf(&tag, "tag %s\n", tag_name); - git_signature__writebuf(&tag, "tagger ", tagger); - git_buf_putc(&tag, '\n'); - git_buf_puts(&tag, message); - - if (git_buf_oom(&tag)) { - git_buf_free(&tag); - return git__throw(GIT_ENOMEM, "Not enough memory to build the tag data"); - } - - error = git_odb_write(oid, git_repository_database(repo), tag.ptr, tag.size, GIT_OBJ_TAG); - git_buf_free(&tag); - - if (error < GIT_SUCCESS) - return git__rethrow(error, "Failed to create tag"); + if (create_tag_annotation) { + if ((error = write_tag_annotation(oid, repo, tag_name, target, tagger, message)) < GIT_SUCCESS) + return error; + } else + git_oid_cpy(oid, git_object_id(target)); if (!should_update_ref) error = git_reference_create_oid(&new_ref, repo, ref_name, oid, 0); @@ -246,6 +269,28 @@ int git_tag_create( return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag"); } +int git_tag_create( + git_oid *oid, + git_repository *repo, + const char *tag_name, + const git_object *target, + const git_signature *tagger, + const char *message, + int allow_ref_overwrite) +{ + return git_tag_create__internal(oid, repo, tag_name, target, tagger, message, allow_ref_overwrite, 1); +} + +int git_tag_create_lightweight( + git_oid *oid, + git_repository *repo, + const char *tag_name, + const git_object *target, + int allow_ref_overwrite) +{ + return git_tag_create__internal(oid, repo, tag_name, target, NULL, NULL, allow_ref_overwrite, 0); +} + int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer, int allow_ref_overwrite) { git_tag tag; diff --git a/tests/t08-tag.c b/tests/t08-tag.c index aeff8b360..2e33055e8 100644 --- a/tests/t08-tag.c +++ b/tests/t08-tag.c @@ -234,18 +234,72 @@ BEGIN_TEST(write3, "Replace an already existing tag") END_TEST -BEGIN_TEST(write4, "Delete an already existing tag") +BEGIN_TEST(write4, "write a lightweight tag to the repository and read it again") + git_repository *repo; + git_oid target_id, object_id; + git_reference *ref_tag; + git_object *target; + + must_pass(git_repository_open(&repo, REPOSITORY_FOLDER)); + + git_oid_fromstr(&target_id, tagged_commit); + must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT)); + + must_pass(git_tag_create_lightweight( + &object_id, + repo, + "light-tag", + target, + 0)); + + git_object_close(target); + + must_be_true(git_oid_cmp(&object_id, &target_id) == 0); + + must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/light-tag")); + must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &target_id) == 0); + + must_pass(git_tag_delete(repo, "light-tag")); + + git_repository_free(repo); +END_TEST + +BEGIN_TEST(write5, "Attempt to write a lightweight tag bearing the same name than an already existing tag") + git_repository *repo; + git_oid target_id, object_id, existing_object_id; + git_object *target; + + must_pass(git_repository_open(&repo, REPOSITORY_FOLDER)); + + git_oid_fromstr(&target_id, tagged_commit); + must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT)); + + must_fail(git_tag_create_lightweight( + &object_id, + repo, + "e90810b", + target, + 0)); + + git_oid_fromstr(&existing_object_id, tag2_id); + must_be_true(git_oid_cmp(&object_id, &existing_object_id) == 0); + + git_object_close(target); + + git_repository_free(repo); +END_TEST + +BEGIN_TEST(delete0, "Delete an already existing tag") git_repository *repo; git_reference *ref_tag; must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER)); - must_pass(git_tag_delete(repo,"e90810b")); + must_pass(git_tag_delete(repo, "e90810b")); must_fail(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b")); close_temp_repo(repo); - END_TEST BEGIN_SUITE(tag) @@ -257,4 +311,8 @@ BEGIN_SUITE(tag) ADD_TEST(write2); ADD_TEST(write3); ADD_TEST(write4); + ADD_TEST(write5); + + ADD_TEST(delete0); + END_SUITE |
