commit 788c352e1f3b00dfa5628e7ccfcfb056433c1948 from: Stefan Sperling date: Sat Jun 16 17:18:32 2018 UTC store commit timestamps as 'struct tm' in UTC commit - 5489743fa2b652dc080c3ecb621f80a5de568ce5 commit + 788c352e1f3b00dfa5628e7ccfcfb056433c1948 blob - a8dad302445587afca3921aacfe506fb6b487b18 blob + a80083bfb47f68f00c32b5b01618c6fbc9aa66a7 --- got/got.c +++ got/got.c @@ -323,23 +323,29 @@ print_commit(struct got_commit_object *commit, struct const struct got_error *err = NULL; char *id_str, *datestr, *logmsg, *line; char datebuf[26]; + time_t author_time, committer_time; err = got_object_id_str(&id_str, id); if (err) return err; + + author_time = mktime(&commit->tm_author); + committer_time = mktime(&commit->tm_committer); +#if 0 + /* This would express the date in committer's timezone. */ + author_time += commit->tm_author.tm_gmtoff; + committer_time += commit->tm_committer.tm_gmtoff; +#endif printf("-----------------------------------------------\n"); printf("commit %s\n", id_str); free(id_str); - datestr = get_datestr(&commit->author_time, datebuf); - printf("author: %s %s %s\n", commit->author, datestr, - commit->author_tzoff); + datestr = get_datestr(&author_time, datebuf); + printf("author: %s %s UTC\n", commit->author, datestr); if (strcmp(commit->author, commit->committer) != 0 || - commit->author_time != commit->committer_time || - strcmp(commit->author_tzoff, commit->committer_tzoff) != 0) { - datestr = get_datestr(&commit->committer_time, datebuf); - printf("committer: %s %s %s\n", commit->committer, - datestr, commit->committer_tzoff); + author_time != committer_time) { + datestr = get_datestr(&committer_time, datebuf); + printf("committer: %s %s UTC\n", commit->committer, datestr); } if (commit->nparents > 1) { struct got_object_qid *qid; blob - 1f6e4e055123872ec7e6b34a908765fe2bb1abdf blob + ec5c5b134da4aac3b2260284f17374a481a813ca --- include/got_object.h +++ include/got_object.h @@ -42,11 +42,9 @@ struct got_commit_object { unsigned int nparents; struct got_object_id_queue parent_ids; char *author; - time_t author_time; /* local time */ - char *author_tzoff; /* timezone offset description */ + struct tm tm_author; /* UTC */ char *committer; - time_t committer_time; /* local time */ - char *committer_tzoff; /* timezone offset description */ + struct tm tm_committer; /* UTC */ char *logmsg; }; blob - 9e8852e024353a395aff616e5276a04585dd2240 blob + 958b66ec82b4dd7e18be4a27f9d081e78e7b6484 --- lib/commit_graph.c +++ lib/commit_graph.c @@ -281,7 +281,9 @@ add_node(struct got_commit_graph_node **new_node, return err; node->nparents++; } - node->commit_timestamp = commit->committer_time; /* XXX not UTC! */ + node->commit_timestamp = mktime(&commit->tm_committer); + if (node->commit_timestamp == -1) + return got_error_from_errno(); err = got_object_idset_add((void **)(&existing_node), graph->node_ids, &node->id, node); blob - af295fc40438bb0ead909df0299dc917f29ea676 blob + 5d81bff851248d53b410b6439315d28e2f467c7f --- lib/delta.c +++ lib/delta.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "got_error.h" #include "got_repository.h" blob - 0f2d7838f8a00ec112a1ba2bf0d7b3340e6c8808 blob + 67a687b619f5daf43ec02cb885bec570058db386 --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -99,17 +99,14 @@ struct got_imsg_object { struct got_imsg_commit_object { uint8_t tree_id[SHA1_DIGEST_LENGTH]; size_t author_len; - time_t author_time; - size_t author_tzoff_len; + struct tm tm_author; size_t committer_len; - time_t committer_time; - size_t committer_tzoff_len; + struct tm tm_committer; size_t logmsg_len; int nparents; /* - * Followed by author_len + author_tzoff_len + committer_len + - * committer_tzoff_len + logmsg_len data bytes + * Followed by author_len + committer_len + logmsg_len data bytes */ /* Followed by 'nparents' SHA1_DIGEST_LENGTH length strings */ blob - 498d4c5d14364cf60575dcef5d969848dbb895a8 blob + 1765ec7c9ff3743ac32416d1a8baa920602a89c6 --- lib/object.c +++ lib/object.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "got_error.h" #include "got_object.h" @@ -493,20 +494,52 @@ got_object_commit_add_parent(struct got_commit_object } static const struct got_error * -parse_commit_time(time_t *time, char **tzoff, char *committer) +parse_gmtoff(time_t *gmtoff, const char *tzstr) { - const char *errstr; - char *space; + int sign = 1; + const char *p = tzstr; + time_t h, m; - *time = 0; + *gmtoff = 0; - /* Parse and then strip trailing timezone indicator. */ + if (*p == '-') + sign = -1; + else if (*p != '+') + return got_error(GOT_ERR_BAD_OBJ_DATA); + p++; + if (!isdigit(*p) && !isdigit(*(p + 1))) + return got_error(GOT_ERR_BAD_OBJ_DATA); + h = (((*p - '0') * 10) + (*(p + 1) - '0')); + + p += 2; + if (!isdigit(*p) && !isdigit(*(p + 1))) + return got_error(GOT_ERR_BAD_OBJ_DATA); + m = ((*p - '0') * 10) + (*(p + 1) - '0'); + + *gmtoff = (h * 60 * 60 + m * 60) * sign; + return NULL; +} + +static const struct got_error * +parse_commit_time(struct tm *tm, char *committer) +{ + const struct got_error *err = NULL; + const char *errstr; + char *space, *tzstr; + time_t gmtoff; + time_t time; + + /* Parse and strip off trailing timezone indicator string. */ space = strrchr(committer, ' '); if (space == NULL) return got_error(GOT_ERR_BAD_OBJ_DATA); - *tzoff = strdup(space + 1); - if (*tzoff == NULL) + tzstr = strdup(space + 1); + if (tzstr == NULL) return got_error_from_errno(); + err = parse_gmtoff(&gmtoff, tzstr); + free(tzstr); + if (err) + return err; *space = '\0'; /* Timestamp is separated from committer name + email by space. */ @@ -514,12 +547,21 @@ parse_commit_time(time_t *time, char **tzoff, char *co if (space == NULL) return got_error(GOT_ERR_BAD_OBJ_DATA); - *time = strtonum(space + 1, 0, INT64_MAX, &errstr); + /* Timestamp parsed here is expressed in comitter's local time. */ + time = strtonum(space + 1, 0, INT64_MAX, &errstr); if (errstr) return got_error(GOT_ERR_BAD_OBJ_DATA); + /* Express the time stamp in UTC. */ + memset(tm, 0, sizeof(*tm)); + time -= gmtoff; + if (localtime_r(&time, tm) == NULL) + return got_error_from_errno(); + tm->tm_gmtoff = gmtoff; + /* Strip off parsed time information, leaving just author and email. */ *space = '\0'; + return NULL; } @@ -588,8 +630,7 @@ parse_commit_object(struct got_commit_object **commit, } *p = '\0'; slen = strlen(s); - err = parse_commit_time(&(*commit)->author_time, - &(*commit)->author_tzoff, s); + err = parse_commit_time(&(*commit)->tm_author, s); if (err) goto done; (*commit)->author = strdup(s); @@ -619,8 +660,7 @@ parse_commit_object(struct got_commit_object **commit, } *p = '\0'; slen = strlen(s); - err = parse_commit_time(&(*commit)->committer_time, - &(*commit)->committer_tzoff, s); + err = parse_commit_time(&(*commit)->tm_committer, s); if (err) goto done; (*commit)->committer = strdup(s); @@ -949,9 +989,7 @@ got_object_commit_close(struct got_commit_object *comm free(commit->tree_id); free(commit->author); - free(commit->author_tzoff); free(commit->committer); - free(commit->committer_tzoff); free(commit->logmsg); free(commit); } blob - e7e8b1b918ce38fbbb00abcd2583937dcfabf32b blob + ae64f9afe555ae449ffadfb4d39015675ba0b35b --- lib/object_idset.c +++ lib/object_idset.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "got_object.h" #include "got_error.h" blob - 1c18f16672018cc1aea650967e5b3d848968f948 blob + 2fc13c0bc4f4adfde459767488c025425b5a05fe --- lib/privsep.c +++ lib/privsep.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "got_object.h" #include "got_error.h" @@ -266,17 +267,16 @@ got_privsep_send_commit(struct imsgbuf *ibuf, struct g memcpy(icommit.tree_id, commit->tree_id->sha1, sizeof(icommit.tree_id)); icommit.author_len = strlen(commit->author); - icommit.author_time = commit->author_time; - icommit.author_tzoff_len = strlen(commit->author_tzoff); + memcpy(&icommit.tm_author, &commit->tm_author, + sizeof(icommit.tm_author)); icommit.committer_len = strlen(commit->committer); - icommit.committer_time = commit->committer_time; - icommit.committer_tzoff_len = strlen(commit->committer_tzoff); + memcpy(&icommit.tm_committer, &commit->tm_committer, + sizeof(icommit.tm_committer)); icommit.logmsg_len = strlen(commit->logmsg); icommit.nparents = commit->nparents; total = sizeof(icommit) + icommit.author_len + - icommit.author_tzoff_len + icommit.committer_len + - icommit.committer_tzoff_len + icommit.logmsg_len + + icommit.committer_len + icommit.logmsg_len + icommit.nparents * SHA1_DIGEST_LENGTH; /* XXX TODO support very large log messages properly */ if (total > MAX_IMSGSIZE) @@ -291,12 +291,8 @@ got_privsep_send_commit(struct imsgbuf *ibuf, struct g len += sizeof(icommit); memcpy(buf + len, commit->author, icommit.author_len); len += icommit.author_len; - memcpy(buf + len, commit->author_tzoff, icommit.author_tzoff_len); - len += icommit.author_tzoff_len; memcpy(buf + len, commit->committer, icommit.committer_len); len += icommit.committer_len; - memcpy(buf + len, commit->committer_tzoff, icommit.committer_tzoff_len); - len += icommit.committer_tzoff_len; memcpy(buf + len, commit->logmsg, icommit.logmsg_len); len += icommit.logmsg_len; SIMPLEQ_FOREACH(qid, &commit->parent_ids, entry) { @@ -349,8 +345,7 @@ got_privsep_recv_commit(struct got_commit_object **com memcpy(&icommit, data, sizeof(icommit)); if (datalen != sizeof(icommit) + icommit.author_len + - icommit.author_tzoff_len + icommit.committer_len + - icommit.committer_tzoff_len + icommit.logmsg_len + + icommit.committer_len + icommit.logmsg_len + icommit.nparents * SHA1_DIGEST_LENGTH) { err = got_error(GOT_ERR_PRIVSEP_LEN); break; @@ -369,6 +364,10 @@ got_privsep_recv_commit(struct got_commit_object **com memcpy((*commit)->tree_id->sha1, icommit.tree_id, SHA1_DIGEST_LENGTH); + memcpy(&(*commit)->tm_author, &icommit.tm_author, + sizeof((*commit)->tm_author)); + memcpy(&(*commit)->tm_committer, &icommit.tm_committer, + sizeof((*commit)->tm_committer)); if (icommit.author_len == 0) { (*commit)->author = strdup(""); @@ -376,7 +375,6 @@ got_privsep_recv_commit(struct got_commit_object **com err = got_error_from_errno(); break; } - (*commit)->author_time = 0; } else { (*commit)->author = malloc(icommit.author_len + 1); if ((*commit)->author == NULL) { @@ -389,34 +387,12 @@ got_privsep_recv_commit(struct got_commit_object **com } len += icommit.author_len; - (*commit)->author_time = icommit.author_time; - if (icommit.author_tzoff_len == 0) { - (*commit)->author_tzoff = strdup(""); - if ((*commit)->author_tzoff == NULL) { - err = got_error_from_errno(); - break; - } - } else { - (*commit)->author_tzoff = - malloc(icommit.author_tzoff_len + 1); - if ((*commit)->author_tzoff == NULL) { - err = got_error_from_errno(); - break; - } - memcpy((*commit)->author_tzoff, data + len, - icommit.author_tzoff_len); - (*commit)->author_tzoff[icommit.author_tzoff_len] = - '\0'; - } - len += icommit.author_tzoff_len; - if (icommit.committer_len == 0) { (*commit)->committer = strdup(""); if ((*commit)->committer == NULL) { err = got_error_from_errno(); break; } - (*commit)->committer_time = 0; } else { (*commit)->committer = malloc(icommit.committer_len + 1); @@ -430,27 +406,6 @@ got_privsep_recv_commit(struct got_commit_object **com } len += icommit.committer_len; - (*commit)->committer_time = icommit.committer_time; - if (icommit.committer_tzoff_len == 0) { - (*commit)->committer_tzoff = strdup(""); - if ((*commit)->committer_tzoff == NULL) { - err = got_error_from_errno(); - break; - } - } else { - (*commit)->committer_tzoff = - malloc(icommit.committer_tzoff_len + 1); - if ((*commit)->committer_tzoff == NULL) { - err = got_error_from_errno(); - break; - } - memcpy((*commit)->committer_tzoff, data + len, - icommit.committer_tzoff_len); - (*commit)->committer_tzoff[icommit.committer_tzoff_len] - = '\0'; - } - len += icommit.committer_tzoff_len; - if (icommit.logmsg_len == 0) { (*commit)->logmsg = strdup(""); if ((*commit)->logmsg == NULL) { blob - 8336d486ab9d4e22fab6d158517d9809b5c84bbf blob + 635623e6ce2338f4495a8e2021c539a29cf39b14 --- lib/reference.c +++ lib/reference.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "got_error.h" #include "got_object.h" blob - 90a2cab8ef89165a7eec96bcb7f6dbf99119e75b blob + cd8dc7d1925b20202d7dd0d3f89e37bcc75806da --- lib/zbuf.c +++ lib/zbuf.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "got_error.h" #include "got_object.h" blob - 3b6200000b3462fc4fa34348605f411fe70b4896 blob + 35a2c48dd780532592d387e60fde43f989958b1f --- regress/idset/idset_test.c +++ regress/idset/idset_test.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "got_error.h" #include "got_object.h" blob - 96875062cb41b6f612b4a6972fde4cb283909042 blob + b4bebe2c83c1a2648a3c9a817ed26bcd7327542e --- tog/tog.c +++ tog/tog.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "got_error.h" #include "got_object.h"