tag: Deploy EINVALIDSPEC usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
diff --git a/include/git2/tag.h b/include/git2/tag.h
index f82a6c9..a9773be 100644
--- a/include/git2/tag.h
+++ b/include/git2/tag.h
@@ -144,6 +144,10 @@ GIT_EXTERN(const char *) git_tag_message(const git_tag *tag);
* The message will not be cleaned up. This can be achieved
* through `git_message_prettify()`.
*
+ * The tag name will be checked for validity. You must avoid
+ * the characters '~', '^', ':', '\\', '?', '[', and '*', and the
+ * sequences ".." and "@{" which have special meaning to revparse.
+ *
* @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 existing tag, and the function will
@@ -165,7 +169,7 @@ GIT_EXTERN(const char *) git_tag_message(const git_tag *tag);
*
* @param force Overwrite existing references
*
- * @return 0 or an error code
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
* A tag object is written to the ODB, and a proper reference
* is written in the /refs/tags folder, pointing to it
*/
@@ -200,6 +204,9 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
* this target object. If `force` is true and a reference
* already exists with the given name, it'll be replaced.
*
+ * The tag name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @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
@@ -216,7 +223,7 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
*
* @param force Overwrite existing references
*
- * @return 0 or an error code
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
* A proper reference is written in the /refs/tags folder,
* pointing to the provided target object
*/
@@ -230,12 +237,15 @@ GIT_EXTERN(int) git_tag_create_lightweight(
/**
* Delete an existing tag reference.
*
+ * The tag name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param repo Repository where lives the tag
*
* @param tag_name Name of the tag to be deleted;
* this name is validated for consistency.
*
- * @return 0 or an error code
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_tag_delete(
git_repository *repo,
diff --git a/src/tag.c b/src/tag.c
index 606afd6..94915ad 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -251,7 +251,7 @@ static int git_tag_create__internal(
error = retrieve_tag_reference_oid(oid, &ref_name, repo, tag_name);
if (error < 0 && error != GIT_ENOTFOUND)
- return -1;
+ goto cleanup;
/** Ensure the tag name doesn't conflict with an already existing
* reference unless overwriting has explictly been requested **/
@@ -269,6 +269,7 @@ static int git_tag_create__internal(
error = git_reference_create(&new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite);
+cleanup:
git_reference_free(new_ref);
git_buf_free(&ref_name);
return error;
@@ -384,7 +385,7 @@ int git_tag_delete(git_repository *repo, const char *tag_name)
git_buf_free(&ref_name);
if (error < 0)
- return -1;
+ return error;
return git_reference_delete(tag_ref);
}
diff --git a/tests-clar/object/tag/write.c b/tests-clar/object/tag/write.c
index ad6ca76..eb0ac28 100644
--- a/tests-clar/object/tag/write.c
+++ b/tests-clar/object/tag/write.c
@@ -88,7 +88,6 @@ void test_object_tag_write__overwrite(void)
git_object_free(target);
git_signature_free(tagger);
-
}
void test_object_tag_write__replace(void)
@@ -190,3 +189,33 @@ void test_object_tag_write__delete(void)
git_reference_free(ref_tag);
}
+
+void test_object_tag_write__creating_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ git_oid target_id, tag_id;
+ git_signature *tagger;
+ git_object *target;
+
+ 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_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60));
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_tag_create(&tag_id, g_repo,
+ "Inv@{id", target, tagger, tagger_message, 0)
+ );
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_tag_create_lightweight(&tag_id, g_repo,
+ "Inv@{id", target, 0)
+ );
+
+ git_object_free(target);
+ git_signature_free(tagger);
+}
+
+void test_object_tag_write__deleting_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_tag_delete(g_repo, "Inv@{id"));
+}