Skip to content

Commit 13710f1

Browse files
committed
Added timezone offset parsing and outputting.
1 parent 2cd6d68 commit 13710f1

9 files changed

Lines changed: 109 additions & 14 deletions

File tree

src/commit.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ int commit_parse_buffer(git_commit *commit, void *data, size_t len, unsigned int
159159
return error;
160160

161161
commit->commit_time = commit->committer->time;
162+
commit->commit_timezone_offset = commit->committer->timezone_offset;
162163

163164
/* parse commit message */
164165
while (buffer <= buffer_end && *buffer == '\n')
@@ -249,6 +250,19 @@ time_t git_commit_time(git_commit *commit)
249250
return commit->commit_time;
250251
}
251252

253+
int git_commit_timezone_offset(git_commit *commit)
254+
{
255+
assert(commit);
256+
257+
if (commit->commit_timezone_offset)
258+
return commit->commit_timezone_offset;
259+
260+
if (!commit->object.in_memory)
261+
git_commit__parse_full(commit);
262+
263+
return commit->commit_timezone_offset;
264+
}
265+
252266
unsigned int git_commit_parentcount(git_commit *commit)
253267
{
254268
assert(commit);
@@ -269,24 +283,24 @@ void git_commit_set_tree(git_commit *commit, git_tree *tree)
269283
commit->tree = tree;
270284
}
271285

272-
void git_commit_set_author(git_commit *commit, const char *name, const char *email, time_t time)
286+
void git_commit_set_author(git_commit *commit, const char *name, const char *email, time_t time, int offset)
273287
{
274288
assert(commit && name && email);
275289
commit->object.modified = 1;
276290
CHECK_FULL_PARSE();
277291

278292
git_person__free(commit->author);
279-
commit->author = git_person__new(name, email, time);
293+
commit->author = git_person__new(name, email, time, offset);
280294
}
281295

282-
void git_commit_set_committer(git_commit *commit, const char *name, const char *email, time_t time)
296+
void git_commit_set_committer(git_commit *commit, const char *name, const char *email, time_t time, int offset)
283297
{
284298
assert(commit && name && email);
285299
commit->object.modified = 1;
286300
CHECK_FULL_PARSE();
287301

288302
git_person__free(commit->committer);
289-
commit->committer = git_person__new(name, email, time);
303+
commit->committer = git_person__new(name, email, time, offset);
290304
commit->commit_time = time;
291305
}
292306

