"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: tog is sluggish with FreeBSD src.git
To:
Christian Weisgerber <naddy@mips.inka.de>, gameoftrees@openbsd.org
Date:
Sat, 26 Dec 2020 16:33:53 +0100

Download raw body.

Thread
On Sat, Dec 26, 2020 at 02:24:58PM +0100, Stefan Sperling wrote:
> Another change we may want is optional skipping of got_ref_list() inside
> got_repo_match_object_id(). It needs refs to match user input with tag names. 

This patch implements the above idea (on top of the previous patch).
Now 'tog diff A B' will not read references twice on startup.
And got and gotweb also avoid loading references repeatedly.

However, this doesn't fix the slowness of "got log" on the freebsd repo.
That will require use of an object id map.

diff refs/heads/togref refs/heads/match_object_id_refs
blob - 5f87f8a6758feb7e94e8c6665cab42a06ff59f62
blob + 5ae8df4581b3c8b1b606407a8243cf633db3b443
--- got/got.c
+++ got/got.c
@@ -2743,8 +2743,15 @@ cmd_checkout(int argc, char *argv[])
 
 	if (commit_id_str) {
 		struct got_object_id *commit_id;
+		struct got_reflist_head refs;
+		SIMPLEQ_INIT(&refs);
+		error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
+		    NULL);
+		if (error)
+			goto done;
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    commit_id_str, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
+		got_ref_list_free(&refs);
 		if (error)
 			goto done;
 		error = check_linear_ancestry(commit_id,
@@ -3050,8 +3057,15 @@ cmd_update(int argc, char *argv[])
 		if (error != NULL)
 			goto done;
 	} else {
+		struct got_reflist_head refs;
+		SIMPLEQ_INIT(&refs);
+		error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
+		    NULL);
+		if (error)
+			goto done;
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    commit_id_str, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
+		got_ref_list_free(&refs);
 		free(commit_id_str);
 		commit_id_str = NULL;
 		if (error)
@@ -3815,6 +3829,10 @@ cmd_log(int argc, char *argv[])
 	if (error)
 		goto done;
 
+	error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
+	if (error)
+		goto done;
+
 	if (start_commit == NULL) {
 		struct got_reference *head_ref;
 		struct got_commit_object *commit = NULL;
@@ -3834,13 +3852,13 @@ cmd_log(int argc, char *argv[])
 		got_object_commit_close(commit);
 	} else {
 		error = got_repo_match_object_id(&start_id, NULL,
-		    start_commit, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    start_commit, GOT_OBJ_TYPE_COMMIT, &refs, repo);
 		if (error != NULL)
 			goto done;
 	}
 	if (end_commit != NULL) {
 		error = got_repo_match_object_id(&end_id, NULL,
-		    end_commit, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    end_commit, GOT_OBJ_TYPE_COMMIT, &refs, repo);
 		if (error != NULL)
 			goto done;
 	}
@@ -3870,10 +3888,6 @@ cmd_log(int argc, char *argv[])
 		path = in_repo_path;
 	}
 
-	error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
-	if (error)
-		goto done;
-
 	error = print_commits(start_id, end_id, repo, path ? path : "",
 	    show_changed_paths, show_patch, search_pattern, diff_context,
 	    limit, log_branches, reverse_display_order, &refs);
@@ -4114,7 +4128,10 @@ cmd_diff(int argc, char *argv[])
 	int force_text_diff = 0;
 	const char *errstr;
 	char *path = NULL;
+	struct got_reflist_head refs;
 
+	SIMPLEQ_INIT(&refs);
+
 #ifndef PROFILE
 	if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil",
 	    NULL) == -1)
