Commit Diff


commit - ece731b025b35fd112ea1faebfabb163b61aacbe
commit + 799728f7aeb4842a6458eccfc51df84e5cbc40d0
blob - f4a93f9f22c2a2ae93a2bf822794bade8af45b6c
blob + e6b67696b6074e0499b029da5f51a883bf9c1e89
--- gotwebd/got_operations.c
+++ gotwebd/got_operations.c
@@ -116,59 +116,82 @@ got_get_repo_owner(char **owner, struct request *c)
 	return NULL;
 }
 
-const struct got_error *
-got_get_repo_age(time_t *repo_age, struct request *c, const char *refname)
+static const struct got_error *
+get_ref_commit_timestamp(time_t *timestamp,
+    struct got_reference *ref, struct got_repository *repo)
 {
-	const struct got_error *error = NULL;
-	struct transport *t = c->t;
-	struct got_repository *repo = t->repo;
+	const struct got_error *error;
+	struct got_object_id *id = NULL;
+	int obj_type;
 	struct got_commit_object *commit = NULL;
-	struct got_reflist_head refs;
-	struct got_reflist_entry *re;
-	time_t committer_time = 0, cmp_time = 0;
 
-	TAILQ_INIT(&refs);
+	/* We might have a cached timestamp available. */
+	*timestamp = got_ref_get_cached_committer_time(ref);
+	if (*timestamp != 0)
+		return NULL;
 
-	*repo_age = 0;
+	error = got_ref_resolve(&id, repo, ref);
+	if (error)
+		return error;
 
-	error = got_ref_list(&refs, repo, "refs/heads",
-	    got_ref_cmp_by_name, NULL);
+	error = got_object_get_type(&obj_type, repo, id);
+	if (error || obj_type != GOT_OBJ_TYPE_COMMIT)
+		goto done;
+
+	error = got_object_open_as_commit(&commit, repo, id);
 	if (error)
 		goto done;
 
-	/*
-	 * Find the youngest branch tip in the repository, or the age of
-	 * the a specific branch tip if a name was provided by the caller.
-	 */
-	TAILQ_FOREACH(re, &refs, entry) {
-		struct got_object_id *id = NULL;
+	*timestamp = got_object_commit_get_committer_time(commit);
+done:
+	free(id);
+	if (commit)
+		got_object_commit_close(commit);
 
-		if (refname && strcmp(got_ref_get_name(re->ref), refname) != 0)
-			continue;
+	return error;
+}
 
-		error = got_ref_resolve(&id, repo, re->ref);
-		if (error)
-			goto done;
-
-		error = got_object_open_as_commit(&commit, repo, id);
-		free(id);
+/*
+ * Find the youngest branch tip in the repository, or the age of
+ * a specific branch tip if a name was provided by the caller.
+ */
+const struct got_error *
+got_get_repo_age(time_t *repo_age, struct request *c, const char *refname)
+{
+	const struct got_error *error = NULL;
+	struct transport *t = c->t;
+	struct got_repository *repo = t->repo;
+
+	*repo_age = 0;
+
+	if (refname) {
+		struct got_reference *ref;
+
+		error = got_ref_open(&ref, repo, refname, 0);
 		if (error)
-			goto done;
+			return error;
 
-		committer_time =
-		    got_object_commit_get_committer_time(commit);
-		got_object_commit_close(commit);
-		if (cmp_time < committer_time)
-			cmp_time = committer_time;
+		error = get_ref_commit_timestamp(repo_age, ref, repo);
+		got_ref_close(ref);
+	} else {
+		struct got_reflist_head refs;
+		struct got_reflist_entry *re;
 
-		if (refname)
-			break;
+		TAILQ_INIT(&refs);
+
+		error = got_ref_list(&refs, repo, "refs/heads",
+		    got_ref_cmp_by_commit_timestamp_descending, repo);
+		if (error)
+			return error;
+
+		re = TAILQ_FIRST(&refs);
+		if (re) {
+			error = get_ref_commit_timestamp(repo_age,
+			    re->ref, repo);
+		}
+		got_ref_list_free(&refs);
 	}
 
-	if (cmp_time != 0)
-		*repo_age = cmp_time;
- done:
-	got_ref_list_free(&refs);
 	return error;
 }
 
blob - 0e987a302c6c21819424c0bbf8c957b06744abd8
blob + 55e4df44b40d37a2a722f120946119046d3edc41
--- include/got_reference.h
+++ include/got_reference.h
@@ -66,6 +66,17 @@ const char *got_ref_get_symref_target(struct got_refer
 time_t got_ref_get_mtime(struct got_reference *);
 
 /*
+ * Get the modification timestamp of the commit pointed at by the
+ * given reference. Will return zero if the commit timestamp is
+ * unknown or if the reference does not point at a commit.
+ *
+ * The cached timestamp will be known after got_ref_list() was called
+ * with either got_ref_cmp_by_commit_timestamp_descending() or
+ * with got_ref_cmp_tags().
+ */
+time_t got_ref_get_cached_committer_time(struct got_reference *);
+
+/*
  * Create a duplicate copy of a reference.
  * The caller must dispose of this copy with got_ref_close().
  */
blob - 3b728f8e2874054c0698accbbe24e51d69d93929
blob + b79065ff8ad9f1c2ab6d0c59c7cbb5c02c6b2467
--- lib/reference.c
+++ lib/reference.c
@@ -642,6 +642,12 @@ time_t
 got_ref_get_mtime(struct got_reference *ref)
 {
 	return ref->mtime;
+}
+
+time_t
+got_ref_get_cached_committer_time(struct got_reference *ref)
+{
+	return ref->committer_time;
 }
 
 const struct got_error *