src/commit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ struct git_commit {
1212
git_object object;
1313

1414
time_t commit_time;
15+
int commit_timezone_offset;
16+
1517
git_vector parents;
1618

1719
git_tree *tree;

src/git2/commit.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ GIT_EXTERN(const char *) git_commit_message(git_commit *commit);
9292
*/
9393
GIT_EXTERN(time_t) git_commit_time(git_commit *commit);
9494

95+
/**
96+
* Get the commit timezone offset (i.e. committer's preferred timezone) of a commit.
97+
* @param commit a previously loaded commit.
98+
* @return positive or negative timezone offset, in minutes from UTC
99+
*/
100+
GIT_EXTERN(int) git_commit_timezone_offset(git_commit *commit);
101+
95102
/**
96103
* Get the committer of a commit.
97104
* @param commit a previously loaded commit.
@@ -150,17 +157,19 @@ GIT_EXTERN(void) git_commit_set_message(git_commit *commit, const char *message)
150157
* @param name name of the new committer
151158
* @param email email of the new committer
152159
* @param time time when the committer committed the commit
160+
* @param offset committer positive or negative timezone offset, in minutes from UTC
153161
*/
154-
GIT_EXTERN(void) git_commit_set_committer(git_commit *commit, const char *name, const char *email, time_t time);
162+
GIT_EXTERN(void) git_commit_set_committer(git_commit *commit, const char *name, const char *email, time_t time, int offset);
155163

156164
/**
157165
* Set the author of a commit
158166
* @param commit the commit object
159167
* @param name name of the new author
160168
* @param email email of the new author
161169
* @param time time when the author created the commit
170+
* @param offset author positive or negative timezone offset, in minutes from UTC
162171
*/
163-
GIT_EXTERN(void) git_commit_set_author(git_commit *commit, const char *name, const char *email, time_t time);
172+
GIT_EXTERN(void) git_commit_set_author(git_commit *commit, const char *name, const char *email, time_t time, int offset);
164173

165174
/**
166175
* Set the tree which is pointed to by a commit

src/git2/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ typedef struct git_person git_person;
143143
const char *git_person_name(git_person *person);
144144
const char *git_person_email(git_person *person);
145145
time_t git_person_time(git_person *person);
146+
int git_person_timezone_offset(git_person *person);
146147

147148
/** @} */
148149
GIT_END_DECL

src/git2/tag.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ GIT_EXTERN(void) git_tag_set_name(git_tag *tag, const char *name);
125125
* @param name the name of the new tagger
126126
* @param email the email of the new tagger
127127
* @param time the time when the tag was created
128+
* @param offset tagger positive or negative timezone offset, in minutes from UTC
128129
*/
129-
GIT_EXTERN(void) git_tag_set_tagger(git_tag *tag, const char *name, const char *email, time_t time);
130+
GIT_EXTERN(void) git_tag_set_tagger(git_tag *tag, const char *name, const char *email, time_t time, int offset);
130131

131132
/**
132133
* Set the message of a tag

src/person.c

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ void git_person__free(git_person *person)
3838
free(person);
3939
}
4040

41-
git_person *git_person__new(const char *name, const char *email, time_t time)
41+
git_person *git_person__new(const char *name, const char *email, time_t time, int offset)
4242
{
4343
git_person *p;
4444

@@ -48,6 +48,7 @@ git_person *git_person__new(const char *name, const char *email, time_t time)
4848
p->name = git__strdup(name);
4949
p->email = git__strdup(email);
5050
p->time = time;
51+
p->timezone_offset = offset;
5152

5253
if (p->name == NULL || p->email == NULL)
5354
goto cleanup;
@@ -74,6 +75,51 @@ time_t git_person_time(git_person *person)
7475
return person->time;
7576
}
7677

78+
int git_person_timezone_offset(git_person *person)
79+
{
80+
return person->timezone_offset;
81+
}
82+
83+
int git_person__parse_timezone_offset(const char *buffer, int *offset_out)
84+
{
85+
int offset, dec_offset;
86+
int mins, hours;
87+
88+
const char* offset_start;
89+
char* offset_end;
90+
91+
offset_start = buffer + 1;
92+
93+
if (offset_start[0] != '-' && offset_start[0] != '+')
94+
return GIT_EOBJCORRUPTED;
95+
96+
dec_offset = strtol(offset_start + 1, &offset_end, 10);
97+
98+
if (offset_end - offset_start != 5)
99+
return GIT_EOBJCORRUPTED;
100+
101+
hours = dec_offset / 100;
102+
mins = dec_offset % 100;
103+
104+
if (hours > 14) // see http://www.worldtimezone.com/faq.html
105+
return GIT_EOBJCORRUPTED;
106+
107+
if (mins > 59)
108+
return GIT_EOBJCORRUPTED;
109+
110+
offset = (hours * 60) + mins;
111+
112+
if (offset_start[0] == '-')
113+
{
114+
offset *= -1;
115+
}
116+
117+
*offset_out = offset;
118+
119+
return GIT_SUCCESS;
120+
}
121+
122+
77123
int git_person__parse(git_person *person, char **buffer_out,
78124
const char *buffer_end, const char *header)
79125
{
@@ -82,6 +128,7 @@ int git_person__parse(git_person *person, char **buffer_out,
82128
int name_length, email_length;
83129
char *buffer = *buffer_out;
84130
char *line_end, *name_end, *email_end;
131+
int offset = 0;
85132

86133
memset(person, 0x0, sizeof(git_person));
87134

@@ -128,13 +175,30 @@ int git_person__parse(git_person *person, char **buffer_out,
128175
if (person->time == 0)
129176
return GIT_EOBJCORRUPTED;
130177

178+
if (git_person__parse_timezone_offset(buffer, &offset) < GIT_SUCCESS)
179+
return GIT_EOBJCORRUPTED;
180+
181+
person->timezone_offset = offset;
182+
131183
*buffer_out = (line_end + 1);
132184
return GIT_SUCCESS;
133185
}
134186

135187
int git_person__write(git_odb_source *src, const char *header, const git_person *person)
136188
{
137-
return git__source_printf(src, "%s %s <%s> %u\n", header, person->name, person->email, person->time);
189+
char *sign;
190+
int offset, hours, mins;
191+
192+
offset = person->timezone_offset;
193+
sign = (person->timezone_offset < 0) ? "-" : "+";
194+
195+
if (offset < 0)
196+
offset = -offset;
197+
198+
hours = offset / 60;
199+
mins = offset % 60;
200+
201+
return git__source_printf(src, "%s %s <%s> %u %s%02d%02d\n", header, person->name, person->email, person->time, sign, hours, mins);
138202
}
139203

140204

src/person.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ struct git_person {
1010
char *name; /**< Full name */
1111
char *email; /**< Email address */
1212
time_t time; /**< Time when this person committed the change */
13+
int timezone_offset; /**< Time zone offset in minutes. Can be either positive or negative. */
1314
};
1415