@@ -4256,13 +4273,17 @@ cmd_diff(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
+	if (error)
+		return error;
+
 	error = got_repo_match_object_id(&id1, &label1, id_str1,
-	    GOT_OBJ_TYPE_ANY, 1, repo);
+	    GOT_OBJ_TYPE_ANY, &refs, repo);
 	if (error)
 		goto done;
 
 	error = got_repo_match_object_id(&id2, &label2, id_str2,
-	    GOT_OBJ_TYPE_ANY, 1, repo);
+	    GOT_OBJ_TYPE_ANY, &refs, repo);
 	if (error)
 		goto done;
 
@@ -4313,6 +4334,7 @@ done:
 		if (error == NULL)
 			error = repo_error;
 	}
+	got_ref_list_free(&refs);
 	return error;
 }
 
@@ -4559,8 +4581,15 @@ cmd_blame(int argc, char *argv[])
 		if (error != NULL)
 			goto done;
 	} else {
+		struct got_reflist_head refs;
+		SIMPLEQ_INIT(&refs);
+		error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
+		    NULL);
+		if (error)
+			goto done;
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    commit_id_str, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
+		got_ref_list_free(&refs);
 		if (error)
 			goto done;
 	}
@@ -4895,8 +4924,15 @@ cmd_tree(int argc, char *argv[])
 		if (error != NULL)
 			goto done;
 	} else {
+		struct got_reflist_head refs;
+		SIMPLEQ_INIT(&refs);
+		error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
+		    NULL);
+		if (error)
+			goto done;
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    commit_id_str, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
+		got_ref_list_free(&refs);
 		if (error)
 			goto done;
 	}
@@ -5609,12 +5645,19 @@ cmd_branch(int argc, char *argv[])
 	else if (delref)
 		error = delete_branch(repo, worktree, delref);
 	else {
+		struct got_reflist_head refs;
+		SIMPLEQ_INIT(&refs);
+		error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
+		    NULL);
+		if (error)
+			goto done;
 		if (commit_id_arg == NULL)
 			commit_id_arg = worktree ?
 			    got_worktree_get_head_ref_name(worktree) :
 			    GOT_REF_HEAD;
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    commit_id_arg, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    commit_id_arg, GOT_OBJ_TYPE_COMMIT, &refs, repo);
+		got_ref_list_free(&refs);
 		if (error)
 			goto done;
 		error = add_branch(repo, argv[0], commit_id);
@@ -5931,7 +5974,10 @@ add_tag(struct got_repository *repo, struct got_worktr
 	char *refname = NULL, *tagmsg = NULL, *tagger = NULL;
 	char *tagmsg_path = NULL, *tag_id_str = NULL;
 	int preserve_tagmsg = 0;
+	struct got_reflist_head refs;
 
+	SIMPLEQ_INIT(&refs);
+
 	/*
 	 * Don't let the user create a tag name with a leading '-'.
 	 * While technically a valid reference name, this case is usually
@@ -5944,8 +5990,12 @@ add_tag(struct got_repository *repo, struct got_worktr
 	if (err)
 		return err;
 
+	err = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
+	if (err)
+		goto done;
+
 	err = got_repo_match_object_id(&commit_id, &label, commit_arg,
-	    GOT_OBJ_TYPE_COMMIT, 1, repo);
+	    GOT_OBJ_TYPE_COMMIT, &refs, repo);
 	if (err)
 		goto done;
 
@@ -6027,6 +6077,7 @@ done:
 	free(tagmsg);
 	free(tagmsg_path);
 	free(tagger);
+	got_ref_list_free(&refs);
 	return err;
 }
 
@@ -9571,7 +9622,10 @@ cmd_cat(int argc, char *argv[])
 	const char *commit_id_str = NULL;
 	struct got_object_id *id = NULL, *commit_id = NULL;
 	int ch, obj_type, i, force_path = 0;
+	struct got_reflist_head refs;
 
+	SIMPLEQ_INIT(&refs);
+
 #ifndef PROFILE
 	if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil",
 	    NULL) == -1)
@@ -9636,10 +9690,14 @@ cmd_cat(int argc, char *argv[])
 	if (error)
 		goto done;
 
+	error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
+	if (error)
+		goto done;
+
 	if (commit_id_str == NULL)
 		commit_id_str = GOT_REF_HEAD;
 	error = got_repo_match_object_id(&commit_id, NULL,
-	    commit_id_str, GOT_OBJ_TYPE_COMMIT, 1, repo);
+	    commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
 	if (error)
 		goto done;
 
@@ -9651,7 +9709,8 @@ cmd_cat(int argc, char *argv[])
 				break;
 		} else {
 			error = got_repo_match_object_id(&id, &label, argv[i],
-			    GOT_OBJ_TYPE_ANY, 0, repo);
+			    GOT_OBJ_TYPE_ANY, NULL /* do not resolve tags */,
+			    repo);
 			if (error) {
 				if (error->code != GOT_ERR_BAD_OBJ_ID_STR &&
 				    error->code != GOT_ERR_NOT_REF)
@@ -9703,6 +9762,7 @@ done:
 		if (error == NULL)
 			error = repo_error;
 	}
+	got_ref_list_free(&refs);
 	return error;
 }
 
blob - fe98a9294517fd1c072b9a28b7f9d272389c72f7
blob + 53ce046986e836dd5050f4b5ede182d2d14a06e0
--- gotweb/gotweb.c
+++ gotweb/gotweb.c
@@ -175,9 +175,12 @@ static const struct got_error	*gw_get_repo_owner(char 
 static const struct got_error	*gw_get_time_str(char **, time_t, int);
 static const struct got_error	*gw_get_repo_age(char **, struct gw_trans *,
 				    char *, const char *, int);
-static const struct got_error	*gw_output_file_blame(struct gw_trans *);
-static const struct got_error	*gw_output_blob_buf(struct gw_trans *);
-static const struct got_error	*gw_output_repo_tree(struct gw_trans *);
+static const struct got_error	*gw_output_file_blame(struct gw_trans *,
+				    struct gw_header *);
+static const struct got_error	*gw_output_blob_buf(struct gw_trans *,
+				    struct gw_header *);
+static const struct got_error	*gw_output_repo_tree(struct gw_trans *,
+				    struct gw_header *);
 static const struct got_error	*gw_output_diff(struct gw_trans *,
 				    struct gw_header *);
 static const struct got_error	*gw_output_repo_tags(struct gw_trans *,
@@ -399,7 +402,7 @@ gw_blame(struct gw_trans *gw_trans)
 	    "blame", KATTR__MAX);
 	if (kerr != KCGI_OK)
 		goto done;
-	error = gw_output_file_blame(gw_trans);
+	error = gw_output_file_blame(gw_trans, header);
 	if (error)
 		goto done;
 	kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
@@ -443,7 +446,7 @@ gw_blob(struct gw_trans *gw_trans)
 	if (error)
 		goto done;
 
-	error = gw_output_blob_buf(gw_trans);
+	error = gw_output_blob_buf(gw_trans, header);
 done:
 
 	if (error) {
@@ -1653,7 +1656,7 @@ gw_tree(struct gw_trans *gw_trans)
 	    "tree", KATTR__MAX);
 	if (kerr != KCGI_OK)
 		goto done;
-	error = gw_output_repo_tree(gw_trans);
+	error = gw_output_repo_tree(gw_trans, header);
 	if (error)
 		goto done;
 
@@ -2854,13 +2857,15 @@ gw_output_diff(struct gw_trans *gw_trans, struct gw_he
 	if (header->parent_id != NULL &&
 	    strncmp(header->parent_id, "/dev/null", 9) != 0) {
 		error = got_repo_match_object_id(&id1, &label1,
-			header->parent_id, GOT_OBJ_TYPE_ANY, 1, gw_trans->repo);
+			header->parent_id, GOT_OBJ_TYPE_ANY,
+			&header->refs, gw_trans->repo);
 		if (error)
 			goto done;
 	}
 
 	error = got_repo_match_object_id(&id2, &label2,
-	    header->commit_id, GOT_OBJ_TYPE_ANY, 1, gw_trans->repo);
+	    header->commit_id, GOT_OBJ_TYPE_ANY, &header->refs,
+	    gw_trans->repo);
 	if (error)
 		goto done;
 
@@ -3951,7 +3956,7 @@ done:
 }
 
 static const struct got_error *
-gw_output_file_blame(struct gw_trans *gw_trans)
+gw_output_file_blame(struct gw_trans *gw_trans, struct gw_header *header)
 {
 	const struct got_error *error = NULL;
 	struct got_object_id *obj_id = NULL;
@@ -3975,7 +3980,7 @@ gw_output_file_blame(struct gw_trans *gw_trans)
 		goto done;
 
 	error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit_id,
-	    GOT_OBJ_TYPE_COMMIT, 1, gw_trans->repo);
+	    GOT_OBJ_TYPE_COMMIT, &header->refs, gw_trans->repo);
 	if (error)
 		goto done;
 
@@ -4056,7 +4061,7 @@ done:
 }
 
 static const struct got_error *
-gw_output_blob_buf(struct gw_trans *gw_trans)
+gw_output_blob_buf(struct gw_trans *gw_trans, struct gw_header *header)
 {
 	const struct got_error *error = NULL;
 	struct got_object_id *obj_id = NULL;
@@ -4081,7 +4086,7 @@ gw_output_blob_buf(struct gw_trans *gw_trans)
 		goto done;
 
 	error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit_id,
-	    GOT_OBJ_TYPE_COMMIT, 1, gw_trans->repo);
+	    GOT_OBJ_TYPE_COMMIT, &header->refs, gw_trans->repo);
 	if (error)
 		goto done;
 
@@ -4148,7 +4153,7 @@ done:
 }
 
 static const struct got_error *
-gw_output_repo_tree(struct gw_trans *gw_trans)
+gw_output_repo_tree(struct gw_trans *gw_trans, struct gw_header *header)
 {
 	const struct got_error *error = NULL;
 	struct got_object_id *tree_id = NULL, *commit_id = NULL;
@@ -4198,7 +4203,7 @@ gw_output_repo_tree(struct gw_trans *gw_trans)
 
 	} else {
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    gw_trans->commit_id, GOT_OBJ_TYPE_COMMIT, 1,
+		    gw_trans->commit_id, GOT_OBJ_TYPE_COMMIT, &header->refs,
 		    gw_trans->repo);
 		if (error)
 			goto done;
blob - 58d890d3d6f831f42b34c8497b53e4dbaafb6eb3
blob + 1b274cc91e744b2672ce8c785379d258cd79f4cb
--- include/got_repository.h
+++ include/got_repository.h
@@ -94,6 +94,7 @@ char *got_repo_get_path_gitconfig(struct got_repositor
 char *got_repo_get_path_gotconfig(struct got_repository *);
 
 struct got_reference;
+struct got_reflist_head;
 
 /*
  * Obtain a reference, by name, from a repository.
@@ -119,22 +120,25 @@ const struct got_error *got_repo_match_object_id_prefi
 
 /*
  * Given an object ID string or reference name, attempt to find a corresponding
- * commit object. Tags can optionally be ignored during matching.
+ * commit object.
  * The object type may be restricted to commit, tree, blob, or tag.
+ * Tags will only be matched if a list of references is provided.
  * GOT_OBJ_TYPE_ANY will match any type of object.
  * A human-readable label can optionally be returned, which the caller should
  * dispose of with free(3).
  * Return GOT_ERR_NO_OBJ if no matching commit can be found.
  */
 const struct got_error *got_repo_match_object_id(struct got_object_id **,
-    char **, const char *, int, int, struct got_repository *);
+    char **, const char *, int, struct got_reflist_head *,
+    struct got_repository *);
 
 /*
- * Attempt to find a tag object with a given name and target object type.
+ * Search the provided list of references for a tag with a given name
+ * and target object type.
  * Return GOT_ERR_NO_OBJ if no matching tag can be found.
  */
 const struct got_error *got_repo_object_match_tag(struct got_tag_object **,
-    const char *, int, struct got_repository *);
+    const char *, int, struct got_reflist_head *, struct got_repository *);
 
 /* A callback function which is invoked when a path is imported. */
 typedef const struct got_error *(*got_repo_import_cb)(void *, const char *);
blob - 7a2d2999eee396614f65ab978214ffc035a1f4c2
blob + bfbd39aabab2179cdbf0100c7d1b2534617f140e
--- lib/repository.c
+++ lib/repository.c
@@ -1467,7 +1467,7 @@ done:
 
 const struct got_error *
 got_repo_match_object_id(struct got_object_id **id, char **label,
-    const char *id_str, int obj_type, int resolve_tags,
+    const char *id_str, int obj_type, struct got_reflist_head *refs,
     struct got_repository *repo)
 {
 	const struct got_error *err;
@@ -1478,9 +1478,9 @@ got_repo_match_object_id(struct got_object_id **id, ch
 	if (label)
 		*label = NULL;
 
-	if (resolve_tags) {
+	if (refs) {
 		err = got_repo_object_match_tag(&tag, id_str, GOT_OBJ_TYPE_ANY,
-		    repo);
+		    refs, repo);
 		if (err == NULL) {
 			*id = got_object_id_dup(
 			    got_object_tag_get_object_id(tag));
@@ -1529,26 +1529,22 @@ done:
 
 const struct got_error *
 got_repo_object_match_tag(struct got_tag_object **tag, const char *name,
-    int obj_type, struct got_repository *repo)
+    int obj_type, struct got_reflist_head *refs, struct got_repository *repo)
 {
-	const struct got_error *err;
-	struct got_reflist_head refs;
+	const struct got_error *err = NULL;
 	struct got_reflist_entry *re;
 	struct got_object_id *tag_id;
 	int name_is_absolute = (strncmp(name, "refs/", 5) == 0);
 
-	SIMPLEQ_INIT(&refs);
 	*tag = NULL;
 
-	err = got_ref_list(&refs, repo, "refs/tags", got_ref_cmp_by_name, NULL);
-	if (err)
-		return err;
-
-	SIMPLEQ_FOREACH(re, &refs, entry) {
+	SIMPLEQ_FOREACH(re, refs, entry) {
 		const char *refname;
 		refname = got_ref_get_name(re->ref);
 		if (got_ref_is_symbolic(re->ref))
 			continue;
+		if (strncmp(refname, "refs/tags/", 10) != 0)
+			continue;
 		if (!name_is_absolute)
 			refname += strlen("refs/tags/");
 		if (strcmp(refname, name) != 0)
@@ -1567,7 +1563,6 @@ got_repo_object_match_tag(struct got_tag_object **tag,
 		*tag = NULL;
 	}
 
-	got_ref_list_free(&refs);
 	if (err == NULL && *tag == NULL)
 		err = got_error_path(name, GOT_ERR_NO_OBJ);
 	return err;
blob - ee2324cc37e9714754f8a581d0e546d0ef5f385c
blob + c02189d556c9524c29a6a39fe32265db45eaf932
--- tog/tog.c
+++ tog/tog.c
@@ -2537,7 +2537,7 @@ input_log_view(struct tog_view **new_view, struct tog_
 			struct got_object_id *start_id;
 			err = got_repo_match_object_id(&start_id, NULL,
 			    s->head_ref_name ? s->head_ref_name : GOT_REF_HEAD,
-			    GOT_OBJ_TYPE_COMMIT, 1, s->repo);
+			    GOT_OBJ_TYPE_COMMIT, &tog_refs, s->repo);
 			if (err)
 				return err;
 			free(s->start_id);
@@ -2763,7 +2763,7 @@ cmd_log(int argc, char *argv[])
 	if (start_commit == NULL) {
 		error = got_repo_match_object_id(&start_id, &label,
 		    worktree ? got_worktree_get_head_ref_name(worktree) :
-		    GOT_REF_HEAD, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    GOT_REF_HEAD, GOT_OBJ_TYPE_COMMIT, &tog_refs, repo);
 		if (error)
 			goto done;
 		head_ref_name = label;
@@ -2774,7 +2774,7 @@ cmd_log(int argc, char *argv[])
 		else if (error->code != GOT_ERR_NOT_REF)
 			goto done;
 		error = got_repo_match_object_id(&start_id, NULL,
-		    start_commit, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    start_commit, GOT_OBJ_TYPE_COMMIT, &tog_refs, repo);
 		if (error)
 			goto done;
 	}
@@ -3833,12 +3833,12 @@ cmd_diff(int argc, char *argv[])
 		goto done;
 
 	error = got_repo_match_object_id(&id1, &label1, id_str1,
-	    GOT_OBJ_TYPE_ANY, 1, repo);
+	    GOT_OBJ_TYPE_ANY, &tog_refs, repo);
 	if (error)
 		goto done;
 
 	error = got_repo_match_object_id(&id2, &label2, id_str2,
-	    GOT_OBJ_TYPE_ANY, 1, repo);
+	    GOT_OBJ_TYPE_ANY, &tog_refs, repo);
 	if (error)
 		goto done;
 
@@ -4740,7 +4740,7 @@ cmd_blame(int argc, char *argv[])
 		got_ref_close(head_ref);
 	} else {
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    commit_id_str, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    commit_id_str, GOT_OBJ_TYPE_COMMIT, &tog_refs, repo);
 	}
 	if (error != NULL)
 		goto done;
@@ -5548,7 +5548,7 @@ cmd_tree(int argc, char *argv[])
 	if (commit_id_arg == NULL) {
 		error = got_repo_match_object_id(&commit_id, &label,
 		    worktree ? got_worktree_get_head_ref_name(worktree) :
-		    GOT_REF_HEAD, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    GOT_REF_HEAD, GOT_OBJ_TYPE_COMMIT, &tog_refs, repo);
 		if (error)
 			goto done;
 		head_ref_name = label;
@@ -5559,7 +5559,7 @@ cmd_tree(int argc, char *argv[])
 		else if (error->code != GOT_ERR_NOT_REF)
 			goto done;
 		error = got_repo_match_object_id(&commit_id, NULL,
-		    commit_id_arg, GOT_OBJ_TYPE_COMMIT, 1, repo);
+		    commit_id_arg, GOT_OBJ_TYPE_COMMIT, &tog_refs, repo);
 		if (error)
 			goto done;
 	}
@@ -6353,7 +6353,10 @@ tog_log_with_path(int argc, char *argv[])
 	struct got_object_id *commit_id = NULL, *id = NULL;
 	char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL;
 	char *commit_id_str = NULL, **cmd_argv = NULL;
+	struct got_reflist_head refs;
 
+	SIMPLEQ_INIT(&refs);
+
 	cwd = getcwd(NULL, 0);
 	if (cwd == NULL)
 		return got_error_from_errno("getcwd");
@@ -6380,9 +6383,12 @@ tog_log_with_path(int argc, char *argv[])
 	if (error)
 		goto done;
 
+	error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
+	if (error)
+		goto done;
 	error = got_repo_match_object_id(&commit_id, NULL, worktree ?
 	    got_worktree_get_head_ref_name(worktree) : GOT_REF_HEAD,
-	    GOT_OBJ_TYPE_COMMIT, 1, repo);
+	    GOT_OBJ_TYPE_COMMIT, &refs, repo);
 	if (error)
 		goto done;
 
@@ -6429,6 +6435,7 @@ done:
 			free(cmd_argv[i]);
 		free(cmd_argv);
 	}
+	got_ref_list_free(&refs);
 	return error;
 }