Commit 6c281f94f63d6e0fe62836ab7af0690fcdab581a

Stefan Sperling 2018-06-11T02:14:44

show timezone offset in 'got log'

diff --git a/got/got.c b/got/got.c
index 11a84bd..d9d771d 100644
--- a/got/got.c
+++ b/got/got.c
@@ -306,12 +306,23 @@ print_patch(struct got_commit_object *commit, struct got_object_id *id,
 	return err;
 }
 
+char *
+get_datestr(time_t *time, char *datebuf)
+{
+	char *p, *s = ctime_r(time, datebuf);
+	p = strchr(s, '\n');
+	if (p)
+		*p = '\0';
+	return s;
+}
+
 static const struct got_error *
 print_commit(struct got_commit_object *commit, struct got_object_id *id,
     struct got_repository *repo, int show_patch, int verbose)
 {
 	const struct got_error *err = NULL;
-	char *id_str, *logmsg, *line;
+	char *id_str, *datestr, *logmsg, *line;
+	char datebuf[26];
 
 	err = got_object_id_str(&id_str, id);
 	if (err)
@@ -320,10 +331,14 @@ print_commit(struct got_commit_object *commit, struct got_object_id *id,
 	printf("-----------------------------------------------\n");
 	printf("commit %s\n", id_str);
 	free(id_str);
-	printf("author: %s  %s", commit->author, ctime(&commit->author_time));
-	if (strcmp(commit->author, commit->committer) != 0)
-		printf("committer: %s  %s\n", commit->committer,
-		    ctime(&commit->committer_time));
+	datestr = get_datestr(&commit->author_time, datebuf);
+	printf("author: %s  %s %s\n", commit->author, datestr,
+	    commit->author_tzoff);
+	if (strcmp(commit->author, commit->committer) != 0) {
+		datestr = get_datestr(&commit->committer_time, datebuf);
+		printf("committer: %s  %s %s\n", commit->committer,
+		    datestr, commit->committer_tzoff);
+	}
 	if (commit->nparents > 1) {
 		struct got_parent_id *pid;
 		int n = 1;
diff --git a/include/got_object.h b/include/got_object.h
index 1e65e1d..69cba31 100644
--- a/include/got_object.h
+++ b/include/got_object.h
@@ -40,9 +40,11 @@ struct got_commit_object {
 	unsigned int nparents;
 	SIMPLEQ_HEAD(, got_parent_id) parent_ids;
 	char *author;
-	time_t author_time;	/* UTC */
+	time_t author_time;	/* local time */
+	char *author_tzoff;	/* timezone offset description */
 	char *committer;
-	time_t committer_time;	/* UTC */
+	time_t committer_time;	/* local time */
+	char *committer_tzoff;	/* timezone offset description */
 	char *logmsg;
 };
 
diff --git a/lib/got_lib_privsep.h b/lib/got_lib_privsep.h
index f802293..0f2d783 100644
--- a/lib/got_lib_privsep.h
+++ b/lib/got_lib_privsep.h
@@ -100,12 +100,17 @@ 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;
 	size_t committer_len;
 	time_t committer_time;
+	size_t committer_tzoff_len;
 	size_t logmsg_len;
 	int nparents;
 
-	/* Followed by author_len + committer_len + logmsg_len data bytes */
+	/*
+	 * Followed by author_len + author_tzoff_len + committer_len +
+	 * committer_tzoff_len + logmsg_len data bytes
+	 */
 
 	/* Followed by 'nparents' SHA1_DIGEST_LENGTH length strings */
 
diff --git a/lib/object.c b/lib/object.c
index 71c594e..1874fc8 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -472,17 +472,20 @@ got_object_commit_add_parent(struct got_commit_object *commit,
 }
 
 static const struct got_error *
-parse_commit_time(time_t *time, char *committer)
+parse_commit_time(time_t *time, char **tzoff, char *committer)
 {
 	const char *errstr;
 	char *space;
 
 	*time = 0;
 
-	/* Strip off trailing timezone indicator. */
+	/* Parse and then strip trailing timezone indicator. */
 	space = strrchr(committer, ' ');
 	if (space == NULL)
 		return got_error(GOT_ERR_BAD_OBJ_DATA);
+	*tzoff = strdup(space + 1);
+	if (*tzoff == NULL)
+		return got_error_from_errno();
 	*space = '\0';
 
 	/* Timestamp is separated from committer name + email by space. */
@@ -564,7 +567,8 @@ parse_commit_object(struct got_commit_object **commit, char *buf, size_t len)
 		}
 		*p = '\0';
 		slen = strlen(s);
-		err = parse_commit_time(&(*commit)->author_time, s);
+		err = parse_commit_time(&(*commit)->author_time,
+		    &(*commit)->author_tzoff, s);
 		if (err)
 			goto done;
 		(*commit)->author = strdup(s);
@@ -594,7 +598,8 @@ parse_commit_object(struct got_commit_object **commit, char *buf, size_t len)
 		}
 		*p = '\0';
 		slen = strlen(s);
-		err = parse_commit_time(&(*commit)->committer_time, s);
+		err = parse_commit_time(&(*commit)->committer_time,
+		    &(*commit)->committer_tzoff, s);
 		if (err)
 			goto done;
 		(*commit)->committer = strdup(s);
diff --git a/lib/privsep.c b/lib/privsep.c
index c4ef656..847fbc1 100644
--- a/lib/privsep.c
+++ b/lib/privsep.c
@@ -267,13 +267,16 @@ got_privsep_send_commit(struct imsgbuf *ibuf, struct got_commit_object *commit)
 	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);
 	icommit.committer_len = strlen(commit->committer);
 	icommit.committer_time = commit->committer_time;
+	icommit.committer_tzoff_len = strlen(commit->committer_tzoff);
 	icommit.logmsg_len = strlen(commit->logmsg);
 	icommit.nparents = commit->nparents;
 
 	total = sizeof(icommit) + icommit.author_len +
-	    icommit.committer_len + icommit.logmsg_len +
+	    icommit.author_tzoff_len + icommit.committer_len +
+	    icommit.committer_tzoff_len + icommit.logmsg_len +
 	    icommit.nparents * SHA1_DIGEST_LENGTH;
 	/* XXX TODO support very large log messages properly */
 	if (total > MAX_IMSGSIZE)
@@ -288,8 +291,12 @@ got_privsep_send_commit(struct imsgbuf *ibuf, struct got_commit_object *commit)
 	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(pid, &commit->parent_ids, entry) {
@@ -342,7 +349,8 @@ got_privsep_recv_commit(struct got_commit_object **commit, struct imsgbuf *ibuf)
 
 		memcpy(&icommit, data, sizeof(icommit));
 		if (datalen != sizeof(icommit) + icommit.author_len +
-		    icommit.committer_len + icommit.logmsg_len +
+		    icommit.author_tzoff_len + icommit.committer_len +
+		    icommit.committer_tzoff_len + icommit.logmsg_len +
 		    icommit.nparents * SHA1_DIGEST_LENGTH) {
 			err = got_error(GOT_ERR_PRIVSEP_LEN);
 			break;
@@ -378,10 +386,30 @@ got_privsep_recv_commit(struct got_commit_object **commit, struct imsgbuf *ibuf)
 			memcpy((*commit)->author, data + len,
 			    icommit.author_len);
 			(*commit)->author[icommit.author_len] = '\0';
-			(*commit)->author_time = icommit.author_time;
 		}
 		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) {
@@ -399,10 +427,30 @@ got_privsep_recv_commit(struct got_commit_object **commit, struct imsgbuf *ibuf)
 			memcpy((*commit)->committer, data + len,
 			    icommit.committer_len);
 			(*commit)->committer[icommit.committer_len] = '\0';
-			(*commit)->committer_time = icommit.committer_time;
 		}
 		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) {