From: Omar Polo Subject: Re: got_object_id_by_path() vs. commit object cache To: Stefan Sperling Cc: gameoftrees@openbsd.org Date: Thu, 07 Apr 2022 14:19:33 +0200 Stefan Sperling wrote: > On Tue, Apr 05, 2022 at 06:12:59PM +0200, Stefan Sperling wrote: > > Stop relying on the commit object cache for reasoable performance > > of got_object_id_by_path(). This function is called over and over > > on the same commit by commands like 'got tree -R'. > > > > Instead of internally opening and closing the same commit object over and > > over again, require callers to pass an open commit object in. Avoids an > > inherent dependency on the commit object cache for reasonable performance > > of this function. > > > > My end goal is to eventually get rid of the commit object cache altogether > > because this cache seems to be slowing down operations like 'gotadmin pack'. > > The cache is only useful when commits are accessed repeatedly and very often, > > which is rarely the case. > > Usually, operations open one commit as an anchor to start from, or they open > > commits in sequence and do not process a given commit more than once. > > In such cases the object cache management overhead provides no benefit and > > just slows things down. > > > > ok? > > New version which includes changes to gotweb.c I forgot in the previous diff. > The previous version broke the build in 'make web'. I don't know much about the commit object cache, but agree on the idea: commits are traversed in sequence and caching them when they won't be re-used is just a waste. The diff reads fine to me. > diff 720c84593b989629674c0c2d566b6fcb246578fd 6fd1a33c932d168a9aef98ca7760e8f63446bea1 > blob - f3608d970c5ae77fee89a4e9ca8fdb89b015c5f8 > blob + 7ac9d84ea1bc903f4fd7ab569799630bbaa48aaa > --- got/got.c > +++ got/got.c > @@ -3609,7 +3609,7 @@ print_patch(struct got_commit_object *commit, struct g > > if (path && path[0] != '\0') { > int obj_type; > - err = got_object_id_by_path(&obj_id2, repo, id, path); > + err = got_object_id_by_path(&obj_id2, repo, commit, path); > if (err) > goto done; > err = got_object_id_str(&id_str2, obj_id2); > @@ -3619,7 +3619,7 @@ print_patch(struct got_commit_object *commit, struct g > } > if (pcommit) { > err = got_object_id_by_path(&obj_id1, repo, > - qid->id, path); > + pcommit, path); > if (err) { > if (err->code != GOT_ERR_NO_TREE_ENTRY) { > free(obj_id2); > @@ -4984,6 +4984,7 @@ cmd_blame(int argc, char *argv[]) > char *link_target = NULL; > struct got_object_id *obj_id = NULL; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > struct got_blob_object *blob = NULL; > char *commit_id_str = NULL; > struct blame_cb_args bca; > @@ -5111,12 +5112,16 @@ cmd_blame(int argc, char *argv[]) > worktree = NULL; > } > > + error = got_object_open_as_commit(&commit, repo, commit_id); > + if (error) > + goto done; > + > error = got_object_resolve_symlinks(&link_target, in_repo_path, > - commit_id, repo); > + commit, repo); > if (error) > goto done; > > - error = got_object_id_by_path(&obj_id, repo, commit_id, > + error = got_object_id_by_path(&obj_id, repo, commit, > link_target ? link_target : in_repo_path); > if (error) > goto done; > @@ -5171,6 +5176,8 @@ done: > free(cwd); > free(commit_id); > free(obj_id); > + if (commit) > + got_object_commit_close(commit); > if (blob) > got_object_blob_close(blob); > if (worktree) > @@ -5246,7 +5253,7 @@ print_entry(struct got_tree_entry *te, const char *id, > } > > static const struct got_error * > -print_tree(const char *path, struct got_object_id *commit_id, > +print_tree(const char *path, struct got_commit_object *commit, > int show_ids, int recurse, const char *root_path, > struct got_repository *repo) > { > @@ -5255,7 +5262,7 @@ print_tree(const char *path, struct got_object_id *com > struct got_tree_object *tree = NULL; > int nentries, i; > > - err = got_object_id_by_path(&tree_id, repo, commit_id, path); > + err = got_object_id_by_path(&tree_id, repo, commit, path); > if (err) > goto done; > > @@ -5297,7 +5304,7 @@ print_tree(const char *path, struct got_object_id *com > err = got_error_from_errno("asprintf"); > goto done; > } > - err = print_tree(child_path, commit_id, show_ids, 1, > + err = print_tree(child_path, commit, show_ids, 1, > root_path, repo); > free(child_path); > if (err) > @@ -5320,6 +5327,7 @@ cmd_tree(int argc, char *argv[]) > const char *path, *refname = NULL; > char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > char *commit_id_str = NULL; > int show_ids = 0, recurse = 0; > int ch; > @@ -5459,13 +5467,19 @@ cmd_tree(int argc, char *argv[]) > worktree = NULL; > } > > - error = print_tree(in_repo_path, commit_id, show_ids, recurse, > + error = got_object_open_as_commit(&commit, repo, commit_id); > + if (error) > + goto done; > + > + error = print_tree(in_repo_path, commit, show_ids, recurse, > in_repo_path, repo); > done: > free(in_repo_path); > free(repo_path); > free(cwd); > free(commit_id); > + if (commit) > + got_object_commit_close(commit); > if (worktree) > got_worktree_close(worktree); > if (repo) { > @@ -11830,6 +11844,7 @@ cmd_cat(int argc, char *argv[]) > char *cwd = NULL, *repo_path = NULL, *label = NULL; > const char *commit_id_str = NULL; > struct got_object_id *id = NULL, *commit_id = NULL; > + struct got_commit_object *commit = NULL; > int ch, obj_type, i, force_path = 0; > struct got_reflist_head refs; > > @@ -11914,9 +11929,13 @@ cmd_cat(int argc, char *argv[]) > if (error) > goto done; > > + error = got_object_open_as_commit(&commit, repo, commit_id); > + if (error) > + goto done; > + > for (i = 0; i < argc; i++) { > if (force_path) { > - error = got_object_id_by_path(&id, repo, commit_id, > + error = got_object_id_by_path(&id, repo, commit, > argv[i]); > if (error) > break; > @@ -11929,7 +11948,7 @@ cmd_cat(int argc, char *argv[]) > error->code != GOT_ERR_NOT_REF) > break; > error = got_object_id_by_path(&id, repo, > - commit_id, argv[i]); > + commit, argv[i]); > if (error) > break; > } > @@ -11967,6 +11986,8 @@ done: > free(label); > free(id); > free(commit_id); > + if (commit) > + got_object_commit_close(commit); > if (worktree) > got_worktree_close(worktree); > if (repo) { > blob - a0286f156c9551904a9dfcbdfe00805bfe05bdf6 > blob + 70b31ef68737cdd0d46bd944fea3af2c33d3e89a > --- gotweb/gotweb.c > +++ gotweb/gotweb.c > @@ -4044,6 +4044,7 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct > const struct got_error *error = NULL; > struct got_object_id *obj_id = NULL; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > struct got_blob_object *blob = NULL; > char *path = NULL, *in_repo_path = NULL; > struct gw_blame_cb_args bca; > @@ -4069,7 +4070,11 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct > if (error) > goto done; > > - error = got_object_id_by_path(&obj_id, gw_trans->repo, commit_id, > + error = got_object_open_as_commit(&commit, gw_trans->repo, commit_id); > + if (error) > + goto done; > + > + error = got_object_id_by_path(&obj_id, gw_trans->repo, commit, > in_repo_path); > if (error) > goto done; > @@ -4142,6 +4147,8 @@ done: > } > if (blob) > got_object_blob_close(blob); > + if (commit) > + got_object_commit_close(commit); > return error; > } > > @@ -4151,6 +4158,7 @@ gw_output_blob_buf(struct gw_trans *gw_trans, struct g > const struct got_error *error = NULL; > struct got_object_id *obj_id = NULL; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > struct got_blob_object *blob = NULL; > char *path = NULL, *in_repo_path = NULL; > int obj_type, set_mime = 0; > @@ -4175,7 +4183,11 @@ gw_output_blob_buf(struct gw_trans *gw_trans, struct g > if (error) > goto done; > > - error = got_object_id_by_path(&obj_id, gw_trans->repo, commit_id, > + error = got_object_open_as_commit(&commit, gw_trans->repo, commit_id); > + if (error) > + goto done; > + > + error = got_object_id_by_path(&obj_id, gw_trans->repo, commit, > in_repo_path); > if (error) > goto done; > @@ -4232,6 +4244,8 @@ done: > free(path); > if (blob) > got_object_blob_close(blob); > + if (commit) > + got_object_commit_close(commit); > if (error == NULL && kerr != KCGI_OK) > error = gw_kcgi_error(kerr); > return error; > @@ -4243,6 +4257,7 @@ gw_output_repo_tree(struct gw_trans *gw_trans, struct > const struct got_error *error = NULL; > struct got_object_id *tree_id = NULL, *commit_id = NULL; > struct got_tree_object *tree = NULL; > + struct got_commit_object *commit = NULL; > char *path = NULL, *in_repo_path = NULL; > char *id_str = NULL; > char *build_folder = NULL; > @@ -4294,7 +4309,11 @@ gw_output_repo_tree(struct gw_trans *gw_trans, struct > goto done; > } > > - error = got_object_id_by_path(&tree_id, gw_trans->repo, commit_id, > + error = got_object_open_as_commit(&commit, gw_trans->repo, commit_id); > + if (error) > + goto done; > + > + error = got_object_id_by_path(&tree_id, gw_trans->repo, commit, > path); > if (error) > goto done; > @@ -4466,6 +4485,8 @@ gw_output_repo_tree(struct gw_trans *gw_trans, struct > done: > if (tree) > got_object_tree_close(tree); > + if (commit) > + got_object_commit_close(commit); > free(id_str); > free(href_blob); > free(href_blame); > blob - 592e77655be88e831265856057c0f2f4d253128e > blob + 9d6f362ad6242f2fdff94792bc113ede1710807d > --- include/got_object.h > +++ include/got_object.h > @@ -106,7 +106,7 @@ const struct got_error *got_object_tree_find_path(stru > * The caller should dispose of it with free(3). > */ > const struct got_error *got_object_id_by_path(struct got_object_id **, > - struct got_repository *, struct got_object_id *, const char *); > + struct got_repository *, struct got_commit_object *, const char *); > > /* > * Obtain the type of an object. > @@ -241,7 +241,7 @@ int got_object_tree_entry_is_symlink(struct got_tree_e > * target path. The caller must dispose of it with free(3). > */ > const struct got_error *got_object_resolve_symlinks(char **, const char *, > - struct got_object_id *, struct got_repository *); > + struct got_commit_object *, struct got_repository *); > > /* > * Compare two trees and indicate whether the entry at the specified path > blob - d2db8c1e2cd6a46130821551a293b51fa2c841b9 > blob + 4fb57b680144beb72b8bb8898b73e6d032ad15d8 > --- lib/blame.c > +++ lib/blame.c > @@ -200,7 +200,7 @@ blame_commit(struct got_blame *blame, struct got_objec > void *arg) > { > const struct got_error *err = NULL; > - struct got_commit_object *commit = NULL; > + struct got_commit_object *commit = NULL, *pcommit = NULL; > struct got_object_qid *pid = NULL; > struct got_object_id *pblob_id = NULL; > struct got_blob_object *pblob = NULL; > @@ -216,7 +216,11 @@ blame_commit(struct got_blame *blame, struct got_objec > return NULL; > } > > - err = got_object_id_by_path(&pblob_id, repo, pid->id, path); > + err = got_object_open_as_commit(&pcommit, repo, pid->id); > + if (err) > + goto done; > + > + err = got_object_id_by_path(&pblob_id, repo, pcommit, path); > if (err) { > if (err->code == GOT_ERR_NO_TREE_ENTRY) > err = NULL; > @@ -267,6 +271,8 @@ done: > diff_result_free(diff_result); > if (commit) > got_object_commit_close(commit); > + if (pcommit) > + got_object_commit_close(pcommit); > free(pblob_id); > if (pblob) > got_object_blob_close(pblob); > @@ -498,6 +504,7 @@ blame_open(struct got_blame **blamep, const char *path > void *arg, got_cancel_cb cancel_cb, void *cancel_arg) > { > const struct got_error *err = NULL; > + struct got_commit_object *start_commit = NULL; > struct got_object_id *obj_id = NULL; > struct got_blob_object *blob = NULL; > struct got_blame *blame = NULL; > @@ -507,10 +514,14 @@ blame_open(struct got_blame **blamep, const char *path > > *blamep = NULL; > > - err = got_object_id_by_path(&obj_id, repo, start_commit_id, path); > + err = got_object_open_as_commit(&start_commit, repo, start_commit_id); > if (err) > goto done; > > + err = got_object_id_by_path(&obj_id, repo, start_commit, path); > + if (err) > + goto done; > + > err = got_object_open_as_blob(&blob, repo, obj_id, 8192); > if (err) > goto done; > @@ -621,6 +632,8 @@ done: > free(obj_id); > if (blob) > got_object_blob_close(blob); > + if (start_commit) > + got_object_commit_close(start_commit); > if (err) { > if (blame) > blame_close(blame); > blob - 55b4da29492815a14efed2a3680b55d68dddbfd0 > blob + 644fd4c564841be0c8142f649c9e68f26133deb7 > --- lib/commit_graph.c > +++ lib/commit_graph.c > @@ -112,7 +112,7 @@ detect_changed_path(int *changed, struct got_commit_ob > pid = STAILQ_FIRST(&commit->parent_ids); > if (pid == NULL) { > struct got_object_id *obj_id; > - err = got_object_id_by_path(&obj_id, repo, commit_id, path); > + err = got_object_id_by_path(&obj_id, repo, commit, path); > if (err) { > if (err->code == GOT_ERR_NO_TREE_ENTRY) > err = NULL; > @@ -293,20 +293,30 @@ advance_branch(struct got_commit_graph *graph, struct > struct got_object_id *merged_id, *prev_id = NULL; > int branches_differ = 0; > > - err = got_object_id_by_path(&merged_id, repo, commit_id, > + err = got_object_id_by_path(&merged_id, repo, commit, > graph->path); > if (err) > return err; > > STAILQ_FOREACH(qid, &commit->parent_ids, entry) { > - struct got_object_id *id; > + struct got_object_id *id = NULL; > + struct got_commit_object *pcommit = NULL; > > if (got_object_idset_contains(graph->open_branches, > qid->id)) > continue; > > - err = got_object_id_by_path(&id, repo, qid->id, > + err = got_object_open_as_commit(&pcommit, repo, > + qid->id); > + if (err) { > + free(merged_id); > + free(prev_id); > + return err; > + } > + err = got_object_id_by_path(&id, repo, pcommit, > graph->path); > + got_object_commit_close(pcommit); > + pcommit = NULL; > if (err) { > if (err->code == GOT_ERR_NO_TREE_ENTRY) { > branches_differ = 1; > blob - 8218b2c4c146e832c63f84d4a9f6a43f8b3283f8 > blob + f6a83e12b20b326cac3cf14c4fe93d71d56a2775 > --- lib/object.c > +++ lib/object.c > @@ -1998,18 +1998,13 @@ done: > } > const struct got_error * > got_object_id_by_path(struct got_object_id **id, struct got_repository *repo, > - struct got_object_id *commit_id, const char *path) > + struct got_commit_object *commit, const char *path) > { > const struct got_error *err = NULL; > - struct got_commit_object *commit = NULL; > struct got_tree_object *tree = NULL; > > *id = NULL; > > - err = got_object_open_as_commit(&commit, repo, commit_id); > - if (err) > - goto done; > - > /* Handle opening of root of commit's tree. */ > if (got_path_is_root_dir(path)) { > *id = got_object_id_dup(commit->tree_id); > @@ -2022,8 +2017,6 @@ got_object_id_by_path(struct got_object_id **id, struc > err = got_object_tree_find_path(id, NULL, repo, tree, path); > } > done: > - if (commit) > - got_object_commit_close(commit); > if (tree) > got_object_tree_close(tree); > return err; > @@ -2187,7 +2180,7 @@ got_object_tree_entry_is_symlink(struct got_tree_entry > > static const struct got_error * > resolve_symlink(char **link_target, const char *path, > - struct got_object_id *commit_id, struct got_repository *repo) > + struct got_commit_object *commit, struct got_repository *repo) > { > const struct got_error *err = NULL; > char buf[PATH_MAX]; > @@ -2209,7 +2202,7 @@ resolve_symlink(char **link_target, const char *path, > if (err) > return err; > > - err = got_object_id_by_path(&tree_obj_id, repo, commit_id, > + err = got_object_id_by_path(&tree_obj_id, repo, commit, > parent_path); > if (err) { > if (err->code == GOT_ERR_NO_TREE_ENTRY) { > @@ -2265,7 +2258,7 @@ done: > > const struct got_error * > got_object_resolve_symlinks(char **link_target, const char *path, > - struct got_object_id *commit_id, struct got_repository *repo) > + struct got_commit_object *commit, struct got_repository *repo) > { > const struct got_error *err = NULL; > char *next_target = NULL; > @@ -2275,7 +2268,7 @@ got_object_resolve_symlinks(char **link_target, const > > do { > err = resolve_symlink(&next_target, > - *link_target ? *link_target : path, commit_id, repo); > + *link_target ? *link_target : path, commit, repo); > if (err) > break; > if (next_target) { > blob - 16eebc519859d846026d968e3e953c502035de48 > blob + bfebb46526cc0f3f0deda90d0868edad7c6946c9 > --- lib/worktree.c > +++ lib/worktree.c > @@ -2459,7 +2459,8 @@ done: > static const struct got_error * > find_tree_entry_for_checkout(int *entry_type, char **tree_relpath, > struct got_object_id **tree_id, const char *wt_relpath, > - struct got_worktree *worktree, struct got_repository *repo) > + struct got_commit_object *base_commit, struct got_worktree *worktree, > + struct got_repository *repo) > { > const struct got_error *err = NULL; > struct got_object_id *id = NULL; > @@ -2478,8 +2479,8 @@ find_tree_entry_for_checkout(int *entry_type, char **t > err = got_error_from_errno("strdup"); > goto done; > } > - err = got_object_id_by_path(tree_id, repo, > - worktree->base_commit_id, worktree->path_prefix); > + err = got_object_id_by_path(tree_id, repo, base_commit, > + worktree->path_prefix); > if (err) > goto done; > return NULL; > @@ -2493,8 +2494,7 @@ find_tree_entry_for_checkout(int *entry_type, char **t > goto done; > } > > - err = got_object_id_by_path(&id, repo, worktree->base_commit_id, > - in_repo_path); > + err = got_object_id_by_path(&id, repo, base_commit, in_repo_path); > if (err) > goto done; > > @@ -2532,7 +2532,7 @@ find_tree_entry_for_checkout(int *entry_type, char **t > } > } > err = got_object_id_by_path(tree_id, repo, > - worktree->base_commit_id, in_repo_path); > + base_commit, in_repo_path); > } else { > /* Check out all files within a subdirectory. */ > *tree_id = got_object_id_dup(id); > @@ -2644,6 +2644,11 @@ got_worktree_checkout_files(struct got_worktree *workt > if (err) > return err; > > + err = got_object_open_as_commit(&commit, repo, > + worktree->base_commit_id); > + if (err) > + goto done; > + > /* Map all specified paths to in-repository trees. */ > TAILQ_FOREACH(pe, paths, entry) { > tpd = malloc(sizeof(*tpd)); > @@ -2653,7 +2658,8 @@ got_worktree_checkout_files(struct got_worktree *workt > } > > err = find_tree_entry_for_checkout(&tpd->entry_type, > - &tpd->relpath, &tpd->tree_id, pe->path, worktree, repo); > + &tpd->relpath, &tpd->tree_id, pe->path, commit, > + worktree, repo); > if (err) { > free(tpd); > goto done; > @@ -3095,12 +3101,16 @@ merge_files(struct got_worktree *worktree, struct got_ > const struct got_error *err = NULL, *sync_err; > struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL; > struct got_tree_object *tree1 = NULL, *tree2 = NULL; > + struct got_commit_object *commit1 = NULL, *commit2 = NULL; > struct check_merge_conflicts_arg cmc_arg; > struct merge_file_cb_arg arg; > char *label_orig = NULL; > > if (commit_id1) { > - err = got_object_id_by_path(&tree_id1, repo, commit_id1, > + err = got_object_open_as_commit(&commit1, repo, commit_id1); > + if (err) > + goto done; > + err = got_object_id_by_path(&tree_id1, repo, commit1, > worktree->path_prefix); > if (err && err->code != GOT_ERR_NO_TREE_ENTRY) > goto done; > @@ -3125,7 +3135,11 @@ merge_files(struct got_worktree *worktree, struct got_ > free(id_str); > } > > - err = got_object_id_by_path(&tree_id2, repo, commit_id2, > + err = got_object_open_as_commit(&commit2, repo, commit_id2); > + if (err) > + goto done; > + > + err = got_object_id_by_path(&tree_id2, repo, commit2, > worktree->path_prefix); > if (err) > goto done; > @@ -3156,6 +3170,10 @@ merge_files(struct got_worktree *worktree, struct got_ > if (sync_err && err == NULL) > err = sync_err; > done: > + if (commit1) > + got_object_commit_close(commit1); > + if (commit2) > + got_object_commit_close(commit2); > if (tree1) > got_object_tree_close(tree1); > if (tree2) > @@ -4544,6 +4562,7 @@ revert_file(void *arg, unsigned char status, unsigned > const struct got_error *err = NULL; > char *parent_path = NULL; > struct got_fileindex_entry *ie; > + struct got_commit_object *base_commit = NULL; > struct got_tree_object *tree = NULL; > struct got_object_id *tree_id = NULL; > const struct got_tree_entry *te = NULL; > @@ -4597,8 +4616,12 @@ revert_file(void *arg, unsigned char status, unsigned > } > } > > - err = got_object_id_by_path(&tree_id, a->repo, > - a->worktree->base_commit_id, tree_path); > + err = got_object_open_as_commit(&base_commit, a->repo, > + a->worktree->base_commit_id); > + if (err) > + goto done; > + > + err = got_object_id_by_path(&tree_id, a->repo, base_commit, tree_path); > if (err) { > if (!(err->code == GOT_ERR_NO_TREE_ENTRY && > (status == GOT_STATUS_ADD || > @@ -4756,6 +4779,8 @@ done: > if (tree) > got_object_tree_close(tree); > free(tree_id); > + if (base_commit) > + got_object_commit_close(base_commit); > return err; > } > > @@ -5513,6 +5538,7 @@ check_out_of_date(const char *in_repo_path, unsigned c > int ood_errcode) > { > const struct got_error *err = NULL; > + struct got_commit_object *commit = NULL; > struct got_object_id *id = NULL; > > if (status != GOT_STATUS_ADD && staged_status != GOT_STATUS_ADD) { > @@ -5523,8 +5549,10 @@ check_out_of_date(const char *in_repo_path, unsigned c > * Ensure file content which local changes were based > * on matches file content in the branch head. > */ > - err = got_object_id_by_path(&id, repo, head_commit_id, > - in_repo_path); > + err = got_object_open_as_commit(&commit, repo, head_commit_id); > + if (err) > + goto done; > + err = got_object_id_by_path(&id, repo, commit, in_repo_path); > if (err) { > if (err->code == GOT_ERR_NO_TREE_ENTRY) > err = got_error(ood_errcode); > @@ -5533,14 +5561,18 @@ check_out_of_date(const char *in_repo_path, unsigned c > err = got_error(ood_errcode); > } else { > /* Require that added files don't exist in the branch head. */ > - err = got_object_id_by_path(&id, repo, head_commit_id, > - in_repo_path); > + err = got_object_open_as_commit(&commit, repo, head_commit_id); > + if (err) > + goto done; > + err = got_object_id_by_path(&id, repo, commit, in_repo_path); > if (err && err->code != GOT_ERR_NO_TREE_ENTRY) > goto done; > err = id ? got_error(ood_errcode) : NULL; > } > done: > free(id); > + if (commit) > + got_object_commit_close(commit); > return err; > } > > @@ -6692,6 +6724,7 @@ got_worktree_rebase_abort(struct got_worktree *worktre > const struct got_error *err, *unlockerr, *sync_err; > struct got_reference *resolved = NULL; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > char *fileindex_path = NULL; > struct revert_file_args rfa; > struct got_object_id *tree_id = NULL; > @@ -6700,6 +6733,11 @@ got_worktree_rebase_abort(struct got_worktree *worktre > if (err) > return err; > > + err = got_object_open_as_commit(&commit, repo, > + worktree->base_commit_id); > + if (err) > + goto done; > + > err = got_ref_open(&resolved, repo, > got_ref_get_symref_target(new_base_branch), 0); > if (err) > @@ -6722,8 +6760,8 @@ got_worktree_rebase_abort(struct got_worktree *worktre > if (err) > goto done; > > - err = got_object_id_by_path(&tree_id, repo, > - worktree->base_commit_id, worktree->path_prefix); > + err = got_object_id_by_path(&tree_id, repo, commit, > + worktree->path_prefix); > if (err) > goto done; > > @@ -6758,6 +6796,8 @@ done: > got_ref_close(resolved); > free(tree_id); > free(commit_id); > + if (commit) > + got_object_commit_close(commit); > if (fileindex) > got_fileindex_free(fileindex); > free(fileindex_path); > @@ -7056,6 +7096,7 @@ got_worktree_histedit_abort(struct got_worktree *workt > const struct got_error *err, *unlockerr, *sync_err; > struct got_reference *resolved = NULL; > char *fileindex_path = NULL; > + struct got_commit_object *commit = NULL; > struct got_object_id *tree_id = NULL; > struct revert_file_args rfa; > > @@ -7063,6 +7104,11 @@ got_worktree_histedit_abort(struct got_worktree *workt > if (err) > return err; > > + err = got_object_open_as_commit(&commit, repo, > + worktree->base_commit_id); > + if (err) > + goto done; > + > err = got_ref_open(&resolved, repo, > got_ref_get_symref_target(branch), 0); > if (err) > @@ -7076,7 +7122,7 @@ got_worktree_histedit_abort(struct got_worktree *workt > if (err) > goto done; > > - err = got_object_id_by_path(&tree_id, repo, base_commit_id, > + err = got_object_id_by_path(&tree_id, repo, commit, > worktree->path_prefix); > if (err) > goto done; > @@ -7269,6 +7315,7 @@ got_worktree_integrate_continue(struct got_worktree *w > const struct got_error *err = NULL, *sync_err, *unlockerr; > char *fileindex_path = NULL; > struct got_object_id *tree_id = NULL, *commit_id = NULL; > + struct got_commit_object *commit = NULL; > > err = get_fileindex_path(&fileindex_path, worktree); > if (err) > @@ -7278,7 +7325,11 @@ got_worktree_integrate_continue(struct got_worktree *w > if (err) > goto done; > > - err = got_object_id_by_path(&tree_id, repo, commit_id, > + err = got_object_open_as_commit(&commit, repo, commit_id); > + if (err) > + goto done; > + > + err = got_object_id_by_path(&tree_id, repo, commit, > worktree->path_prefix); > if (err) > goto done; > @@ -7320,6 +7371,8 @@ done: > got_fileindex_free(fileindex); > free(fileindex_path); > free(tree_id); > + if (commit) > + got_object_commit_close(commit); > > unlockerr = lock_worktree(worktree, LOCK_SH); > if (unlockerr && err == NULL) > @@ -7780,15 +7833,21 @@ got_worktree_merge_abort(struct got_worktree *worktree > { > const struct got_error *err, *unlockerr, *sync_err; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > char *fileindex_path = NULL; > struct revert_file_args rfa; > struct got_object_id *tree_id = NULL; > > - err = got_object_id_by_path(&tree_id, repo, > - worktree->base_commit_id, worktree->path_prefix); > + err = got_object_open_as_commit(&commit, repo, > + worktree->base_commit_id); > if (err) > goto done; > > + err = got_object_id_by_path(&tree_id, repo, commit, > + worktree->path_prefix); > + if (err) > + goto done; > + > err = delete_merge_refs(worktree, repo); > if (err) > goto done; > @@ -7819,6 +7878,8 @@ sync: > done: > free(tree_id); > free(commit_id); > + if (commit) > + got_object_commit_close(commit); > if (fileindex) > got_fileindex_free(fileindex); > free(fileindex_path); > blob - 162cb7c902a68e5ba42a938f863e0f9846e84b1a > blob + cf640001b1d644e38bc4909d42362dd3ed7f348e > --- tog/tog.c > +++ tog/tog.c > @@ -1910,7 +1910,7 @@ tree_view_visit_subtree(struct tog_tree_view_state *s, > > static const struct got_error * > tree_view_walk_path(struct tog_tree_view_state *s, > - struct got_object_id *commit_id, const char *path) > + struct got_commit_object *commit, const char *path) > { > const struct got_error *err = NULL; > struct got_tree_object *tree = NULL; > @@ -1959,7 +1959,7 @@ tree_view_walk_path(struct tog_tree_view_state *s, > break; > } > > - err = got_object_id_by_path(&tree_id, s->repo, commit_id, > + err = got_object_id_by_path(&tree_id, s->repo, commit, > subpath); > if (err) > break; > @@ -2008,7 +2008,7 @@ browse_commit_tree(struct tog_view **new_view, int beg > if (got_path_is_root_dir(path)) > return NULL; > > - return tree_view_walk_path(s, entry->id, path); > + return tree_view_walk_path(s, entry->commit, path); > } > > static const struct got_error * > @@ -4329,16 +4329,21 @@ run_blame(struct tog_view *view) > struct tog_blame_view_state *s = &view->state.blame; > struct tog_blame *blame = &s->blame; > const struct got_error *err = NULL; > + struct got_commit_object *commit = NULL; > struct got_blob_object *blob = NULL; > struct got_repository *thread_repo = NULL; > struct got_object_id *obj_id = NULL; > int obj_type; > > - err = got_object_id_by_path(&obj_id, s->repo, s->blamed_commit->id, > - s->path); > + err = got_object_open_as_commit(&commit, s->repo, > + s->blamed_commit->id); > if (err) > return err; > > + err = got_object_id_by_path(&obj_id, s->repo, commit, s->path); > + if (err) > + goto done; > + > err = got_object_get_type(&obj_type, s->repo, obj_id); > if (err) > goto done; > @@ -4405,6 +4410,8 @@ run_blame(struct tog_view *view) > s->matched_line = 0; > > done: > + if (commit) > + got_object_commit_close(commit); > if (blob) > got_object_blob_close(blob); > free(obj_id); > @@ -4646,7 +4653,7 @@ input_blame_view(struct tog_view **new_view, struct to > if (id == NULL) > break; > if (ch == 'p') { > - struct got_commit_object *commit; > + struct got_commit_object *commit, *pcommit; > struct got_object_qid *pid; > struct got_object_id *blob_id = NULL; > int obj_type; > @@ -4661,8 +4668,13 @@ input_blame_view(struct tog_view **new_view, struct to > break; > } > /* Check if path history ends here. */ > + err = got_object_open_as_commit(&pcommit, > + s->repo, pid->id); > + if (err) > + break; > err = got_object_id_by_path(&blob_id, s->repo, > - pid->id, s->path); > + pcommit, s->path); > + got_object_commit_close(pcommit); > if (err) { > if (err->code == GOT_ERR_NO_TREE_ENTRY) > err = NULL; > @@ -4807,6 +4819,7 @@ cmd_blame(int argc, char *argv[]) > char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL; > char *link_target = NULL; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > char *commit_id_str = NULL; > int ch; > struct tog_view *view; > @@ -4892,8 +4905,12 @@ cmd_blame(int argc, char *argv[]) > goto done; > } > > + error = got_object_open_as_commit(&commit, repo, commit_id); > + if (error) > + goto done; > + > error = got_object_resolve_symlinks(&link_target, in_repo_path, > - commit_id, repo); > + commit, repo); > if (error) > goto done; > > @@ -4913,6 +4930,8 @@ done: > free(link_target); > free(cwd); > free(commit_id); > + if (commit) > + got_object_commit_close(commit); > if (worktree) > got_worktree_close(worktree); > if (repo) { > @@ -5659,6 +5678,7 @@ cmd_tree(int argc, char *argv[]) > struct got_worktree *worktree = NULL; > char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL; > struct got_object_id *commit_id = NULL; > + struct got_commit_object *commit = NULL; > const char *commit_id_arg = NULL; > char *label = NULL; > struct got_reference *ref = NULL; > @@ -5745,6 +5765,10 @@ cmd_tree(int argc, char *argv[]) > goto done; > } > > + error = got_object_open_as_commit(&commit, repo, commit_id); > + if (error) > + goto done; > + > view = view_open(0, 0, 0, 0, TOG_VIEW_TREE); > if (view == NULL) { > error = got_error_from_errno("view_open"); > @@ -5754,7 +5778,7 @@ cmd_tree(int argc, char *argv[]) > if (error) > goto done; > if (!got_path_is_root_dir(in_repo_path)) { > - error = tree_view_walk_path(&view->state.tree, commit_id, > + error = tree_view_walk_path(&view->state.tree, commit, > in_repo_path); > if (error) > goto done; > @@ -6559,6 +6583,7 @@ tog_log_with_path(int argc, char *argv[]) > struct got_repository *repo = NULL; > struct got_worktree *worktree = NULL; > struct got_object_id *commit_id = NULL, *id = NULL; > + struct got_commit_object *commit = NULL; > char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL; > char *commit_id_str = NULL, **cmd_argv = NULL; > > @@ -6602,7 +6627,11 @@ tog_log_with_path(int argc, char *argv[]) > worktree = NULL; > } > > - error = got_object_id_by_path(&id, repo, commit_id, in_repo_path); > + error = got_object_open_as_commit(&commit, repo, commit_id); > + if (error) > + goto done; > + > + error = got_object_id_by_path(&id, repo, commit, in_repo_path); > if (error) { > if (error->code != GOT_ERR_NO_TREE_ENTRY) > goto done; > @@ -6631,6 +6660,8 @@ done: > if (error == NULL) > error = close_err; > } > + if (commit) > + got_object_commit_close(commit); > if (worktree) > got_worktree_close(worktree); > free(id);