]> git.proxmox.com Git - libgit2.git/commitdiff
Add git_tag_create_o_f() and git_tag_create_f() which overwrite existing tag referenc...
authornulltoken <emeric.fermas@gmail.com>
Wed, 30 Mar 2011 21:16:30 +0000 (23:16 +0200)
committernulltoken <emeric.fermas@gmail.com>
Wed, 30 Mar 2011 21:16:30 +0000 (23:16 +0200)
include/git2/tag.h
src/tag.c
tests/t08-tag.c

index b83d44733a99cc70428387b214d47cbd061f6d20..6468cfdd7c395bc7e46499c6e16ab210f983a157 100644 (file)
@@ -189,6 +189,64 @@ GIT_EXTERN(int) git_tag_create_o(
                const git_signature *tagger,
                const char *message);
 
+/**
+* Create a new tag in the repository from an OID
+* and overwrite an already existing tag reference, if any.
+*
+* @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; this name is validated
+* for consistency.
+*
+* @param target OID to which this tag points; note that no
+*      validation is done on this OID. Use the _o_f version of this
+*      method to assure a proper object is being tagged
+*
+* @param target_type Type of the tagged OID; note that no
+*      validation is performed here either
+*
+* @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; error code otherwise.
+*      A tag object is written to the ODB, and a proper reference
+*      is written in the /refs/tags folder, pointing to it
+*/
+GIT_EXTERN(int) git_tag_create_f(
+               git_oid *oid,
+               git_repository *repo,
+               const char *tag_name,
+               const git_oid *target,
+               git_otype target_type,
+               const git_signature *tagger,
+               const char *message);
+
+/**
+ * Create a new tag in the repository from an existing
+ * `git_object` instance and overwrite an already existing 
+ * tag reference, if any.
+ *
+ * This method replaces the `target` and `target_type`
+ * paremeters of `git_tag_create_f` by a single instance
+ * of a `const git_object *`, which is assured to be
+ * a proper object in the ODB and hence will create
+ * a valid tag
+ *
+ * @see git_tag_create_f
+ */
+GIT_EXTERN(int) git_tag_create_o_f(
+               git_oid *oid,
+               git_repository *repo,
+               const char *tag_name,
+               const git_object *target,
+               const git_signature *tagger,
+               const char *message);
+
 /** @} */
 GIT_END_DECL
 #endif
index 9a0069448086b5220af785c897c077eabca94ea9..e75c46916a8094763c08517d4f73c2d28318a531 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -153,29 +153,15 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end)
        return GIT_SUCCESS;
 }
 
-int git_tag_create_o(
-               git_oid *oid,
-               git_repository *repo,
-               const char *tag_name,
-               const git_object *target,
-               const git_signature *tagger,
-               const char *message)
-{
-       return git_tag_create(
-               oid, repo, tag_name, 
-               git_object_id(target),
-               git_object_type(target),
-               tagger, message);
-}
-
-int git_tag_create(
+static int tag_create(
                git_oid *oid,
                git_repository *repo,
                const char *tag_name,
                const git_oid *target,
                git_otype target_type,
                const git_signature *tagger,
-               const char *message)
+               const char *message,
+               int allow_ref_overwrite)
 {
        size_t final_size = 0;
        git_odb_stream *stream;
@@ -187,12 +173,27 @@ int git_tag_create(
        char ref_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
 
        int type_str_len, tag_name_len, tagger_str_len, message_len;
-       int error;
+       int error, should_update_ref = 0;
 
-       /** Ensure the tag name doesn't conflict with an already existing reference **/
+       /** Ensure the tag name doesn't conflict with an already existing 
+           reference unless overwriting has explictly been requested **/
        git__joinpath(ref_name, GIT_REFS_TAGS_DIR, tag_name);
-       if (!git_reference_lookup(&new_ref, repo, ref_name))
-               return GIT_EEXISTS;     
+       error = git_reference_lookup(&new_ref, repo, ref_name);
+
+       switch (error) {
+       case GIT_SUCCESS:
+               if (!allow_ref_overwrite)
+                       return GIT_EEXISTS;     
+               should_update_ref = 1;
+               
+               /* Fall trough */
+
+       case GIT_ENOTFOUND: 
+               break;
+
+       default:
+               return error;
+       }
 
 
        type_str = git_object_type2string(target_type);
@@ -234,9 +235,75 @@ int git_tag_create(
        if (error < GIT_SUCCESS)
                return error;
 
-       return git_reference_create_oid(&new_ref, repo, ref_name, oid);
+       if (!should_update_ref)
+               error = git_reference_create_oid(&new_ref, repo, ref_name, oid);
+       else
+               error = git_reference_set_oid(new_ref, oid);
+       
+       return error;
+}
+
+int git_tag_create_o(
+               git_oid *oid,
+               git_repository *repo,
+               const char *tag_name,
+               const git_object *target,
+               const git_signature *tagger,
+               const char *message)
+{
+       return tag_create(
+               oid, repo, tag_name, 
+               git_object_id(target),
+               git_object_type(target),
+               tagger, message, 0);
+}
+
+int git_tag_create(
+               git_oid *oid,
+               git_repository *repo,
+               const char *tag_name,
+               const git_oid *target,
+               git_otype target_type,
+               const git_signature *tagger,
+               const char *message)
+{
+       return tag_create(
+               oid, repo, tag_name, 
+               target,
+               target_type,
+               tagger, message, 0);
+}
+
+int git_tag_create_o_f(
+               git_oid *oid,
+               git_repository *repo,
+               const char *tag_name,
+               const git_object *target,
+               const git_signature *tagger,
+               const char *message)
+{
+       return tag_create(
+               oid, repo, tag_name, 
+               git_object_id(target),
+               git_object_type(target),
+               tagger, message, 1);
 }
 
+int git_tag_create_f(
+               git_oid *oid,
+               git_repository *repo,
+               const char *tag_name,
+               const git_oid *target,
+               git_otype target_type,
+               const git_signature *tagger,
+               const char *message)
+{
+       return tag_create(
+               oid, repo, tag_name, 
+               target,
+               target_type,
+               tagger, message, 1);
+}
 
 int git_tag__parse(git_tag *tag, git_odb_object *obj)
 {
index a5bdee3e0ddfbcee46cd457ed52288ac697f2df8..2bea4bc952298c005662d12c5530ac29f136e2c1 100644 (file)
@@ -189,10 +189,46 @@ BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already
 
 END_TEST
 
+BEGIN_TEST(write3, "Replace an already existing tag")
+       git_repository *repo;
+       git_oid target_id, tag_id, old_tag_id;
+       const git_signature *tagger;
+       git_reference *ref_tag;
+
+       must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
+
+       git_oid_mkstr(&target_id, tagged_commit);
+
+       must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/very-simple"));
+       git_oid_cpy(&old_tag_id, git_reference_oid(ref_tag));
+
+       /* create signature */
+       tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
+       must_be_true(tagger != NULL);
+
+       must_pass(git_tag_create_f(
+               &tag_id, /* out id */
+               repo,
+               "very-simple",
+               &target_id,
+               GIT_OBJ_COMMIT,
+               tagger,
+               TAGGER_MESSAGE));
+
+       git_signature_free((git_signature *)tagger);
+
+       must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/very-simple"));
+       must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
+       must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &old_tag_id) != 0);
+
+       close_temp_repo(repo);
+
+END_TEST
 
 BEGIN_SUITE(tag)
        ADD_TEST(read0);
        ADD_TEST(write0); 
        ADD_TEST(write1); 
        ADD_TEST(write2); 
+       ADD_TEST(write3); 
 END_SUITE