diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/commit.c | 61 | ||||
-rw-r--r-- | src/commit.h | 5 | ||||
-rw-r--r-- | src/git2.h | 1 | ||||
-rw-r--r-- | src/git2/commit.h | 23 | ||||
-rw-r--r-- | src/git2/common.h | 9 | ||||
-rw-r--r-- | src/git2/signature.h | 70 | ||||
-rw-r--r-- | src/git2/tag.h | 8 | ||||
-rw-r--r-- | src/git2/types.h | 13 | ||||
-rw-r--r-- | src/person.h | 20 | ||||
-rw-r--r-- | src/revwalk.c | 4 | ||||
-rw-r--r-- | src/signature.c (renamed from src/person.c) | 121 | ||||
-rw-r--r-- | src/signature.h | 12 | ||||
-rw-r--r-- | src/tag.c | 23 | ||||
-rw-r--r-- | src/tag.h | 2 |
14 files changed, 248 insertions, 124 deletions
diff --git a/src/commit.c b/src/commit.c index d39fc540f..019cefecf 100644 --- a/src/commit.c +++ b/src/commit.c @@ -26,11 +26,12 @@ #include "git2/common.h" #include "git2/object.h" #include "git2/repository.h" +#include "git2/signature.h" #include "common.h" #include "commit.h" #include "revwalk.h" -#include "person.h" +#include "signature.h" #define COMMIT_BASIC_PARSE 0x0 #define COMMIT_FULL_PARSE 0x1 @@ -50,8 +51,8 @@ void git_commit__free(git_commit *commit) { clear_parents(commit); - git_person__free(commit->author); - git_person__free(commit->committer); + git_signature_free(commit->author); + git_signature_free(commit->committer); free(commit->message); free(commit->message_short); @@ -82,12 +83,12 @@ int git_commit__writeback(git_commit *commit, git_odb_source *src) if (commit->author == NULL) return GIT_EMISSINGOBJDATA; - git_person__write(src, "author", commit->author); + git_signature__write(src, "author", commit->author); if (commit->committer == NULL) return GIT_EMISSINGOBJDATA; - git_person__write(src, "committer", commit->committer); + git_signature__write(src, "committer", commit->committer); if (commit->message != NULL) git__source_printf(src, "\n%s", commit->message); @@ -137,10 +138,10 @@ int commit_parse_buffer(git_commit *commit, void *data, size_t len, unsigned int if (parse_flags & COMMIT_FULL_PARSE) { if (commit->author) - git_person__free(commit->author); + git_signature_free(commit->author); - commit->author = git__malloc(sizeof(git_person)); - if ((error = git_person__parse(commit->author, &buffer, buffer_end, "author ")) < GIT_SUCCESS) + commit->author = git__malloc(sizeof(git_signature)); + if ((error = git_signature__parse(commit->author, &buffer, buffer_end, "author ")) < GIT_SUCCESS) return error; } else { @@ -152,14 +153,12 @@ int commit_parse_buffer(git_commit *commit, void *data, size_t len, unsigned int /* Always parse the committer; we need the commit time */ if (commit->committer) - git_person__free(commit->committer); + git_signature_free(commit->committer); - commit->committer = git__malloc(sizeof(git_person)); - if ((error = git_person__parse(commit->committer, &buffer, buffer_end, "committer ")) < GIT_SUCCESS) + commit->committer = git__malloc(sizeof(git_signature)); + if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ")) < GIT_SUCCESS) return error; - commit->commit_time = commit->committer->time; - /* parse commit message */ while (buffer <= buffer_end && *buffer == '\n') buffer++; @@ -231,22 +230,21 @@ int git_commit__parse_full(git_commit *commit) git_commit__parse_full(commit); GIT_COMMIT_GETTER(git_tree *, tree) -GIT_COMMIT_GETTER(git_person *, author) -GIT_COMMIT_GETTER(git_person *, committer) +GIT_COMMIT_GETTER(git_signature *, author) +GIT_COMMIT_GETTER(git_signature *, committer) GIT_COMMIT_GETTER(char *, message) GIT_COMMIT_GETTER(char *, message_short) time_t git_commit_time(git_commit *commit) { - assert(commit); - - if (commit->commit_time) - return commit->commit_time; - - if (!commit->object.in_memory) - git_commit__parse_full(commit); + assert(commit && commit->committer); + return commit->committer->when.time; +} - return commit->commit_time; +int git_commit_time_offset(git_commit *commit) +{ + assert(commit && commit->committer); + return commit->committer->when.offset; } unsigned int git_commit_parentcount(git_commit *commit) @@ -269,25 +267,24 @@ void git_commit_set_tree(git_commit *commit, git_tree *tree) commit->tree = tree; } -void git_commit_set_author(git_commit *commit, const char *name, const char *email, time_t time) +void git_commit_set_author(git_commit *commit, const git_signature *author_sig) { - assert(commit && name && email); + assert(commit && author_sig); commit->object.modified = 1; CHECK_FULL_PARSE(); - git_person__free(commit->author); - commit->author = git_person__new(name, email, time); + git_signature_free(commit->author); + commit->author = git_signature_dup(author_sig); } -void git_commit_set_committer(git_commit *commit, const char *name, const char *email, time_t time) +void git_commit_set_committer(git_commit *commit, const git_signature *committer_sig) { - assert(commit && name && email); + assert(commit && committer_sig); commit->object.modified = 1; CHECK_FULL_PARSE(); - git_person__free(commit->committer); - commit->committer = git_person__new(name, email, time); - commit->commit_time = time; + git_signature_free(commit->committer); + commit->committer = git_signature_dup(committer_sig); } void git_commit_set_message(git_commit *commit, const char *message) diff --git a/src/commit.h b/src/commit.h index eca566ddf..b53ee9b23 100644 --- a/src/commit.h +++ b/src/commit.h @@ -11,12 +11,11 @@ struct git_commit { git_object object; - time_t commit_time; git_vector parents; git_tree *tree; - git_person *author; - git_person *committer; + git_signature *author; + git_signature *committer; char *message; char *message_short; diff --git a/src/git2.h b/src/git2.h index dbf5a9961..9eb9294df 100644 --- a/src/git2.h +++ b/src/git2.h @@ -33,6 +33,7 @@ #include "git2/types.h" #include "git2/oid.h" +#include "git2/signature.h" #include "git2/odb.h" #include "git2/repository.h" diff --git a/src/git2/commit.h b/src/git2/commit.h index 728679758..ccffec45f 100644 --- a/src/git2/commit.h +++ b/src/git2/commit.h @@ -93,18 +93,25 @@ GIT_EXTERN(const char *) git_commit_message(git_commit *commit); GIT_EXTERN(time_t) git_commit_time(git_commit *commit); /** + * Get the commit timezone offset (i.e. committer's preferred timezone) of a commit. + * @param commit a previously loaded commit. + * @return positive or negative timezone offset, in minutes from UTC + */ +GIT_EXTERN(int) git_commit_timezone_offset(git_commit *commit); + +/** * Get the committer of a commit. * @param commit a previously loaded commit. * @return the committer of a commit */ -GIT_EXTERN(const git_person *) git_commit_committer(git_commit *commit); +GIT_EXTERN(const git_signature *) git_commit_committer(git_commit *commit); /** * Get the author of a commit. * @param commit a previously loaded commit. * @return the author of a commit */ -GIT_EXTERN(const git_person *) git_commit_author(git_commit *commit); +GIT_EXTERN(const git_signature *) git_commit_author(git_commit *commit); /** * Get the tree pointed to by a commit. @@ -147,20 +154,16 @@ GIT_EXTERN(void) git_commit_set_message(git_commit *commit, const char *message) /** * Set the committer of a commit * @param commit the commit object - * @param name name of the new committer - * @param email email of the new committer - * @param time time when the committer committed the commit + * @param author_sig signature of the committer */ -GIT_EXTERN(void) git_commit_set_committer(git_commit *commit, const char *name, const char *email, time_t time); +GIT_EXTERN(void) git_commit_set_committer(git_commit *commit, const git_signature *committer_sig); /** * Set the author of a commit * @param commit the commit object - * @param name name of the new author - * @param email email of the new author - * @param time time when the author created the commit + * @param author_sig signature of the author */ -GIT_EXTERN(void) git_commit_set_author(git_commit *commit, const char *name, const char *email, time_t time); +GIT_EXTERN(void) git_commit_set_author(git_commit *commit, const git_signature *author_sig); /** * Set the tree which is pointed to by a commit diff --git a/src/git2/common.h b/src/git2/common.h index b819f0549..9d014c038 100644 --- a/src/git2/common.h +++ b/src/git2/common.h @@ -134,16 +134,7 @@ /** The index file is not backed up by an existing repository */ #define GIT_EBAREINDEX (GIT_ERROR -14) - GIT_BEGIN_DECL - -/** Parsed representation of a person */ -typedef struct git_person git_person; - -const char *git_person_name(git_person *person); -const char *git_person_email(git_person *person); -time_t git_person_time(git_person *person); - /** @} */ GIT_END_DECL #endif diff --git a/src/git2/signature.h b/src/git2/signature.h new file mode 100644 index 000000000..96275aa07 --- /dev/null +++ b/src/git2/signature.h @@ -0,0 +1,70 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef INCLUDE_git_signature_h__ +#define INCLUDE_git_signature_h__ + +#include "common.h" +#include "types.h" + +/** + * @file git2/signature.h + * @brief Git signature creation + * @defgroup git_signature Git signature creation + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Create a new action signature. The signature must be freed + * manually or using git_signature_free + * + * @name name of the person + * @email email of the person + * @time time when the action happened + * @offset timezone offset in minutes for the time + * @return the new sig, NULl on out of memory + */ +GIT_EXTERN(git_signature *) git_signature_new(const char *name, const char *email, time_t time, int offset); + +/** + * Create a copy of an existing signature. + * + * All internal strings are also duplicated. + * @sig signature to duplicated + * @return a copy of sig, NULL on out of memory + */ +GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig); + +/** + * Free an existing signature + * + * @sig signature to free + */ +GIT_EXTERN(void) git_signature_free(git_signature *sig); + +/** @} */ +GIT_END_DECL +#endif diff --git a/src/git2/tag.h b/src/git2/tag.h index 39b45ac74..8e29bc14a 100644 --- a/src/git2/tag.h +++ b/src/git2/tag.h @@ -96,7 +96,7 @@ GIT_EXTERN(const char *) git_tag_name(git_tag *t); * @param tag a previously loaded tag. * @return reference to the tag's author */ -GIT_EXTERN(const git_person *) git_tag_tagger(git_tag *t); +GIT_EXTERN(const git_signature *) git_tag_tagger(git_tag *t); /** * Get the message of a tag @@ -122,11 +122,9 @@ 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 name the name of the new tagger - * @param email the email of the new tagger - * @param time the time when the tag was created + * @param tagger_sig signature of the tagging action */ -GIT_EXTERN(void) git_tag_set_tagger(git_tag *tag, const char *name, const char *email, time_t time); +GIT_EXTERN(void) git_tag_set_tagger(git_tag *tag, const git_signature *tagger_sig); /** * Set the message of a tag diff --git a/src/git2/types.h b/src/git2/types.h index 22fecef3f..99de33218 100644 --- a/src/git2/types.h +++ b/src/git2/types.h @@ -82,6 +82,19 @@ typedef struct git_tree git_tree; /** Memory representation of an index file. */ typedef struct git_index git_index; +/** Time in a signature */ +typedef struct git_time { + time_t time; /** time in seconds from epoch */ + int offset; /** timezone offset, in minutes */ +} git_time; + +/** An action signature (e.g. for committers, taggers, etc) */ +typedef struct git_signature { + char *name; /** full name of the author */ + char *email; /** email of the author */ + git_time when; /** time when the action happened */ +} git_signature; + /** @} */ GIT_END_DECL diff --git a/src/person.h b/src/person.h deleted file mode 100644 index 7a9fcb75b..000000000 --- a/src/person.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef INCLUDE_person_h__ -#define INCLUDE_person_h__ - -#include "git2/common.h" -#include "repository.h" -#include <time.h> - -/** Parsed representation of a person */ -struct git_person { - char *name; /**< Full name */ - char *email; /**< Email address */ - time_t time; /**< Time when this person committed the change */ -}; - -void git_person__free(git_person *person); -git_person *git_person__new(const char *name, const char *email, time_t time); -int git_person__parse(git_person *person, char **buffer_out, const char *buffer_end, const char *header); -int git_person__write(git_odb_source *src, const char *header, const git_person *person); - -#endif diff --git a/src/revwalk.c b/src/revwalk.c index f2eaa710f..df8f47ab8 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -400,8 +400,8 @@ void git_revwalk_list_timesort(git_revwalk_list *list) e = q, q = q->next, q_size--; else if (q_size == 0 || q == NULL || - p->walk_commit->commit_object->commit_time >= - q->walk_commit->commit_object->commit_time) + p->walk_commit->commit_object->committer->when.time >= + q->walk_commit->commit_object->committer->when.time) e = p, p = p->next, p_size--; else diff --git a/src/person.c b/src/signature.c index e93e1b827..c5bfda805 100644 --- a/src/person.c +++ b/src/signature.c @@ -24,30 +24,37 @@ */ #include "common.h" -#include "person.h" +#include "signature.h" #include "repository.h" #include "git2/common.h" -void git_person__free(git_person *person) +void git_signature_free(git_signature *sig) { - if (person == NULL) + if (sig == NULL) return; - free(person->name); - free(person->email); - free(person); + free(sig->name); + free(sig->email); + free(sig); } -git_person *git_person__new(const char *name, const char *email, time_t time) +git_signature *git_signature_new(const char *name, const char *email, time_t time, int offset) { - git_person *p; + git_signature *p = NULL; - if ((p = git__malloc(sizeof(git_person))) == NULL) + if ((p = git__malloc(sizeof(git_signature))) == NULL) goto cleanup; p->name = git__strdup(name); + if (p->name == NULL) + goto cleanup; + p->email = git__strdup(email); - p->time = time; + if (p->email == NULL) + goto cleanup; + + p->when.time = time; + p->when.offset = offset; if (p->name == NULL || p->email == NULL) goto cleanup; @@ -55,26 +62,60 @@ git_person *git_person__new(const char *name, const char *email, time_t time) return p; cleanup: - git_person__free(p); + git_signature_free(p); return NULL; } -const char *git_person_name(git_person *person) +git_signature *git_signature_dup(const git_signature *sig) { - return person->name; + return git_signature_new(sig->name, sig->email, sig->when.time, sig->when.offset); } -const char *git_person_email(git_person *person) -{ - return person->email; -} -time_t git_person_time(git_person *person) +static int parse_timezone_offset(const char *buffer, int *offset_out) { - return person->time; + int offset, dec_offset; + int mins, hours; + + const char* offset_start; + char* offset_end; + + offset_start = buffer + 1; + + if (*offset_start == '\n') { + *offset_out = 0; + return GIT_SUCCESS; + } + + if (offset_start[0] != '-' && offset_start[0] != '+') + return GIT_EOBJCORRUPTED; + + dec_offset = strtol(offset_start + 1, &offset_end, 10); + + if (offset_end - offset_start != 5) + return GIT_EOBJCORRUPTED; + + hours = dec_offset / 100; + mins = dec_offset % 100; + + if (hours > 14) // see http://www.worldtimezone.com/faq.html + return GIT_EOBJCORRUPTED; + + if (mins > 59) + return GIT_EOBJCORRUPTED; + + offset = (hours * 60) + mins; + + if (offset_start[0] == '-') + offset *= -1; + + *offset_out = offset; + + return GIT_SUCCESS; } -int git_person__parse(git_person *person, char **buffer_out, + +int git_signature__parse(git_signature *sig, char **buffer_out, const char *buffer_end, const char *header) { const size_t header_len = strlen(header); @@ -82,8 +123,9 @@ int git_person__parse(git_person *person, char **buffer_out, int name_length, email_length; char *buffer = *buffer_out; char *line_end, *name_end, *email_end; + int offset = 0; - memset(person, 0x0, sizeof(git_person)); + memset(sig, 0x0, sizeof(git_signature)); line_end = memchr(buffer, '\n', buffer_end - buffer); if (!line_end) @@ -102,9 +144,9 @@ int git_person__parse(git_person *person, char **buffer_out, return GIT_EOBJCORRUPTED; name_length = name_end - buffer - 1; - person->name = git__malloc(name_length + 1); - memcpy(person->name, buffer, name_length); - person->name[name_length] = 0; + sig->name = git__malloc(name_length + 1); + memcpy(sig->name, buffer, name_length); + sig->name[name_length] = 0; buffer = name_end + 1; if (buffer >= line_end) @@ -115,26 +157,43 @@ int git_person__parse(git_person *person, char **buffer_out, return GIT_EOBJCORRUPTED; email_length = email_end - buffer; - person->email = git__malloc(email_length + 1); - memcpy(person->email, buffer, email_length); - person->email[email_length] = 0; + sig->email = git__malloc(email_length + 1); + memcpy(sig->email, buffer, email_length); + sig->email[email_length] = 0; buffer = email_end + 1; if (buffer >= line_end) return GIT_EOBJCORRUPTED; - person->time = strtol(buffer, &buffer, 10); + sig->when.time = strtol(buffer, &buffer, 10); + + if (sig->when.time == 0) + return GIT_EOBJCORRUPTED; - if (person->time == 0) + if (parse_timezone_offset(buffer, &offset) < GIT_SUCCESS) return GIT_EOBJCORRUPTED; + + sig->when.offset = offset; *buffer_out = (line_end + 1); return GIT_SUCCESS; } -int git_person__write(git_odb_source *src, const char *header, const git_person *person) +int git_signature__write(git_odb_source *src, const char *header, const git_signature *sig) { - return git__source_printf(src, "%s %s <%s> %u\n", header, person->name, person->email, person->time); + char sign; + int offset, hours, mins; + + offset = sig->when.offset; + sign = (sig->when.offset < 0) ? '-' : '+'; + + if (offset < 0) + offset = -offset; + + hours = offset / 60; + mins = offset % 60; + + return git__source_printf(src, "%s %s <%s> %u %c%02d%02d\n", header, sig->name, sig->email, sig->when.time, sign, hours, mins); } diff --git a/src/signature.h b/src/signature.h new file mode 100644 index 000000000..ee212c2dc --- /dev/null +++ b/src/signature.h @@ -0,0 +1,12 @@ +#ifndef INCLUDE_signature_h__ +#define INCLUDE_signature_h__ + +#include "git2/common.h" +#include "git2/signature.h" +#include "repository.h" +#include <time.h> + +int git_signature__parse(git_signature *sig, char **buffer_out, const char *buffer_end, const char *header); +int git_signature__write(git_odb_source *src, const char *header, const git_signature *sig); + +#endif @@ -26,14 +26,15 @@ #include "common.h" #include "commit.h" #include "tag.h" -#include "person.h" +#include "signature.h" #include "revwalk.h" #include "git2/object.h" #include "git2/repository.h" +#include "git2/signature.h" void git_tag__free(git_tag *tag) { - git_person__free(tag->tagger); + git_signature_free(tag->tagger); free(tag->message); free(tag->tag_name); free(tag); @@ -92,18 +93,18 @@ void git_tag_set_name(git_tag *tag, const char *name) tag->tag_name = git__strdup(name); } -const git_person *git_tag_tagger(git_tag *t) +const git_signature *git_tag_tagger(git_tag *t) { return t->tagger; } -void git_tag_set_tagger(git_tag *tag, const char *name, const char *email, time_t time) +void git_tag_set_tagger(git_tag *tag, const git_signature *tagger_sig) { - assert(tag && name && email); + assert(tag && tagger_sig); tag->object.modified = 1; - git_person__free(tag->tagger); - tag->tagger = git_person__new(name, email, time); + git_signature_free(tag->tagger); + tag->tagger = git_signature_dup(tagger_sig); } const char *git_tag_message(git_tag *t) @@ -190,11 +191,11 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end) buffer = search + 1; if (tag->tagger != NULL) - git_person__free(tag->tagger); + git_signature_free(tag->tagger); - tag->tagger = git__malloc(sizeof(git_person)); + tag->tagger = git__malloc(sizeof(git_signature)); - if ((error = git_person__parse(tag->tagger, &buffer, buffer_end, "tagger ")) != 0) + if ((error = git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ")) != 0) return error; text_len = buffer_end - ++buffer; @@ -217,7 +218,7 @@ int git_tag__writeback(git_tag *tag, git_odb_source *src) git__write_oid(src, "object", git_object_id(tag->target)); git__source_printf(src, "type %s\n", git_object_type2string(tag->type)); git__source_printf(src, "tag %s\n", tag->tag_name); - git_person__write(src, "tagger", tag->tagger); + git_signature__write(src, "tagger", tag->tagger); if (tag->message != NULL) git__source_printf(src, "\n%s", tag->message); @@ -10,7 +10,7 @@ struct git_tag { git_object *target; git_otype type; char *tag_name; - git_person *tagger; + git_signature *tagger; char *message; }; |