Commit 4626e416306921d48e15bacb31618804cf08c252

Stefan Sperling 2018-06-11T01:25:06

parse commit timestamps when opening commits

diff --git a/include/got_object.h b/include/got_object.h
index 6a104bb..1e65e1d 100644
--- a/include/got_object.h
+++ b/include/got_object.h
@@ -40,7 +40,9 @@ struct got_commit_object {
 	unsigned int nparents;
 	SIMPLEQ_HEAD(, got_parent_id) parent_ids;
 	char *author;
+	time_t author_time;	/* UTC */
 	char *committer;
+	time_t committer_time;	/* UTC */
 	char *logmsg;
 };
 
@@ -122,14 +124,6 @@ const struct got_error *got_object_commit_open(struct got_commit_object **,
 /* Dispose of a commit object. */
 void got_object_commit_close(struct got_commit_object *);
 
-/* Get the commit's committer timestamp (in UTC). */
-const struct got_error *got_object_commit_get_committer_time(time_t *,
-    struct got_commit_object *);
-
-/* Get the commit's author timestamp (in UTC). */
-const struct got_error *got_object_commit_get_committer_time(time_t *,
-    struct got_commit_object *);
-
 /*
  * Attempt to open a tree object in a repository.
  * The provided object must be of type GOT_OBJ_TYPE_TREE.
diff --git a/lib/commit_graph.c b/lib/commit_graph.c
index 5d6edcf..2743d38 100644
--- a/lib/commit_graph.c
+++ b/lib/commit_graph.c
@@ -134,32 +134,21 @@ is_root_node(struct got_commit_graph_node *node)
 	return node->commit->nparents == 0;
 }
 
-static const struct got_error *
-compare_commits(int *cmp, struct got_commit_object *c1,
-    struct got_commit_object *c2)
+static int
+compare_commits(struct got_commit_object *c1, struct got_commit_object *c2)
 {
-	const struct got_error *err;
-	int64_t t1, t2;
-
-	err = got_object_commit_get_committer_time(&t1, c1);
-	if (err)
-		return err;
-	err = got_object_commit_get_committer_time(&t2, c2);
-
-	if (err)
-		return err;
+	time_t t1, t2;
 
+	t1 = c1->committer_time;
+	t2 = c2->committer_time;
 	if (t1 == t2)	
-		*cmp = 0;
+		return 0;
 	else if (t1 < t2)
-		*cmp = -1;
-	else
-		*cmp = 1;
-
-	return NULL;
+		return -1;
+	return 1;
 }
 
-static const struct got_error *
+static void
 add_iteration_candidate(struct got_commit_graph *graph,
     struct got_commit_graph_node *node)
 {
@@ -167,15 +156,11 @@ add_iteration_candidate(struct got_commit_graph *graph,
 	
 	if (TAILQ_EMPTY(&graph->iter_candidates)) {
 		TAILQ_INSERT_TAIL(&graph->iter_candidates, node, entry);
-		return NULL;
+		return;
 	}
 
 	TAILQ_FOREACH(n, &graph->iter_candidates, entry) {
-		const struct got_error *err;
-		int cmp;
-		err = compare_commits(&cmp, node->commit, n->commit);
-		if (err)
-			return err;
+		int cmp = compare_commits(node->commit, n->commit);
 		if (cmp < 0) {
 			next = TAILQ_NEXT(n, entry);
 			if (next == NULL) {
@@ -183,9 +168,7 @@ add_iteration_candidate(struct got_commit_graph *graph,
 				    node, entry);
 				break;
 			}
-			err = compare_commits(&cmp, node->commit, next->commit);
-			if (err)
-				return err;
+			cmp = compare_commits(node->commit, next->commit);
 			if (cmp >= 0) {
 				TAILQ_INSERT_BEFORE(next, node, entry);
 				break;
@@ -195,8 +178,6 @@ add_iteration_candidate(struct got_commit_graph *graph,
 			break;
 		}
 	}
-
-	return NULL;
 }
 
 static const struct got_error *
@@ -222,10 +203,7 @@ add_node(struct got_commit_graph_node **new_node,
 	if (err == NULL) {
 		struct got_parent_id *pid;
 
-		err = add_iteration_candidate(graph, node);
-		if (err)
-			return err;
-
+		add_iteration_candidate(graph, node);
 		err = got_object_idset_remove(graph->open_branches, commit_id);
 		if (err && err->code != GOT_ERR_NO_OBJ)
 			return err;
@@ -476,12 +454,8 @@ got_commit_graph_iter_start(struct got_commit_graph *graph,
 	/* Put all known parents of this commit on the candidate list. */
 	SIMPLEQ_FOREACH(pid, &start_node->commit->parent_ids, entry) {
 		node = got_object_idset_get(graph->node_ids, pid->id);
-		if (node) {
-			const struct got_error *err;
-			err = add_iteration_candidate(graph, node);
-			if (err)
-				return err;
-		}
+		if (node)
+			add_iteration_candidate(graph, node);
 	}
 
 	return NULL;
diff --git a/lib/object.c b/lib/object.c
index 679abec..71c594e 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -472,6 +472,34 @@ got_object_commit_add_parent(struct got_commit_object *commit,
 }
 
 static const struct got_error *
+parse_commit_time(time_t *time, char *committer)
+{
+	const char *errstr;
+	char *space;
+
+	*time = 0;
+
+	/* Strip off trailing timezone indicator. */
+	space = strrchr(committer, ' ');
+	if (space == NULL)
+		return got_error(GOT_ERR_BAD_OBJ_DATA);
+	*space = '\0';
+
+	/* Timestamp is separated from committer name + email by space. */
+	space = strrchr(committer, ' ');
+	if (space == NULL)
+		return got_error(GOT_ERR_BAD_OBJ_DATA);
+
+	*time = strtonum(space + 1, 0, INT64_MAX, &errstr);
+	if (errstr)
+		return got_error(GOT_ERR_BAD_OBJ_DATA);
+
+	/* Strip off parsed time information, leaving just author and email. */
+	*space = '\0';
+	return NULL;
+}
+
+static const struct got_error *
 parse_commit_object(struct got_commit_object **commit, char *buf, size_t len)
 {
 	const struct got_error *err = NULL;
@@ -521,6 +549,7 @@ parse_commit_object(struct got_commit_object **commit, char *buf, size_t len)
 	tlen = strlen(GOT_COMMIT_TAG_AUTHOR);
 	if (strncmp(s, GOT_COMMIT_TAG_AUTHOR, tlen) == 0) {
 		char *p;
+		size_t slen;
 
 		remain -= tlen;
 		if (remain <= 0) {
@@ -534,18 +563,23 @@ parse_commit_object(struct got_commit_object **commit, char *buf, size_t len)
 			goto done;
 		}
 		*p = '\0';
+		slen = strlen(s);
+		err = parse_commit_time(&(*commit)->author_time, s);
+		if (err)
+			goto done;
 		(*commit)->author = strdup(s);
 		if ((*commit)->author == NULL) {
 			err = got_error_from_errno();
 			goto done;
 		}
-		s += strlen((*commit)->author) + 1;
-		remain -= strlen((*commit)->author) + 1;
+		s += slen + 1;
+		remain -= slen + 1;
 	}
 
 	tlen = strlen(GOT_COMMIT_TAG_COMMITTER);
 	if (strncmp(s, GOT_COMMIT_TAG_COMMITTER, tlen) == 0) {
 		char *p;
+		size_t slen;
 
 		remain -= tlen;
 		if (remain <= 0) {
@@ -559,13 +593,17 @@ parse_commit_object(struct got_commit_object **commit, char *buf, size_t len)
 			goto done;
 		}
 		*p = '\0';
+		slen = strlen(s);
+		err = parse_commit_time(&(*commit)->committer_time, s);
+		if (err)
+			goto done;
 		(*commit)->committer = strdup(s);
 		if ((*commit)->committer == NULL) {
 			err = got_error_from_errno();
 			goto done;
 		}
-		s += strlen((*commit)->committer) + 1;
-		remain -= strlen((*commit)->committer) + 1;
+		s += slen + 1;
+		remain -= slen + 1;
 	}
 
 	(*commit)->logmsg = strndup(s, remain);
@@ -581,57 +619,6 @@ done:
 	return err;
 }
 
-static const struct got_error *
-parse_commit_time(time_t *time, const char *author_str)
-{
-	const struct got_error *err = NULL;
-	const char *errstr;
-	char *committer, *space;
-
-	*time = 0;
-
-	committer = strdup(author_str);
-	if (committer == NULL)
-		return got_error_from_errno();
-
-	/* Strip off trailing timezone indicator. */
-	space = strrchr(committer, ' ');
-	if (space == NULL) {
-		err = got_error(GOT_ERR_BAD_OBJ_DATA);
-		goto done;
-	}
-	*space = '\0';
-
-	/* Timestamp is separated from committer name + email by space. */
-	space = strrchr(committer, ' ');
-	if (space == NULL) {
-		err = got_error(GOT_ERR_BAD_OBJ_DATA);
-		goto done;
-	}
-
-	*time = strtonum(space + 1, 0, INT64_MAX, &errstr);
-	if (errstr)
-		err = got_error(GOT_ERR_BAD_OBJ_DATA);
-
-done:
-	free(committer);
-	return err;
-}
-
-const struct got_error *
-got_object_commit_get_committer_time(time_t *time,
-    struct got_commit_object *commit)
-{
-	return parse_commit_time(time, commit->committer);
-}
-
-const struct got_error *
-got_object_commit_get_author_time(time_t *time,
-    struct got_commit_object *commit)
-{
-	return parse_commit_time(time, commit->committer);
-}
-
 static void
 tree_entry_close(struct got_tree_entry *te)
 {