1516
void git_person__free(git_person *person);
16-
git_person *git_person__new(const char *name, const char *email, time_t time);
17+
git_person *git_person__new(const char *name, const char *email, time_t time, int offset);
1718
int git_person__parse(git_person *person, char **buffer_out, const char *buffer_end, const char *header);
1819
int git_person__write(git_odb_source *src, const char *header, const git_person *person);
1920

src/tag.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,13 @@ const git_person *git_tag_tagger(git_tag *t)
9797
return t->tagger;
9898
}
9999

100-
void git_tag_set_tagger(git_tag *tag, const char *name, const char *email, time_t time)
100+
void git_tag_set_tagger(git_tag *tag, const char *name, const char *email, time_t time, int offset)
101101
{
102102
assert(tag && name && email);
103103
tag->object.modified = 1;
104104

105105
git_person__free(tag->tagger);
106-
tag->tagger = git_person__new(name, email, time);
106+
tag->tagger = git_person__new(name, email, time, offset);
107107
}
108108

109109
const char *git_tag_message(git_tag *t)

tests/t0403-write.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ BEGIN_TEST(writenew_test)
4242
git_commit_add_parent(commit, parent);
4343

4444
/* Set other attributes */
45-
git_commit_set_committer(commit, COMMITTER_NAME, COMMITTER_EMAIL, 123456789);
46-
git_commit_set_author(commit, COMMITTER_NAME, COMMITTER_EMAIL, 987654321);
45+
git_commit_set_committer(commit, COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60);
46+
git_commit_set_author(commit, COMMITTER_NAME, COMMITTER_EMAIL, 987654321, 90);
4747
git_commit_set_message(commit, COMMIT_MESSAGE);
4848

4949
/* Check attributes were set correctly */
@@ -52,13 +52,16 @@ BEGIN_TEST(writenew_test)
5252
must_be_true(strcmp(author->name, COMMITTER_NAME) == 0);
5353
must_be_true(strcmp(author->email, COMMITTER_EMAIL) == 0);
5454
must_be_true(author->time == 987654321);
55+
must_be_true(author->time_offset == 90);
5556

5657
committer = git_commit_committer(commit);
5758
must_be_true(committer != NULL);
5859
must_be_true(strcmp(committer->name, COMMITTER_NAME) == 0);
5960
must_be_true(strcmp(committer->email, COMMITTER_EMAIL) == 0);
6061
must_be_true(committer->time == 123456789);
62+
must_be_true(committer->time_offset == 60);
6163
must_be_true(git_commit_time(commit) == 123456789);
64+
must_be_true(git_commit_time_offset(commit) == 60);
6265

6366
must_be_true(strcmp(git_commit_message(commit), COMMIT_MESSAGE) == 0);
6467

0 commit comments

Comments
 (0)