From ec25391dbb5ee6800b48362deadd73599701224f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 7 Oct 2010 00:20:08 +0300 Subject: [PATCH] Add write-back support for Tag files Tag files can now be created and modified in-memory (all the setter methods have been implemented), and written back to disk using the generic git_object_write() method. Signed-off-by: Vicent Marti --- src/commit.h | 3 +- src/git/tag.h | 28 +++++++++++++++++ src/repository.c | 3 ++ src/tag.c | 78 ++++++++++++++++++++++++++++++++++++++++++++---- src/tag.h | 1 + 5 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/commit.h b/src/commit.h index 8039930f7..39a7a52ff 100644 --- a/src/commit.h +++ b/src/commit.h @@ -32,12 +32,13 @@ void git_commit__free(git_commit *c); int git_commit__parse(git_commit *commit); int git_commit__parse_full(git_commit *commit); int git_commit__parse_buffer(git_commit *commit, void *data, size_t len, unsigned int parse_flags); -void git_commit__mark_uninteresting(git_commit *commit); int git_commit__writeback(git_commit *commit, git_odb_source *src); int git__parse_oid(git_oid *oid, char **buffer_out, const char *buffer_end, const char *header); int git__parse_person(git_person *person, char **buffer_out, const char *buffer_end, const char *header); +int git__write_oid(git_odb_source *src, const char *header, const git_oid *oid); +int git__write_person(git_odb_source *src, const char *header, const git_person *person); #endif diff --git a/src/git/tag.h b/src/git/tag.h index 33e3d6f26..aa232128b 100644 --- a/src/git/tag.h +++ b/src/git/tag.h @@ -83,6 +83,34 @@ GIT_EXTERN(const git_person *) git_tag_tagger(git_tag *t); */ GIT_EXTERN(const char *) git_tag_message(git_tag *t); +/** + * Set the target of a tag (i.e. the object that the tag points to) + * @param tag The tag to modify + * @param target the new tagged target + */ +GIT_EXTERN(void) git_tag_set_target(git_tag *tag, git_object *target); + +/** + * Set the name of a tag + * @param tag The tag to modify + * @param name the new name for the tag + */ +GIT_EXTERN(void) git_tag_set_name(git_tag *tag, const char *name); + +/** + * Set the tagger of a tag + * @param tag The tag to modify + * @param tagger the new tagger for the tag + */ +GIT_EXTERN(void) git_tag_set_tagger(git_tag *tag, const git_person *tagger); + +/** + * Set the message of a tag + * @param tag The tag to modify + * @param message the new tagger for the tag + */ +GIT_EXTERN(void) git_tag_set_message(git_tag *tag, const char *message); + /** @} */ GIT_END_DECL #endif diff --git a/src/repository.c b/src/repository.c index 22f2bba40..19f1c4e53 100644 --- a/src/repository.c +++ b/src/repository.c @@ -274,6 +274,9 @@ int git_object_write(git_object *object) break; case GIT_OBJ_TAG: + error = git_tag__writeback((git_tag *)object, source); + break; + default: error = GIT_ERROR; break; diff --git a/src/tag.c b/src/tag.c index 734556ba7..4a79fbd49 100644 --- a/src/tag.c +++ b/src/tag.c @@ -53,26 +53,79 @@ const git_object *git_tag_target(git_tag *t) return t->target; } +void git_tag_set_target(git_tag *tag, git_object *target) +{ + assert(tag && target); + + tag->object.modified = 1; + tag->target = target; + tag->type = git_object_type(target); +} + git_otype git_tag_type(git_tag *t) { return t->type; } +void git_tag_set_type(git_tag *tag, git_otype type) +{ + assert(tag); + + tag->object.modified = 1; + tag->type = type; +} + const char *git_tag_name(git_tag *t) { return t->tag_name; } +void git_tag_set_name(git_tag *tag, const char *name) +{ + assert(tag && name); + + /* TODO: sanity check? no newlines in message */ + tag->object.modified = 1; + + if (tag->tag_name) + free(tag->tag_name); + + tag->tag_name = git__strdup(name); +} + const git_person *git_tag_tagger(git_tag *t) { return t->tagger; } +void git_tag_set_tagger(git_tag *tag, const git_person *tagger) +{ + assert(tag && tagger); + + tag->object.modified = 1; + if (tag->tagger == NULL) + tag->tagger = git__malloc(sizeof(git_person)); + + memcpy(tag->tagger, tagger, sizeof(git_person)); +} + const char *git_tag_message(git_tag *t) { return t->message; } +void git_tag_set_message(git_tag *tag, const char *message) +{ + assert(tag && message); + + tag->object.modified = 1; + + if (tag->message) + free(tag->message); + + tag->message = git__strdup(message); +} + static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end) { static const char *tag_types[] = { @@ -115,10 +168,8 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end) tag->target = git_repository_lookup(tag->object.repo, &target_oid, tag->type); - /* FIXME: is the tag file really corrupted if the tagged object - * cannot be found on the database? */ - /* if (tag->target == NULL) - return GIT_EOBJCORRUPTED; */ + if (tag->target == NULL) + return GIT_EOBJCORRUPTED; if (buffer + 4 >= buffer_end) return GIT_EOBJCORRUPTED; @@ -150,7 +201,7 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end) if (git__parse_person(tag->tagger, &buffer, buffer_end, "tagger ") != 0) return GIT_EOBJCORRUPTED; - text_len = buffer_end - buffer; + text_len = buffer_end - ++buffer; if (tag->message != NULL) free(tag->message); @@ -162,6 +213,23 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end) return 0; } +int git_tag__writeback(git_tag *tag, git_odb_source *src) +{ + if (tag->target == NULL || tag->tag_name == NULL || tag->tagger == NULL) + return GIT_ERROR; + + git__write_oid(src, "object", git_object_id(tag->target)); + git__source_printf(src, "type %s\n", git_obj_type_to_string(tag->type)); + git__source_printf(src, "tag %s\n", tag->tag_name); + git__write_person(src, "tagger", tag->tagger); + + if (tag->message != NULL) + git__source_printf(src, "\n%s", tag->message); + + return GIT_SUCCESS; +} + + int git_tag__parse(git_tag *tag) { int error = 0; diff --git a/src/tag.h b/src/tag.h index 6d9cd8232..fbf520868 100644 --- a/src/tag.h +++ b/src/tag.h @@ -16,5 +16,6 @@ struct git_tag { void git_tag__free(git_tag *tag); int git_tag__parse(git_tag *tag); +int git_tag__writeback(git_tag *tag, git_odb_source *src); #endif