commit ad80ab7bbcd36adcb6e10ed8d9e31a573d188b35 from: Stefan Sperling date: Sat Aug 04 14:50:59 2018 UTC split tog's tree view into open/show/close functions commit - 7cbe629dd726b1f6ec613555e70a79718e615b1c commit + ad80ab7bbcd36adcb6e10ed8d9e31a573d188b35 blob - 4d8685eb92f1f29a4486ebda2670d065385c477d blob + 62a436a1ce30e16c207ee46e03c16eda0b912197 --- tog/tog.c +++ tog/tog.c @@ -85,10 +85,16 @@ static struct tog_cmd tog_commands[] = { enum tog_view_type { TOG_VIEW_DIFF, TOG_VIEW_LOG, - TOG_VIEW_TREE, - TOG_VIEW_BLAME + TOG_VIEW_BLAME, + TOG_VIEW_TREE }; +struct tog_diff_view_state { + FILE *f; + int first_displayed_line; + int last_displayed_line; +}; + struct commit_queue_entry { TAILQ_ENTRY(commit_queue_entry) entry; struct got_object_id *id; @@ -100,12 +106,6 @@ struct commit_queue { struct commit_queue_head head; }; -struct tog_diff_view_state { - FILE *f; - int first_displayed_line; - int last_displayed_line; -}; - struct tog_log_view_state { struct got_commit_graph *graph; struct commit_queue commits; @@ -127,7 +127,31 @@ struct tog_blame_view_state { struct got_object_qid *blamed_commit; const char *path; struct got_repository *repo; + struct got_object_id *commit_id; +}; + +struct tog_parent_tree { + TAILQ_ENTRY(tog_parent_tree) entry; + struct got_tree_object *tree; + struct got_tree_entry *first_displayed_entry; + struct got_tree_entry *selected_entry; + int selected; +}; + +TAILQ_HEAD(tog_parent_trees, tog_parent_tree); + +struct tog_tree_view_state { + char *tree_label; + struct got_tree_object *root; + struct got_tree_object *tree; + const struct got_tree_entries *entries; + struct got_tree_entry *first_displayed_entry; + struct got_tree_entry *last_displayed_entry; + struct got_tree_entry *selected_entry; + int nentries, ndisplayed, selected, show_ids; + struct tog_parent_trees parents; struct got_object_id *commit_id; + struct got_repository *repo; }; struct tog_view { @@ -143,6 +167,7 @@ struct tog_view { struct tog_diff_view_state diff; struct tog_log_view_state log; struct tog_blame_view_state blame; + struct tog_tree_view_state tree; } state; }; @@ -158,8 +183,10 @@ static const struct got_error *open_blame_view(struct struct got_object_id *, struct got_repository *); static const struct got_error *show_blame_view(struct tog_view *); static void close_blame_view(struct tog_view *); -static const struct got_error *show_tree_view(struct tog_view *, +static const struct got_error *open_tree_view(struct tog_view *, struct got_tree_object *, struct got_object_id *, struct got_repository *); +static const struct got_error *show_tree_view(struct tog_view *); +static void close_tree_view(struct tog_view *); static void view_close(struct tog_view *view) @@ -175,7 +202,7 @@ static struct tog_view * view_open(int nlines, int ncols, int begin_y, int begin_x, struct tog_view *parent, enum tog_view_type type) { - struct tog_view *view = malloc(sizeof(*view)); + struct tog_view *view = calloc(1, sizeof(*view)); if (view == NULL) return NULL; @@ -837,7 +864,11 @@ browse_commit(struct tog_view *parent_view, struct com err = got_error_from_errno(); goto done; } - err = show_tree_view(view, tree, entry->id, repo); + err = open_tree_view(view, tree, entry->id, repo); + if (err) + goto done; + err = show_tree_view(view); + close_tree_view(view); view_close(view); view_show(parent_view); done: @@ -2332,16 +2363,6 @@ tree_scroll_down(struct got_tree_entry **first_display } } -struct tog_parent_tree { - TAILQ_ENTRY(tog_parent_tree) entry; - struct got_tree_object *tree; - struct got_tree_entry *first_displayed_entry; - struct got_tree_entry *selected_entry; - int selected; -}; - -TAILQ_HEAD(tog_parent_trees, tog_parent_tree); - static const struct got_error * tree_entry_path(char **path, struct tog_parent_trees *parents, struct got_tree_entry *te) @@ -2439,50 +2460,79 @@ done: } static const struct got_error * -show_tree_view(struct tog_view *view, struct got_tree_object *root, +open_tree_view(struct tog_view *view, struct got_tree_object *root, struct got_object_id *commit_id, struct got_repository *repo) { const struct got_error *err = NULL; - int ch, done = 0, selected = 0, show_ids = 0; - struct got_tree_object *tree = root; - const struct got_tree_entries *entries; - struct got_tree_entry *first_displayed_entry = NULL; - struct got_tree_entry *last_displayed_entry = NULL; - struct got_tree_entry *selected_entry = NULL; - char *commit_id_str = NULL, *tree_label = NULL; - int nentries, ndisplayed; - struct tog_parent_trees parents; + char *commit_id_str = NULL; + struct tog_tree_view_state *state = &view->state.tree; - TAILQ_INIT(&parents); + TAILQ_INIT(&state->parents); err = got_object_id_str(&commit_id_str, commit_id); if (err != NULL) goto done; - if (asprintf(&tree_label, "commit: %s", commit_id_str) == -1) { + if (asprintf(&state->tree_label, "commit: %s", commit_id_str) == -1) { err = got_error_from_errno(); goto done; } + state->root = state->tree = root; + state->entries = got_object_tree_get_entries(root); + state->first_displayed_entry = SIMPLEQ_FIRST(&state->entries->head); + state->commit_id = commit_id; + state->repo = repo; +done: + free(commit_id_str); + if (err) + free(state->tree_label); + return err; +} + +static void +close_tree_view(struct tog_view *view) +{ + struct tog_tree_view_state *state = &view->state.tree; + + free(state->tree_label); + while (!TAILQ_EMPTY(&state->parents)) { + struct tog_parent_tree *parent; + parent = TAILQ_FIRST(&state->parents); + TAILQ_REMOVE(&state->parents, parent, entry); + free(parent); + + } + if (state->tree != state->root) + got_object_tree_close(state->tree); +} + +static const struct got_error * +show_tree_view(struct tog_view *view) +{ + const struct got_error *err = NULL; + struct tog_tree_view_state *state = &view->state.tree; + int ch, done = 0; + int nentries; + view_show(view); - entries = got_object_tree_get_entries(root); - first_displayed_entry = SIMPLEQ_FIRST(&entries->head); while (!done) { char *parent_path; - entries = got_object_tree_get_entries(tree); - nentries = entries->nentries; - if (tree != root) + state->entries = got_object_tree_get_entries(state->tree); + nentries = state->entries->nentries; + if (state->tree != state->root) nentries++; /* '..' directory */ - err = tree_entry_path(&parent_path, &parents, NULL); + err = tree_entry_path(&parent_path, &state->parents, NULL); if (err) goto done; - err = draw_tree_entries(view, &first_displayed_entry, - &last_displayed_entry, &selected_entry, &ndisplayed, - tree_label, show_ids, parent_path, entries, selected, - view->nlines, tree == root); + err = draw_tree_entries(view, &state->first_displayed_entry, + &state->last_displayed_entry, &state->selected_entry, + &state->ndisplayed, state->tree_label, state->show_ids, + parent_path, state->entries, state->selected, + view->nlines, state->tree == state->root); free(parent_path); if (err) break; @@ -2495,10 +2545,10 @@ show_tree_view(struct tog_view *view, struct got_tree_ done = 1; break; case 'i': - show_ids = !show_ids; + state->show_ids = !state->show_ids; break; case 'l': - if (selected_entry) { + if (state->selected_entry) { struct tog_view *log_view; log_view = view_open(0, 0, 0, 0, view, TOG_VIEW_LOG); @@ -2507,8 +2557,9 @@ show_tree_view(struct tog_view *view, struct got_tree_ goto done; } err = log_tree_entry(log_view, - selected_entry, &parents, - commit_id, repo); + state->selected_entry, + &state->parents, + state->commit_id, state->repo); view_close(log_view); view_show(view); if (err) @@ -2517,65 +2568,66 @@ show_tree_view(struct tog_view *view, struct got_tree_ break; case 'k': case KEY_UP: - if (selected > 0) - selected--; - if (selected > 0) + if (state->selected > 0) + state->selected--; + if (state->selected > 0) break; - tree_scroll_up(&first_displayed_entry, 1, - entries, tree == root); + tree_scroll_up(&state->first_displayed_entry, 1, + state->entries, state->tree == state->root); break; case KEY_PPAGE: - if (SIMPLEQ_FIRST(&entries->head) == - first_displayed_entry) { - if (tree != root) - first_displayed_entry = NULL; - selected = 0; + if (SIMPLEQ_FIRST(&state->entries->head) == + state->first_displayed_entry) { + if (state->tree != state->root) + state->first_displayed_entry = NULL; + state->selected = 0; break; } - tree_scroll_up(&first_displayed_entry, - view->nlines, entries, tree == root); + tree_scroll_up(&state->first_displayed_entry, + view->nlines, state->entries, + state->tree == state->root); break; case 'j': case KEY_DOWN: - if (selected < ndisplayed - 1) { - selected++; + if (state->selected < state->ndisplayed - 1) { + state->selected++; break; } - tree_scroll_down(&first_displayed_entry, 1, - last_displayed_entry, entries); + tree_scroll_down(&state->first_displayed_entry, 1, + state->last_displayed_entry, state->entries); break; case KEY_NPAGE: - tree_scroll_down(&first_displayed_entry, - view->nlines, last_displayed_entry, - entries); - if (SIMPLEQ_NEXT(last_displayed_entry, entry)) + tree_scroll_down(&state->first_displayed_entry, + view->nlines, state->last_displayed_entry, + state->entries); + if (SIMPLEQ_NEXT(state->last_displayed_entry, entry)) break; /* can't scroll any further; move cursor down */ - if (selected < ndisplayed - 1) - selected = ndisplayed - 1; + if (state->selected < state->ndisplayed - 1) + state->selected = state->ndisplayed - 1; break; case KEY_ENTER: case '\r': - if (selected_entry == NULL) { + if (state->selected_entry == NULL) { struct tog_parent_tree *parent; case KEY_BACKSPACE: /* user selected '..' */ - if (tree == root) + if (state->tree == state->root) break; - parent = TAILQ_FIRST(&parents); - TAILQ_REMOVE(&parents, parent, entry); - got_object_tree_close(tree); - tree = parent->tree; - first_displayed_entry = + parent = TAILQ_FIRST(&state->parents); + TAILQ_REMOVE(&state->parents, parent, entry); + got_object_tree_close(state->tree); + state->tree = parent->tree; + state->first_displayed_entry = parent->first_displayed_entry; - selected_entry = parent->selected_entry; - selected = parent->selected; + state->selected_entry = parent->selected_entry; + state->selected = parent->selected; free(parent); - } else if (S_ISDIR(selected_entry->mode)) { + } else if (S_ISDIR(state->selected_entry->mode)) { struct tog_parent_tree *parent; struct got_tree_object *child; err = got_object_open_as_tree( - &child, repo, selected_entry->id); + &child, state->repo, state->selected_entry->id); if (err) goto done; parent = calloc(1, sizeof(*parent)); @@ -2583,20 +2635,20 @@ show_tree_view(struct tog_view *view, struct got_tree_ err = got_error_from_errno(); goto done; } - parent->tree = tree; + parent->tree = state->tree; parent->first_displayed_entry = - first_displayed_entry; - parent->selected_entry = selected_entry; - parent->selected = selected; - TAILQ_INSERT_HEAD(&parents, parent, + state->first_displayed_entry; + parent->selected_entry = state->selected_entry; + parent->selected = state->selected; + TAILQ_INSERT_HEAD(&state->parents, parent, entry); - tree = child; - selected = 0; - first_displayed_entry = NULL; - } else if (S_ISREG(selected_entry->mode)) { + state->tree = child; + state->selected = 0; + state->first_displayed_entry = NULL; + } else if (S_ISREG(state->selected_entry->mode)) { err = blame_tree_entry(view, - selected_entry, &parents, - commit_id, repo); + state->selected_entry, &state->parents, + state->commit_id, state->repo); if (err) goto done; } @@ -2605,25 +2657,14 @@ show_tree_view(struct tog_view *view, struct got_tree_ err = view_resize(view); if (err) goto done; - if (selected > view->nlines) - selected = ndisplayed - 1; + if (state->selected > view->nlines) + state->selected = state->ndisplayed - 1; break; default: break; } } done: - free(tree_label); - free(commit_id_str); - while (!TAILQ_EMPTY(&parents)) { - struct tog_parent_tree *parent; - parent = TAILQ_FIRST(&parents); - TAILQ_REMOVE(&parents, parent, entry); - free(parent); - - } - if (tree != root) - got_object_tree_close(tree); return err; } @@ -2713,7 +2754,11 @@ cmd_tree(int argc, char *argv[]) error = got_error_from_errno(); goto done; } - error = show_tree_view(view, tree, commit_id, repo); + error = open_tree_view(view, tree, commit_id, repo); + if (error) + goto done; + error = show_tree_view(view); + close_tree_view(view); view_close(view); done: free(commit_id);