Commit 5cccfa89 by Vicent Marti

Merge branch 'timezone-offset' of https://github.com/nulltoken/libgit2 into timezone

parents e0d9e12e b76d984e
......@@ -159,6 +159,7 @@ int commit_parse_buffer(git_commit *commit, void *data, size_t len, unsigned int
return error;
commit->commit_time = commit->committer->time;
commit->commit_timezone_offset = commit->committer->timezone_offset;
/* parse commit message */
while (buffer <= buffer_end && *buffer == '\n')
......@@ -249,6 +250,19 @@ time_t git_commit_time(git_commit *commit)
return commit->commit_time;
}
int git_commit_timezone_offset(git_commit *commit)
{
assert(commit);
if (commit->commit_timezone_offset)
return commit->commit_timezone_offset;
if (!commit->object.in_memory)
git_commit__parse_full(commit);
return commit->commit_timezone_offset;
}
unsigned int git_commit_parentcount(git_commit *commit)
{
assert(commit);
......@@ -269,24 +283,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 char *name, const char *email, time_t time, int offset)
{
assert(commit && name && email);
commit->object.modified = 1;
CHECK_FULL_PARSE();
git_person__free(commit->author);
commit->author = git_person__new(name, email, time);
commit->author = git_person__new(name, email, time, offset);
}
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 char *name, const char *email, time_t time, int offset)
{
assert(commit && name && email);
commit->object.modified = 1;
CHECK_FULL_PARSE();
git_person__free(commit->committer);
commit->committer = git_person__new(name, email, time);
commit->committer = git_person__new(name, email, time, offset);
commit->commit_time = time;
}
......
......@@ -12,6 +12,8 @@ struct git_commit {
git_object object;
time_t commit_time;
int commit_timezone_offset;
git_vector parents;
git_tree *tree;
......
......@@ -93,6 +93,13 @@ 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
......@@ -150,8 +157,9 @@ GIT_EXTERN(void) git_commit_set_message(git_commit *commit, const char *message)
* @param name name of the new committer
* @param email email of the new committer
* @param time time when the committer committed the commit
* @param offset committer positive or negative timezone offset, in minutes from UTC
*/
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 char *name, const char *email, time_t time, int offset);
/**
* Set the author of a commit
......@@ -159,8 +167,9 @@ GIT_EXTERN(void) git_commit_set_committer(git_commit *commit, const char *name,
* @param name name of the new author
* @param email email of the new author
* @param time time when the author created the commit
* @param offset author positive or negative timezone offset, in minutes from UTC
*/
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 char *name, const char *email, time_t time, int offset);
/**
* Set the tree which is pointed to by a commit
......
......@@ -143,6 +143,7 @@ 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);
int git_person_timezone_offset(git_person *person);
/** @} */
GIT_END_DECL
......
......@@ -125,8 +125,9 @@ GIT_EXTERN(void) git_tag_set_name(git_tag *tag, const char *name);
* @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 offset tagger positive or negative timezone offset, in minutes from UTC
*/
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 char *name, const char *email, time_t time, int offset);
/**
* Set the message of a tag
......
......@@ -38,7 +38,7 @@ void git_person__free(git_person *person)
free(person);
}
git_person *git_person__new(const char *name, const char *email, time_t time)
git_person *git_person__new(const char *name, const char *email, time_t time, int offset)
{
git_person *p;
......@@ -48,6 +48,7 @@ git_person *git_person__new(const char *name, const char *email, time_t time)
p->name = git__strdup(name);
p->email = git__strdup(email);
p->time = time;
p->timezone_offset = offset;
if (p->name == NULL || p->email == NULL)
goto cleanup;
......@@ -74,6 +75,57 @@ time_t git_person_time(git_person *person)
return person->time;
}
int git_person_timezone_offset(git_person *person)
{
return person->timezone_offset;
}
int git_person__parse_timezone_offset(const char *buffer, int *offset_out)
{
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,
const char *buffer_end, const char *header)
{
......@@ -82,6 +134,7 @@ 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));
......@@ -128,13 +181,30 @@ int git_person__parse(git_person *person, char **buffer_out,
if (person->time == 0)
return GIT_EOBJCORRUPTED;
if (git_person__parse_timezone_offset(buffer, &offset) < GIT_SUCCESS)
return GIT_EOBJCORRUPTED;
person->timezone_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)
{
return git__source_printf(src, "%s %s <%s> %u\n", header, person->name, person->email, person->time);
char *sign;
int offset, hours, mins;
offset = person->timezone_offset;
sign = (person->timezone_offset < 0) ? "-" : "+";
if (offset < 0)
offset = -offset;
hours = offset / 60;
mins = offset % 60;
return git__source_printf(src, "%s %s <%s> %u %s%02d%02d\n", header, person->name, person->email, person->time, sign, hours, mins);
}
......@@ -10,10 +10,11 @@ struct git_person {
char *name; /**< Full name */
char *email; /**< Email address */
time_t time; /**< Time when this person committed the change */
int timezone_offset; /**< Time zone offset in minutes. Can be either positive or negative. */
};
void git_person__free(git_person *person);
git_person *git_person__new(const char *name, const char *email, time_t time);
git_person *git_person__new(const char *name, const char *email, time_t time, int offset);
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);
......
......@@ -97,13 +97,13 @@ const git_person *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 char *name, const char *email, time_t time, int offset)
{
assert(tag && name && email);
tag->object.modified = 1;
git_person__free(tag->tagger);
tag->tagger = git_person__new(name, email, time);
tag->tagger = git_person__new(name, email, time, offset);
}
const char *git_tag_message(git_tag *t)
......
......@@ -131,7 +131,7 @@ END_TEST
BEGIN_TEST(parse_person_test)
#define TEST_PERSON_PASS(_string, _header, _name, _email, _time) { \
#define TEST_PERSON_PASS(_string, _header, _name, _email, _time, _offset) { \
char *ptr = _string; \
size_t len = strlen(_string);\
git_person person = {NULL, NULL, 0}; \
......@@ -139,6 +139,7 @@ BEGIN_TEST(parse_person_test)
must_be_true(strcmp(_name, person.name) == 0);\
must_be_true(strcmp(_email, person.email) == 0);\
must_be_true(_time == person.time);\
must_be_true(_offset == person.timezone_offset);\
free(person.name); free(person.email);\
}
......@@ -155,21 +156,24 @@ BEGIN_TEST(parse_person_test)
"author ",
"Vicent Marti",
"tanoku@gmail.com",
12345);
12345,
0);
TEST_PERSON_PASS(
"author Vicent Marti <> 12345 \n",
"author ",
"Vicent Marti",
"",
12345);
12345,
0);
TEST_PERSON_PASS(
"author Vicent Marti <tanoku@gmail.com> 231301 +2020\n",
"author Vicent Marti <tanoku@gmail.com> 231301 +1020\n",
"author ",
"Vicent Marti",
"tanoku@gmail.com",
231301);
231301,
620);
TEST_PERSON_PASS(
"author Vicent Marti with an outrageously long name \
......@@ -178,7 +182,8 @@ BEGIN_TEST(parse_person_test)
"Vicent Marti with an outrageously long name \
which will probably overflow the buffer",
"tanoku@gmail.com",
12345);
12345,
0);
TEST_PERSON_PASS(
"author Vicent Marti <tanokuwithaveryveryverylongemail\
......@@ -187,7 +192,40 @@ BEGIN_TEST(parse_person_test)
"Vicent Marti",
"tanokuwithaveryveryverylongemail\
whichwillprobablyvoverflowtheemailbuffer@gmail.com",
12345);
12345,
0);
TEST_PERSON_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 +0000 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
123456,
0);
TEST_PERSON_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 +0100 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
123456,
60);
TEST_PERSON_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 -0100 \n",
"committer ",
"Vicent Marti",
"tanoku@gmail.com",
123456,
-60);
TEST_PERSON_FAIL(
"committer Vicent Marti <tanoku@gmail.com> 123456 -1500 \n",
"committer ");
TEST_PERSON_FAIL(
"committer Vicent Marti <tanoku@gmail.com> 123456 +0163 \n",
"committer ");
TEST_PERSON_FAIL(
"author Vicent Marti <tanoku@gmail.com> 12345 \n",
......
......@@ -42,8 +42,8 @@ BEGIN_TEST(writenew_test)
git_commit_add_parent(commit, parent);
/* Set other attributes */
git_commit_set_committer(commit, COMMITTER_NAME, COMMITTER_EMAIL, 123456789);
git_commit_set_author(commit, COMMITTER_NAME, COMMITTER_EMAIL, 987654321);
git_commit_set_committer(commit, COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60);
git_commit_set_author(commit, COMMITTER_NAME, COMMITTER_EMAIL, 987654321, 90);
git_commit_set_message(commit, COMMIT_MESSAGE);
/* Check attributes were set correctly */
......@@ -52,13 +52,16 @@ BEGIN_TEST(writenew_test)
must_be_true(strcmp(author->name, COMMITTER_NAME) == 0);
must_be_true(strcmp(author->email, COMMITTER_EMAIL) == 0);
must_be_true(author->time == 987654321);
must_be_true(author->time_offset == 90);
committer = git_commit_committer(commit);
must_be_true(committer != NULL);
must_be_true(strcmp(committer->name, COMMITTER_NAME) == 0);
must_be_true(strcmp(committer->email, COMMITTER_EMAIL) == 0);
must_be_true(committer->time == 123456789);
must_be_true(committer->time_offset == 60);
must_be_true(git_commit_time(commit) == 123456789);
must_be_true(git_commit_time_offset(commit) == 60);
must_be_true(strcmp(git_commit_message(commit), COMMIT_MESSAGE) == 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment