mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-09 18:22:16 +00:00
Merge branch 'timezone-offset' of https://github.com/nulltoken/libgit2 into timezone
This commit is contained in:
commit
5cccfa8999
22
src/commit.c
22
src/commit.c
@ -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;
|
||||
|
@ -92,6 +92,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.
|
||||
@ -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
|
||||
|
74
src/person.c
74
src/person.c
@ -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);\
|
||||
}
|
||||
|
||||
@ -151,25 +152,28 @@ BEGIN_TEST(parse_person_test)
|
||||
}
|
||||
|
||||
TEST_PERSON_PASS(
|
||||
"author Vicent Marti <tanoku@gmail.com> 12345 \n",
|
||||
"author ",
|
||||
"Vicent Marti",
|
||||
"tanoku@gmail.com",
|
||||
12345);
|
||||
"author Vicent Marti <tanoku@gmail.com> 12345 \n",
|
||||
"author ",
|
||||
"Vicent Marti",
|
||||
"tanoku@gmail.com",
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user