diff --git a/include/git2/tag.h b/include/git2/tag.h index ee92cd5c2..b83d44733 100644 --- a/include/git2/tag.h +++ b/include/git2/tag.h @@ -140,7 +140,8 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *t); * @param repo Repository where to store the tag * * @param tag_name Name for the tag; this name is validated - * for consistency + * for consistency. It should also not conflict with an + * already existing tag name * * @param target OID to which this tag points; note that no * validation is done on this OID. Use the _o version of this diff --git a/src/tag.c b/src/tag.c index 7baababbf..9a0069448 100644 --- a/src/tag.c +++ b/src/tag.c @@ -182,10 +182,18 @@ int git_tag_create( const char *type_str; char *tagger_str; + git_reference *new_ref; + + char ref_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH]; int type_str_len, tag_name_len, tagger_str_len, message_len; int error; + /** Ensure the tag name doesn't conflict with an already existing reference **/ + git__joinpath(ref_name, GIT_REFS_TAGS_DIR, tag_name); + if (!git_reference_lookup(&new_ref, repo, ref_name)) + return GIT_EEXISTS; + type_str = git_object_type2string(target_type); @@ -223,14 +231,10 @@ int git_tag_create( error = stream->finalize_write(oid, stream); stream->free(stream); - if (error == GIT_SUCCESS) { - char ref_name[512]; - git_reference *new_ref; - git__joinpath(ref_name, GIT_REFS_TAGS_DIR, tag_name); - error = git_reference_create_oid(&new_ref, repo, ref_name, oid); - } + if (error < GIT_SUCCESS) + return error; - return error; + return git_reference_create_oid(&new_ref, repo, ref_name, oid); } diff --git a/tests/t08-tag.c b/tests/t08-tag.c index 7b3c88649..371f8621c 100644 --- a/tests/t08-tag.c +++ b/tests/t08-tag.c @@ -156,9 +156,38 @@ BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid END_TEST +BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already existing tag") + git_repository *repo; + git_oid target_id, tag_id; + const git_signature *tagger; + + must_pass(git_repository_open(&repo, REPOSITORY_FOLDER)); + + git_oid_mkstr(&target_id, tagged_commit); + + /* create signature */ + tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60); + must_be_true(tagger != NULL); + + must_fail(git_tag_create( + &tag_id, /* out id */ + repo, + "very-simple", + &target_id, + GIT_OBJ_COMMIT, + tagger, + TAGGER_MESSAGE)); + + git_signature_free((git_signature *)tagger); + + git_repository_free(repo); + +END_TEST + BEGIN_SUITE(tag) ADD_TEST(read0); ADD_TEST(write0); ADD_TEST(write1); + ADD_TEST(write2); END_SUITE