commit 941e9f741afacc0a0b0fc19b80c534c8917589fb from: Stefan Sperling date: Tue May 21 11:32:41 2019 UTC tog: if opened from log view, open tree view at path being logged commit - 8cbe58099b1488354d3efbfcb9f4877ed5b1364c commit + 941e9f741afacc0a0b0fc19b80c534c8917589fb blob - f6e6728835caba36f32640aac656a5dcc1431600 blob + d0e5a2aa7f3136157c5f5d9036fcffa69949bcf1 --- tog/tog.c +++ tog/tog.c @@ -1389,13 +1389,40 @@ open_diff_view_for_commit(struct tog_view **new_view, } static const struct got_error * -browse_commit(struct tog_view **new_view, int begin_x, - struct commit_queue_entry *entry, struct got_reflist_head *refs, - struct got_repository *repo) +tree_view_visit_subtree(struct got_tree_object *subtree, + struct tog_tree_view_state *s) { + struct tog_parent_tree *parent; + + parent = calloc(1, sizeof(*parent)); + if (parent == NULL) + return got_error_from_errno("calloc"); + + parent->tree = s->tree; + parent->first_displayed_entry = s->first_displayed_entry; + parent->selected_entry = s->selected_entry; + parent->selected = s->selected; + TAILQ_INSERT_HEAD(&s->parents, parent, entry); + s->tree = subtree; + s->entries = got_object_tree_get_entries(s->tree); + s->selected = 0; + s->first_displayed_entry = NULL; + return NULL; +} + + +static const struct got_error * +browse_commit_tree(struct tog_view **new_view, int begin_x, + struct commit_queue_entry *entry, const char *path, + struct got_reflist_head *refs, struct got_repository *repo) +{ const struct got_error *err = NULL; struct got_tree_object *tree; + struct got_tree_entry *te; + struct tog_tree_view_state *s; struct tog_view *tree_view; + char *slash, *subpath; + const char *p; err = got_object_open_as_tree(&tree, repo, got_object_commit_get_tree_id(entry->commit)); @@ -1407,10 +1434,73 @@ browse_commit(struct tog_view **new_view, int begin_x, return got_error_from_errno("view_open"); err = open_tree_view(tree_view, tree, entry->id, refs, repo); - if (err) + if (err) { got_object_tree_close(tree); - else - *new_view = tree_view; + return err; + } + s = &tree_view->state.tree; + + *new_view = tree_view; + + if (got_path_is_root_dir(path)) + return NULL; + + /* Walk the path and open corresponding tree objects. */ + p = path; + while (*p) { + struct got_object_id *tree_id; + + while (p[0] == '/') + p++; + + /* Ensure the correct subtree entry is selected. */ + slash = strchr(p, '/'); + if (slash == NULL) + slash = strchr(p, '\0'); + SIMPLEQ_FOREACH(te, &s->entries->head, entry) { + if (strncmp(p, te->name, slash - p) == 0) { + s->selected_entry = te; + break; + } + } + if (s->selected_entry == NULL) { + err = got_error(GOT_ERR_NO_TREE_ENTRY); + break; + } + + slash = strchr(p, '/'); + if (slash) + subpath = strndup(path, slash - path); + else + subpath = strdup(path); + if (subpath == NULL) { + err = got_error_from_errno("strdup"); + break; + } + + err = got_object_id_by_path(&tree_id, repo, entry->id, + subpath); + if (err) + break; + + err = got_object_open_as_tree(&tree, repo, tree_id); + free(tree_id); + if (err) + break; + + err = tree_view_visit_subtree(tree, s); + if (err) { + got_object_tree_close(tree); + break; + } + if (slash == NULL) + break; + free(subpath); + subpath = NULL; + p = slash; + } + + free(subpath); return err; } @@ -1721,8 +1811,8 @@ input_log_view(struct tog_view **new_view, struct tog_ break; if (view_is_parent_view(view)) begin_x = view_split_begin_x(view->begin_x); - err = browse_commit(&tree_view, begin_x, - s->selected_entry, s->refs, s->repo); + err = browse_commit_tree(&tree_view, begin_x, + s->selected_entry, s->in_repo_path, s->refs, s->repo); if (err) break; if (view_is_parent_view(view)) { @@ -3772,28 +3862,16 @@ input_tree_view(struct tog_view **new_view, struct tog s->selected = parent->selected; free(parent); } else if (S_ISDIR(s->selected_entry->mode)) { - struct tog_parent_tree *parent; - struct got_tree_object *child; - err = got_object_open_as_tree(&child, + struct got_tree_object *subtree; + err = got_object_open_as_tree(&subtree, s->repo, s->selected_entry->id); if (err) break; - parent = calloc(1, sizeof(*parent)); - if (parent == NULL) { - err = got_error_from_errno("calloc"); + err = tree_view_visit_subtree(subtree, s); + if (err) { + got_object_tree_close(subtree); break; } - parent->tree = s->tree; - parent->first_displayed_entry = - s->first_displayed_entry; - parent->selected_entry = s->selected_entry; - parent->selected = s->selected; - TAILQ_INSERT_HEAD(&s->parents, parent, entry); - s->tree = child; - s->entries = - got_object_tree_get_entries(s->tree); - s->selected = 0; - s->first_displayed_entry = NULL; } else if (S_ISREG(s->selected_entry->mode)) { struct tog_view *blame_view; int begin_x = view_is_parent_view(view) ?