commit - 1bfa490b48cb2797a16bd26b03503764adfe4b38
commit + e5a0f69f558eebfc5ff9c994a48dc1dda2ba8b86
blob - 93f828ffcee7e333d9552e4cc8a4789ab67f8621
blob + cab4c27a9b5f22859bb24cea712e3fc2fc4a2ad9
--- tog/tog.c
+++ tog/tog.c
FILE *f;
int first_displayed_line;
int last_displayed_line;
+ int eof;
};
struct commit_queue_entry {
int *last_displayed_line;
int *selected_line;
int *quit;
+ int *eof;
};
struct tog_blame_thread_args {
int last_displayed_line;
int selected_line;
int blame_complete;
+ int eof;
+ int done;
pthread_mutex_t mutex;
struct got_object_id_queue blamed_commits;
struct got_object_qid *blamed_commit;
- const char *path;
+ char *path;
struct got_repository *repo;
struct got_object_id *commit_id;
struct tog_blame blame;
};
struct tog_view {
+ TAILQ_ENTRY(tog_view) entry;
WINDOW *window;
PANEL *panel;
int nlines, ncols, begin_y, begin_x;
struct tog_blame_view_state blame;
struct tog_tree_view_state tree;
} state;
+
+ const struct got_error *(*show)(struct tog_view *);
+ const struct got_error *(*input)(struct tog_view **,
+ struct tog_view **, struct tog_view *, int);
+ const struct got_error *(*close)(struct tog_view *);
};
+TAILQ_HEAD(tog_view_list_head, tog_view);
static const struct got_error *open_diff_view(struct tog_view *,
struct got_object *, struct got_object *, struct got_repository *);
static const struct got_error *show_diff_view(struct tog_view *);
-static void close_diff_view(struct tog_view *);
+static const struct got_error *input_diff_view(struct tog_view **,
+ struct tog_view **, struct tog_view *, int);
+static const struct got_error* close_diff_view(struct tog_view *);
+
static const struct got_error *open_log_view(struct tog_view *,
struct got_object_id *, struct got_repository *, const char *);
static const struct got_error * show_log_view(struct tog_view *);
-static void close_log_view(struct tog_view *);
-static const struct got_error *open_blame_view(struct tog_view *, const char *,
+static const struct got_error *input_log_view(struct tog_view **,
+ struct tog_view **, struct tog_view *, int);
+static const struct got_error *close_log_view(struct tog_view *);
+
+static const struct got_error *open_blame_view(struct tog_view *, char *,
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 *input_blame_view(struct tog_view **,
+ struct tog_view **, struct tog_view *, int);
+static const struct got_error *close_blame_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 const struct got_error *input_tree_view(struct tog_view **,
+ struct tog_view **, struct tog_view *, int);
+static const struct got_error *close_tree_view(struct tog_view *);
-static void
+static const struct got_error *
view_close(struct tog_view *view)
{
+ const struct got_error *err = NULL;
+
+ if (view->close)
+ err = view->close(view);
if (view->panel)
del_panel(view->panel);
if (view->window)
delwin(view->window);
free(view);
+ return err;
}
static struct tog_view *
return view;
}
-void
+const struct got_error *
view_show(struct tog_view *view)
{
+ const struct got_error *err;
+
+ err = view->show(view);
+ if (err)
+ return err;
show_panel(view->panel);
update_panels();
+ doupdate();
+
+ return err;
}
const struct got_error *
}
return NULL;
+}
+
+static const struct got_error *
+view_input(struct tog_view **new, struct tog_view **dead, struct tog_view *view)
+{
+ const struct got_error *err = NULL;
+ int ch;
+
+ *new = NULL;
+ *dead = NULL;
+
+ nodelay(stdscr, FALSE);
+ ch = wgetch(view->window);
+ nodelay(stdscr, TRUE);
+ switch (ch) {
+ case ERR:
+ break;
+ case 'q':
+ err = view->input(new, dead, view, ch);
+ *dead = view;
+ break;
+ case KEY_RESIZE:
+ err = view_resize(view);
+ if (err)
+ return err;
+ err = view->input(new, dead, view, ch);
+ break;
+ default:
+ err = view->input(new, dead, view, ch);
+ break;
+ }
+
+ return err;
+}
+
+static const struct got_error *
+view_loop(struct tog_view *view)
+{
+ const struct got_error *err = NULL;
+ struct tog_view_list_head views;
+ struct tog_view *new_view, *dead_view;
+
+ TAILQ_INIT(&views);
+ TAILQ_INSERT_HEAD(&views, view, entry);
+
+ while (!TAILQ_EMPTY(&views)) {
+ err = view_show(view);
+ if (err)
+ break;
+ err = view_input(&new_view, &dead_view, view);
+ if (err)
+ break;
+ if (new_view) {
+ TAILQ_INSERT_TAIL(&views, new_view, entry);
+ view = new_view;
+ }
+ if (dead_view) {
+ TAILQ_REMOVE(&views, dead_view, entry);
+ TAILQ_FOREACH(view, &views, entry) {
+ if (view->parent == dead_view)
+ view->parent = NULL;
+ }
+ if (dead_view->parent)
+ view = dead_view->parent;
+ else
+ view = TAILQ_LAST(&views, tog_view_list_head);
+ err = view_close(dead_view);
+ if (err)
+ goto done;
+ }
+ }
+done:
+ while (!TAILQ_EMPTY(&views)) {
+ view = TAILQ_FIRST(&views);
+ TAILQ_REMOVE(&views, view, entry);
+ view_close(view);
+ }
+ return err;
}
__dead static void
}
update_panels();
- doupdate();
return err;
}
}
static const struct got_error *
-show_commit(struct tog_view *parent_view, struct commit_queue_entry *entry,
- struct got_repository *repo)
+show_commit(struct tog_view **new_view, struct tog_view *parent_view,
+ struct commit_queue_entry *entry, struct got_repository *repo)
{
const struct got_error *err;
struct got_object *obj1 = NULL, *obj2 = NULL;
struct got_object_qid *parent_id;
- struct tog_view *view;
+ struct tog_view *diff_view;
err = got_object_open(&obj2, repo, entry->id);
if (err)
goto done;
}
- view = view_open(0, 0, 0, 0, parent_view, TOG_VIEW_DIFF);
- if (view == NULL) {
+ diff_view = view_open(0, 0, 0, 0, parent_view, TOG_VIEW_DIFF);
+ if (diff_view == NULL) {
err = got_error_from_errno();
goto done;
}
- err = open_diff_view(view, obj1, obj2, repo);
- if (err)
- goto done;
- err = show_diff_view(view);
- close_diff_view(view);
- view_close(view);
- view_show(parent_view);
+ err = open_diff_view(diff_view, obj1, obj2, repo);
+ if (err == NULL)
+ *new_view = diff_view;
done:
if (obj1)
got_object_close(obj1);
}
static const struct got_error *
-browse_commit(struct tog_view *parent_view, struct commit_queue_entry *entry,
- struct got_repository *repo)
+browse_commit(struct tog_view **new_view, struct tog_view *parent_view,
+ struct commit_queue_entry *entry, struct got_repository *repo)
{
const struct got_error *err = NULL;
struct got_tree_object *tree;
- struct tog_view *view;
+ struct tog_view *tree_view;
err = got_object_open_as_tree(&tree, repo, entry->commit->tree_id);
if (err)
return err;
- view = view_open(0, 0, 0, 0, parent_view, TOG_VIEW_TREE);
- if (view == NULL) {
- err = got_error_from_errno();
- goto done;
- }
- err = open_tree_view(view, tree, entry->id, repo);
+ tree_view = view_open(0, 0, 0, 0, parent_view, TOG_VIEW_TREE);
+ if (tree_view == NULL)
+ return got_error_from_errno();
+
+ err = open_tree_view(tree_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:
- got_object_tree_close(tree);
+ got_object_tree_close(tree);
+ else
+ *new_view = tree_view;
return err;
}
TAILQ_FIRST(&s->commits.head);
s->selected_entry = s->first_displayed_entry;
s->repo = repo;
+
+ view->show = show_log_view;
+ view->input = input_log_view;
+ view->close = close_log_view;
done:
free(head_id);
return err;
}
-static void close_log_view(struct tog_view *view)
+static const struct got_error *
+close_log_view(struct tog_view *view)
{
struct tog_log_view_state *s = &view->state.log;
got_commit_graph_close(s->graph);
free_commits(&s->commits);
free(s->in_repo_path);
+ return NULL;
}
static const struct got_error *
show_log_view(struct tog_view *view)
{
- const struct got_error *err = NULL;
- int ch, done = 0;
struct tog_log_view_state *s = &view->state.log;
- view_show(view);
+ return draw_commits(view, &s->last_displayed_entry,
+ &s->selected_entry, s->first_displayed_entry,
+ &s->commits, s->selected, view->nlines, s->graph,
+ s->repo, s->in_repo_path);
+}
- while (!done) {
- err = draw_commits(view, &s->last_displayed_entry,
- &s->selected_entry, s->first_displayed_entry,
- &s->commits, s->selected, view->nlines, s->graph,
- s->repo, s->in_repo_path);
- if (err)
- goto done;
+static const struct got_error *
+input_log_view(struct tog_view **new_view, struct tog_view **dead_view,
+ struct tog_view *view, int ch)
+{
+ const struct got_error *err = NULL;
+ struct tog_log_view_state *s = &view->state.log;
- nodelay(stdscr, FALSE);
- ch = wgetch(view->window);
- nodelay(stdscr, TRUE);
- switch (ch) {
- case ERR:
+ switch (ch) {
+ case 'k':
+ case KEY_UP:
+ if (s->selected > 0)
+ s->selected--;
+ if (s->selected > 0)
break;
- case 'q':
- done = 1;
+ scroll_up(&s->first_displayed_entry, 1,
+ &s->commits);
+ break;
+ case KEY_PPAGE:
+ if (TAILQ_FIRST(&s->commits.head) ==
+ s->first_displayed_entry) {
+ s->selected = 0;
break;
- case 'k':
- case KEY_UP:
- if (s->selected > 0)
- s->selected--;
- if (s->selected > 0)
- break;
- scroll_up(&s->first_displayed_entry, 1,
- &s->commits);
+ }
+ scroll_up(&s->first_displayed_entry,
+ view->nlines, &s->commits);
+ break;
+ case 'j':
+ case KEY_DOWN:
+ if (s->selected < MIN(view->nlines - 2,
+ s->commits.ncommits - 1)) {
+ s->selected++;
break;
- case KEY_PPAGE:
- if (TAILQ_FIRST(&s->commits.head) ==
- s->first_displayed_entry) {
- s->selected = 0;
- break;
- }
- scroll_up(&s->first_displayed_entry,
- view->nlines, &s->commits);
- break;
- case 'j':
- case KEY_DOWN:
- if (s->selected < MIN(view->nlines - 2,
- s->commits.ncommits - 1)) {
- s->selected++;
- break;
- }
- err = scroll_down(&s->first_displayed_entry, 1,
- s->last_displayed_entry, &s->commits,
- s->graph, s->repo, s->in_repo_path);
- if (err) {
- if (err->code != GOT_ERR_ITER_COMPLETED)
- goto done;
- err = NULL;
- }
- break;
- case KEY_NPAGE: {
- struct commit_queue_entry *first;
- first = s->first_displayed_entry;
- err = scroll_down(&s->first_displayed_entry,
- view->nlines, s->last_displayed_entry,
- &s->commits, s->graph, s->repo,
- s->in_repo_path);
- if (err == NULL)
- break;
+ }
+ err = scroll_down(&s->first_displayed_entry, 1,
+ s->last_displayed_entry, &s->commits,
+ s->graph, s->repo, s->in_repo_path);
+ if (err) {
if (err->code != GOT_ERR_ITER_COMPLETED)
- goto done;
- if (first == s->first_displayed_entry &&
- s->selected < MIN(view->nlines - 2,
- s->commits.ncommits - 1)) {
- /* can't scroll further down */
- s->selected = MIN(view->nlines - 2,
- s->commits.ncommits - 1);
- }
+ break;
err = NULL;
- break;
}
- case KEY_RESIZE:
- err = view_resize(view);
- if (err)
- goto done;
- if (s->selected > view->nlines - 2)
- s->selected = view->nlines - 2;
- if (s->selected > s->commits.ncommits - 1)
- s->selected = s->commits.ncommits - 1;
+ break;
+ case KEY_NPAGE: {
+ struct commit_queue_entry *first;
+ first = s->first_displayed_entry;
+ err = scroll_down(&s->first_displayed_entry,
+ view->nlines, s->last_displayed_entry,
+ &s->commits, s->graph, s->repo,
+ s->in_repo_path);
+ if (err == NULL)
break;
- case KEY_ENTER:
- case '\r':
- err = show_commit(view, s->selected_entry,
- s->repo);
- if (err)
- goto done;
- view_show(view);
+ if (err->code != GOT_ERR_ITER_COMPLETED)
break;
- case 't':
- err = browse_commit(view, s->selected_entry,
- s->repo);
- if (err)
- goto done;
- view_show(view);
- break;
- default:
- break;
+ if (first == s->first_displayed_entry &&
+ s->selected < MIN(view->nlines - 2,
+ s->commits.ncommits - 1)) {
+ /* can't scroll further down */
+ s->selected = MIN(view->nlines - 2,
+ s->commits.ncommits - 1);
+ }
+ err = NULL;
+ break;
}
+ case KEY_RESIZE:
+ if (s->selected > view->nlines - 2)
+ s->selected = view->nlines - 2;
+ if (s->selected > s->commits.ncommits - 1)
+ s->selected = s->commits.ncommits - 1;
+ break;
+ case KEY_ENTER:
+ case '\r':
+ err = show_commit(new_view, view, s->selected_entry,
+ s->repo);
+ break;
+ case 't':
+ err = browse_commit(new_view, view, s->selected_entry,
+ s->repo);
+ break;
+ default:
+ break;
}
-done:
+
return err;
}
error = open_log_view(view, start_id, repo, path);
if (error)
goto done;
- error = show_log_view(view);
- close_log_view(view);
- view_close(view);
+ error = view_loop(view);
done:
free(repo_path);
free(cwd);
*last_displayed_line = nlines;
update_panels();
- doupdate();
return NULL;
}
view->state.diff.first_displayed_line = 1;
view->state.diff.last_displayed_line = view->nlines;
+ view->show = show_diff_view;
+ view->input = input_diff_view;
+ view->close = close_diff_view;
+
return NULL;
}
-static void
+static const struct got_error *
close_diff_view(struct tog_view *view)
{
- fclose(view->state.diff.f);
+ const struct got_error *err = NULL;
+
+ if (view->state.diff.f && fclose(view->state.diff.f) == EOF)
+ err = got_error_from_errno();
+
+ return err;
}
static const struct got_error *
show_diff_view(struct tog_view *view)
{
- const struct got_error *err = NULL;
- int ch, done = 0;
- int eof, i;
struct tog_diff_view_state *s = &view->state.diff;
- view_show(view);
+ return draw_file(view, s->f, &s->first_displayed_line,
+ &s->last_displayed_line, &s->eof, view->nlines);
+}
- while (!done) {
- err = draw_file(view, s->f, &s->first_displayed_line,
- &s->last_displayed_line, &eof, view->nlines);
- if (err)
+static const struct got_error *
+input_diff_view(struct tog_view **new, struct tog_view **dead,
+ struct tog_view *view, int ch)
+{
+ struct tog_diff_view_state *s = &view->state.diff;
+ int i;
+
+ switch (ch) {
+ case 'k':
+ case KEY_UP:
+ if (s->first_displayed_line > 1)
+ s->first_displayed_line--;
break;
- nodelay(stdscr, FALSE);
- ch = wgetch(view->window);
- nodelay(stdscr, TRUE);
- switch (ch) {
- case 'q':
- done = 1;
- break;
- case 'k':
- case KEY_UP:
- if (s->first_displayed_line > 1)
- s->first_displayed_line--;
- break;
- case KEY_PPAGE:
- case KEY_BACKSPACE:
- i = 0;
- while (i++ < view->nlines - 1 &&
- s->first_displayed_line > 1)
- s->first_displayed_line--;
- break;
- case 'j':
- case KEY_DOWN:
- if (!eof)
- s->first_displayed_line++;
- break;
- case KEY_NPAGE:
- case ' ':
- i = 0;
- while (!eof && i++ < view->nlines - 1) {
- char *line;
- line = parse_next_line(s->f, NULL);
- s->first_displayed_line++;
- if (line == NULL)
- break;
- }
- break;
- case KEY_RESIZE:
- err = view_resize(view);
- if (err)
- goto done;
- break;
- default:
- break;
- }
+ case KEY_PPAGE:
+ case KEY_BACKSPACE:
+ i = 0;
+ while (i++ < view->nlines - 1 &&
+ s->first_displayed_line > 1)
+ s->first_displayed_line--;
+ break;
+ case 'j':
+ case KEY_DOWN:
+ if (!s->eof)
+ s->first_displayed_line++;
+ break;
+ case KEY_NPAGE:
+ case ' ':
+ i = 0;
+ while (!s->eof && i++ < view->nlines - 1) {
+ char *line;
+ line = parse_next_line(s->f, NULL);
+ s->first_displayed_line++;
+ if (line == NULL)
+ break;
+ }
+ break;
+ default:
+ break;
}
-done:
- return err;
+
+ return NULL;
}
static const struct got_error *
error = open_diff_view(view, obj1, obj2, repo);
if (error)
goto done;
- error = show_diff_view(view);
- close_diff_view(view);
- view_close(view);
+ error = view_loop(view);
done:
got_repo_close(repo);
if (obj1)
*last_displayed_line = lineno;
update_panels();
- doupdate();
return NULL;
}
const struct got_error *err = NULL;
struct tog_blame_cb_args *a = arg;
struct tog_blame_line *line;
- int eof;
if (nlines != a->nlines ||
(lineno != -1 && lineno < 1) || lineno > a->nlines)
err = draw_blame(a->view, a->commit_id, a->f, a->path,
a->lines, a->nlines, 0, *a->selected_line, a->first_displayed_line,
- a->last_displayed_line, &eof, a->view->nlines);
+ a->last_displayed_line, a->eof, a->view->nlines);
done:
if (pthread_mutex_unlock(a->mutex) != 0)
return got_error_from_errno();
const struct got_error *err;
struct tog_blame_thread_args *ta = arg;
struct tog_blame_cb_args *a = ta->cb_args;
- int eof;
err = got_blame_incremental(ta->path, a->commit_id, ta->repo,
blame_cb, ta->cb_args);
if (!err)
err = draw_blame(a->view, a->commit_id, a->f, a->path,
a->lines, a->nlines, 1, *a->selected_line,
- a->first_displayed_line, a->last_displayed_line, &eof,
+ a->first_displayed_line, a->last_displayed_line, a->eof,
a->view->nlines);
if (pthread_mutex_unlock(a->mutex) != 0 && err == NULL)
run_blame(struct tog_blame *blame, pthread_mutex_t *mutex,
struct tog_view *view, int *blame_complete,
int *first_displayed_line, int *last_displayed_line,
- int *selected_line, int *done, const char *path,
+ int *selected_line, int *done, int *eof, const char *path,
struct got_object_id *commit_id,
struct got_repository *repo)
{
blame->cb_args.selected_line = selected_line;
blame->cb_args.last_displayed_line = last_displayed_line;
blame->cb_args.quit = done;
+ blame->cb_args.eof = eof;
blame->thread_args.path = path;
blame->thread_args.repo = thread_repo;
}
static const struct got_error *
-open_blame_view(struct tog_view *view, const char *path,
+open_blame_view(struct tog_view *view, char *path,
struct got_object_id *commit_id, struct got_repository *repo)
{
const struct got_error *err = NULL;
s->selected_line = 1;
s->blame_complete = 0;
s->path = path;
+ if (s->path == NULL)
+ return got_error_from_errno();
s->repo = repo;
s->commit_id = commit_id;
memset(&s->blame, 0, sizeof(s->blame));
- return NULL;
+ view->show = show_blame_view;
+ view->input = input_blame_view;
+ view->close = close_blame_view;
+
+ return run_blame(&s->blame, &s->mutex, view, &s->blame_complete,
+ &s->first_displayed_line, &s->last_displayed_line,
+ &s->selected_line, &s->done, &s->eof, s->path,
+ s->blamed_commit->id, s->repo);
}
-static void
+static const struct got_error *
close_blame_view(struct tog_view *view)
{
+ const struct got_error *err = NULL;
struct tog_blame_view_state *s = &view->state.blame;
+ if (s->blame.thread)
+ err = stop_blame(&s->blame);
+
while (!SIMPLEQ_EMPTY(&s->blamed_commits)) {
struct got_object_qid *blamed_commit;
blamed_commit = SIMPLEQ_FIRST(&s->blamed_commits);
SIMPLEQ_REMOVE_HEAD(&s->blamed_commits, entry);
got_object_qid_free(blamed_commit);
}
+
+ free(s->path);
+
+ return err;
}
static const struct got_error *
show_blame_view(struct tog_view *view)
{
+ const struct got_error *err = NULL;
+ struct tog_blame_view_state *s = &view->state.blame;
+
+ if (pthread_mutex_lock(&s->mutex) != 0)
+ return got_error_from_errno();
+
+ err = draw_blame(view, s->blamed_commit->id, s->blame.f,
+ s->path, s->blame.lines, s->blame.nlines, s->blame_complete,
+ s->selected_line, &s->first_displayed_line,
+ &s->last_displayed_line, &s->eof, view->nlines);
+
+ if (pthread_mutex_unlock(&s->mutex) != 0 && err == NULL)
+ err = got_error_from_errno();
+
+ return err;
+}
+
+static const struct got_error *
+input_blame_view(struct tog_view **new_view, struct tog_view **dead_view,
+ struct tog_view *view, int ch)
+{
const struct got_error *err = NULL, *thread_err = NULL;
- int ch, done = 0, eof;
struct got_object *obj = NULL, *pobj = NULL;
struct tog_view *diff_view;
struct tog_blame_view_state *s = &view->state.blame;
- view_show(view);
+ if (pthread_mutex_lock(&s->mutex) != 0) {
+ err = got_error_from_errno();
+ goto done;
+ }
- err = run_blame(&s->blame, &s->mutex, view, &s->blame_complete,
- &s->first_displayed_line, &s->last_displayed_line,
- &s->selected_line, &done, s->path, s->blamed_commit->id, s->repo);
- if (err)
- return err;
-
- while (!done) {
- if (pthread_mutex_lock(&s->mutex) != 0) {
- err = got_error_from_errno();
- goto done;
- }
- err = draw_blame(view, s->blamed_commit->id, s->blame.f,
- s->path, s->blame.lines, s->blame.nlines, s->blame_complete,
- s->selected_line, &s->first_displayed_line,
- &s->last_displayed_line, &eof, view->nlines);
- if (pthread_mutex_unlock(&s->mutex) != 0) {
- err = got_error_from_errno();
- goto done;
- }
- if (err)
+ switch (ch) {
+ case 'q':
+ s->done = 1;
+ if (pthread_mutex_unlock(&s->mutex) != 0) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ return stop_blame(&s->blame);
+ case 'k':
+ case KEY_UP:
+ if (s->selected_line > 1)
+ s->selected_line--;
+ else if (s->selected_line == 1 &&
+ s->first_displayed_line > 1)
+ s->first_displayed_line--;
break;
- nodelay(stdscr, FALSE);
- ch = wgetch(view->window);
- nodelay(stdscr, TRUE);
- if (pthread_mutex_lock(&s->mutex) != 0) {
- err = got_error_from_errno();
- goto done;
- }
- switch (ch) {
- case 'q':
- done = 1;
+ case KEY_PPAGE:
+ case KEY_BACKSPACE:
+ if (s->first_displayed_line == 1) {
+ s->selected_line = 1;
break;
- case 'k':
- case KEY_UP:
- if (s->selected_line > 1)
- s->selected_line--;
- else if (s->selected_line == 1 &&
- s->first_displayed_line > 1)
- s->first_displayed_line--;
+ }
+ if (s->first_displayed_line > view->nlines - 2)
+ s->first_displayed_line -=
+ (view->nlines - 2);
+ else
+ s->first_displayed_line = 1;
+ break;
+ case 'j':
+ case KEY_DOWN:
+ if (s->selected_line < view->nlines - 2 &&
+ s->first_displayed_line +
+ s->selected_line <= s->blame.nlines)
+ s->selected_line++;
+ else if (s->last_displayed_line <
+ s->blame.nlines)
+ s->first_displayed_line++;
+ break;
+ case 'b':
+ case 'p': {
+ struct got_object_id *id;
+ id = get_selected_commit_id(s->blame.lines,
+ s->first_displayed_line, s->selected_line);
+ if (id == NULL || got_object_id_cmp(id,
+ s->blamed_commit->id) == 0)
break;
- case KEY_PPAGE:
- case KEY_BACKSPACE:
- if (s->first_displayed_line == 1) {
- s->selected_line = 1;
- break;
- }
- if (s->first_displayed_line > view->nlines - 2)
- s->first_displayed_line -=
- (view->nlines - 2);
- else
- s->first_displayed_line = 1;
+ err = open_selected_commit(&pobj, &obj,
+ s->blame.lines, s->first_displayed_line,
+ s->selected_line, s->repo);
+ if (err)
break;
- case 'j':
- case KEY_DOWN:
- if (s->selected_line < view->nlines - 2 &&
- s->first_displayed_line +
- s->selected_line <= s->blame.nlines)
- s->selected_line++;
- else if (s->last_displayed_line <
- s->blame.nlines)
- s->first_displayed_line++;
+ if (pobj == NULL && obj == NULL)
break;
- case 'b':
- case 'p': {
- struct got_object_id *id;
- id = get_selected_commit_id(s->blame.lines,
- s->first_displayed_line, s->selected_line);
- if (id == NULL || got_object_id_cmp(id,
- s->blamed_commit->id) == 0)
- break;
- err = open_selected_commit(&pobj, &obj,
- s->blame.lines, s->first_displayed_line,
- s->selected_line, s->repo);
- if (err)
- break;
- if (pobj == NULL && obj == NULL)
- break;
- if (ch == 'p' && pobj == NULL)
- break;
- done = 1;
- if (pthread_mutex_unlock(&s->mutex) != 0) {
- err = got_error_from_errno();
- goto done;
- }
- thread_err = stop_blame(&s->blame);
- done = 0;
- if (pthread_mutex_lock(&s->mutex) != 0) {
- err = got_error_from_errno();
- goto done;
- }
- if (thread_err)
- break;
- id = got_object_get_id(ch == 'b' ? obj : pobj);
- got_object_close(obj);
- obj = NULL;
- if (pobj) {
- got_object_close(pobj);
- pobj = NULL;
- }
- if (id == NULL) {
- err = got_error_from_errno();
- break;
- }
- err = got_object_qid_alloc(
- &s->blamed_commit, id);
- free(id);
- if (err)
- goto done;
- SIMPLEQ_INSERT_HEAD(&s->blamed_commits,
- s->blamed_commit, entry);
- err = run_blame(&s->blame, &s->mutex, view,
- &s->blame_complete,
- &s->first_displayed_line,
- &s->last_displayed_line,
- &s->selected_line, &done, s->path,
- s->blamed_commit->id, s->repo);
- if (err)
- break;
+ if (ch == 'p' && pobj == NULL)
break;
+ s->done = 1;
+ if (pthread_mutex_unlock(&s->mutex) != 0) {
+ err = got_error_from_errno();
+ goto done;
}
- case 'B': {
- struct got_object_qid *first;
- first = SIMPLEQ_FIRST(&s->blamed_commits);
- if (!got_object_id_cmp(first->id, s->commit_id))
- break;
- done = 1;
- if (pthread_mutex_unlock(&s->mutex) != 0) {
- err = got_error_from_errno();
- goto done;
- }
- thread_err = stop_blame(&s->blame);
- done = 0;
- if (pthread_mutex_lock(&s->mutex) != 0) {
- err = got_error_from_errno();
- goto done;
- }
- if (thread_err)
- break;
- SIMPLEQ_REMOVE_HEAD(&s->blamed_commits, entry);
- got_object_qid_free(s->blamed_commit);
- s->blamed_commit =
- SIMPLEQ_FIRST(&s->blamed_commits);
- err = run_blame(&s->blame, &s->mutex, view,
- &s->blame_complete,
- &s->first_displayed_line,
- &s->last_displayed_line,
- &s->selected_line, &done, s->path,
- s->blamed_commit->id, s->repo);
- if (err)
- break;
+ thread_err = stop_blame(&s->blame);
+ s->done = 0;
+ if (pthread_mutex_lock(&s->mutex) != 0) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ if (thread_err)
break;
+ id = got_object_get_id(ch == 'b' ? obj : pobj);
+ got_object_close(obj);
+ obj = NULL;
+ if (pobj) {
+ got_object_close(pobj);
+ pobj = NULL;
}
- case KEY_ENTER:
- case '\r':
- err = open_selected_commit(&pobj, &obj,
- s->blame.lines, s->first_displayed_line,
- s->selected_line, s->repo);
- if (err)
- break;
- if (pobj == NULL && obj == NULL)
- break;
- diff_view = view_open(0, 0, 0, 0, view,
- TOG_VIEW_DIFF);
- if (diff_view == NULL) {
- err = got_error_from_errno();
- break;
- }
- err = open_diff_view(diff_view, pobj, obj,
- s->repo);
- if (err)
- break;
- err = show_diff_view(diff_view);
- close_diff_view(diff_view);
- view_close(diff_view);
- if (err)
- break;
- view_show(view);
- if (pobj) {
- got_object_close(pobj);
- pobj = NULL;
- }
- got_object_close(obj);
- obj = NULL;
- if (err)
- break;
+ if (id == NULL) {
+ err = got_error_from_errno();
break;
- case KEY_NPAGE:
- case ' ':
- if (s->last_displayed_line >= s->blame.nlines &&
- s->selected_line < view->nlines - 2) {
- s->selected_line = MIN(s->blame.nlines,
- view->nlines - 2);
- break;
- }
- if (s->last_displayed_line + view->nlines - 2
- <= s->blame.nlines)
- s->first_displayed_line +=
- view->nlines - 2;
- else
- s->first_displayed_line =
- s->blame.nlines -
- (view->nlines - 3);
- break;
- case KEY_RESIZE:
- err = view_resize(view);
- if (err)
- break;
- if (s->selected_line > view->nlines - 2) {
- s->selected_line = MIN(s->blame.nlines,
- view->nlines - 2);
- }
- break;
- default:
+ }
+ err = got_object_qid_alloc(
+ &s->blamed_commit, id);
+ free(id);
+ if (err)
+ goto done;
+ SIMPLEQ_INSERT_HEAD(&s->blamed_commits,
+ s->blamed_commit, entry);
+ err = run_blame(&s->blame, &s->mutex, view,
+ &s->blame_complete,
+ &s->first_displayed_line,
+ &s->last_displayed_line,
+ &s->selected_line, &s->done, &s->eof,
+ s->path, s->blamed_commit->id, s->repo);
+ if (err)
break;
+ break;
}
- if (pthread_mutex_unlock(&s->mutex) != 0)
- err = got_error_from_errno();
- if (err || thread_err)
+ case 'B': {
+ struct got_object_qid *first;
+ first = SIMPLEQ_FIRST(&s->blamed_commits);
+ if (!got_object_id_cmp(first->id, s->commit_id))
+ break;
+ s->done = 1;
+ if (pthread_mutex_unlock(&s->mutex) != 0) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ thread_err = stop_blame(&s->blame);
+ s->done = 0;
+ if (pthread_mutex_lock(&s->mutex) != 0) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ if (thread_err)
+ break;
+ SIMPLEQ_REMOVE_HEAD(&s->blamed_commits, entry);
+ got_object_qid_free(s->blamed_commit);
+ s->blamed_commit =
+ SIMPLEQ_FIRST(&s->blamed_commits);
+ err = run_blame(&s->blame, &s->mutex, view,
+ &s->blame_complete,
+ &s->first_displayed_line,
+ &s->last_displayed_line,
+ &s->selected_line, &s->done, &s->eof, s->path,
+ s->blamed_commit->id, s->repo);
+ if (err)
+ break;
break;
+ }
+ case KEY_ENTER:
+ case '\r':
+ err = open_selected_commit(&pobj, &obj,
+ s->blame.lines, s->first_displayed_line,
+ s->selected_line, s->repo);
+ if (err)
+ break;
+ if (pobj == NULL && obj == NULL)
+ break;
+ diff_view = view_open(0, 0, 0, 0, view,
+ TOG_VIEW_DIFF);
+ if (diff_view == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+ err = open_diff_view(diff_view, pobj, obj,
+ s->repo);
+ if (err) {
+ view_close(diff_view);
+ break;
+ }
+ *new_view = diff_view;
+ if (pobj) {
+ got_object_close(pobj);
+ pobj = NULL;
+ }
+ got_object_close(obj);
+ obj = NULL;
+ if (err)
+ break;
+ break;
+ case KEY_NPAGE:
+ case ' ':
+ if (s->last_displayed_line >= s->blame.nlines &&
+ s->selected_line < view->nlines - 2) {
+ s->selected_line = MIN(s->blame.nlines,
+ view->nlines - 2);
+ break;
+ }
+ if (s->last_displayed_line + view->nlines - 2
+ <= s->blame.nlines)
+ s->first_displayed_line +=
+ view->nlines - 2;
+ else
+ s->first_displayed_line =
+ s->blame.nlines -
+ (view->nlines - 3);
+ break;
+ case KEY_RESIZE:
+ if (s->selected_line > view->nlines - 2) {
+ s->selected_line = MIN(s->blame.nlines,
+ view->nlines - 2);
+ }
+ break;
+ default:
+ break;
}
+
+ if (pthread_mutex_unlock(&s->mutex) != 0)
+ err = got_error_from_errno();
done:
if (pobj)
got_object_close(pobj);
- if (s->blame.thread)
- thread_err = stop_blame(&s->blame);
return thread_err ? thread_err : err;
}
error = open_blame_view(view, in_repo_path, commit_id, repo);
if (error)
goto done;
- error = show_blame_view(view);
- close_blame_view(view);
- view_close(view);
+ error = view_loop(view);
done:
- free(in_repo_path);
free(repo_path);
free(cwd);
free(commit_id);
}
static const struct got_error *
-blame_tree_entry(struct tog_view *parent_view, struct got_tree_entry *te,
- struct tog_parent_trees *parents, struct got_object_id *commit_id,
- struct got_repository *repo)
+blame_tree_entry(struct tog_view **new_view, struct tog_view *parent_view,
+ struct got_tree_entry *te, struct tog_parent_trees *parents,
+ struct got_object_id *commit_id, struct got_repository *repo)
{
const struct got_error *err = NULL;
char *path;
- struct tog_view *view;
+ struct tog_view *blame_view;
err = tree_entry_path(&path, parents, te);
if (err)
return err;
- view = view_open(0, 0, 0, 0, parent_view, TOG_VIEW_BLAME);
- if (view) {
- err = open_blame_view(view, path, commit_id, repo);
- if (err)
- goto done;
- err = show_blame_view(view);
- close_blame_view(view);
- view_close(view);
- } else
- err = got_error_from_errno();
+ blame_view = view_open(0, 0, 0, 0, parent_view, TOG_VIEW_BLAME);
+ if (blame_view == NULL)
+ return got_error_from_errno();
- view_show(parent_view);
-done:
- free(path);
+ err = open_blame_view(blame_view, path, commit_id, repo);
+ if (err) {
+ view_close(blame_view);
+ free(path);
+ } else
+ *new_view = blame_view;
return err;
}
static const struct got_error *
-log_tree_entry(struct tog_view *view, struct got_tree_entry *te,
- struct tog_parent_trees *parents, struct got_object_id *commit_id,
- struct got_repository *repo)
+log_tree_entry(struct tog_view **new_view, struct tog_view *parent_view,
+ struct got_tree_entry *te, struct tog_parent_trees *parents,
+ struct got_object_id *commit_id, struct got_repository *repo)
{
+ struct tog_view *log_view;
const struct got_error *err = NULL;
char *path;
+ log_view = view_open(0, 0, 0, 0, parent_view, TOG_VIEW_LOG);
+ if (log_view == NULL)
+ return got_error_from_errno();
+
err = tree_entry_path(&path, parents, te);
if (err)
return err;
- err = open_log_view(view, commit_id, repo, path);
+ err = open_log_view(log_view, commit_id, repo, path);
if (err)
- goto done;
- err = show_log_view(view);
- close_log_view(view);
-done:
+ view_close(log_view);
+ else
+ *new_view = log_view;
free(path);
return err;
}
s->first_displayed_entry = SIMPLEQ_FIRST(&s->entries->head);
s->commit_id = commit_id;
s->repo = repo;
+
+ view->show = show_tree_view;
+ view->input = input_tree_view;
+ view->close = close_tree_view;
done:
free(commit_id_str);
if (err)
return err;
}
-static void
+static const struct got_error *
close_tree_view(struct tog_view *view)
{
struct tog_tree_view_state *s = &view->state.tree;
}
if (s->tree != s->root)
got_object_tree_close(s->tree);
+ got_object_tree_close(s->root);
+
+ return NULL;
}
static const struct got_error *
{
const struct got_error *err = NULL;
struct tog_tree_view_state *s = &view->state.tree;
- int ch, done = 0;
- int nentries;
+ char *parent_path;
- view_show(view);
+ err = tree_entry_path(&parent_path, &s->parents, NULL);
+ if (err)
+ return err;
- while (!done) {
- char *parent_path;
- s->entries = got_object_tree_get_entries(s->tree);
- nentries = s->entries->nentries;
- if (s->tree != s->root)
- nentries++; /* '..' directory */
+ err = draw_tree_entries(view, &s->first_displayed_entry,
+ &s->last_displayed_entry, &s->selected_entry,
+ &s->ndisplayed, s->tree_label, s->show_ids, parent_path,
+ s->entries, s->selected, view->nlines, s->tree == s->root);
+ free(parent_path);
+ return err;
+}
- err = tree_entry_path(&parent_path, &s->parents, NULL);
- if (err)
- goto done;
+static const struct got_error *
+input_tree_view(struct tog_view **new_view, struct tog_view **dead_view,
+ struct tog_view *view, int ch)
+{
+ const struct got_error *err = NULL;
+ struct tog_tree_view_state *s = &view->state.tree;
- err = draw_tree_entries(view, &s->first_displayed_entry,
- &s->last_displayed_entry, &s->selected_entry,
- &s->ndisplayed, s->tree_label, s->show_ids, parent_path,
- s->entries, s->selected, view->nlines, s->tree == s->root);
- free(parent_path);
- if (err)
+ switch (ch) {
+ case 'i':
+ s->show_ids = !s->show_ids;
break;
-
- nodelay(stdscr, FALSE);
- ch = wgetch(view->window);
- nodelay(stdscr, TRUE);
- switch (ch) {
- case 'q':
- done = 1;
+ case 'l':
+ if (s->selected_entry) {
+ err = log_tree_entry(new_view, view,
+ s->selected_entry, &s->parents,
+ s->commit_id, s->repo);
+ }
+ break;
+ case 'k':
+ case KEY_UP:
+ if (s->selected > 0)
+ s->selected--;
+ if (s->selected > 0)
break;
- case 'i':
- s->show_ids = !s->show_ids;
+ tree_scroll_up(&s->first_displayed_entry, 1,
+ s->entries, s->tree == s->root);
+ break;
+ case KEY_PPAGE:
+ if (SIMPLEQ_FIRST(&s->entries->head) ==
+ s->first_displayed_entry) {
+ if (s->tree != s->root)
+ s->first_displayed_entry = NULL;
+ s->selected = 0;
break;
- case 'l':
- if (s->selected_entry) {
- struct tog_view *log_view;
- log_view = view_open(0, 0, 0, 0, view,
- TOG_VIEW_LOG);
- if (log_view == NULL) {
- err = got_error_from_errno();
- goto done;
- }
- err = log_tree_entry(log_view,
- s->selected_entry, &s->parents,
- s->commit_id, s->repo);
- view_close(log_view);
- view_show(view);
- if (err)
- goto done;
- }
+ }
+ tree_scroll_up(&s->first_displayed_entry,
+ view->nlines, s->entries,
+ s->tree == s->root);
+ break;
+ case 'j':
+ case KEY_DOWN:
+ if (s->selected < s->ndisplayed - 1) {
+ s->selected++;
break;
- case 'k':
- case KEY_UP:
- if (s->selected > 0)
- s->selected--;
- if (s->selected > 0)
- break;
- tree_scroll_up(&s->first_displayed_entry, 1,
- s->entries, s->tree == s->root);
+ }
+ tree_scroll_down(&s->first_displayed_entry, 1,
+ s->last_displayed_entry, s->entries);
+ break;
+ case KEY_NPAGE:
+ tree_scroll_down(&s->first_displayed_entry,
+ view->nlines, s->last_displayed_entry,
+ s->entries);
+ if (SIMPLEQ_NEXT(s->last_displayed_entry,
+ entry))
break;
- case KEY_PPAGE:
- if (SIMPLEQ_FIRST(&s->entries->head) ==
- s->first_displayed_entry) {
- if (s->tree != s->root)
- s->first_displayed_entry = NULL;
- s->selected = 0;
+ /* can't scroll any further; move cursor down */
+ if (s->selected < s->ndisplayed - 1)
+ s->selected = s->ndisplayed - 1;
+ break;
+ case KEY_ENTER:
+ case '\r':
+ if (s->selected_entry == NULL) {
+ struct tog_parent_tree *parent;
+ case KEY_BACKSPACE:
+ /* user selected '..' */
+ if (s->tree == s->root)
break;
- }
- tree_scroll_up(&s->first_displayed_entry,
- view->nlines, s->entries,
- s->tree == s->root);
- break;
- case 'j':
- case KEY_DOWN:
- if (s->selected < s->ndisplayed - 1) {
- s->selected++;
+ parent = TAILQ_FIRST(&s->parents);
+ TAILQ_REMOVE(&s->parents, parent,
+ entry);
+ got_object_tree_close(s->tree);
+ s->tree = parent->tree;
+ s->entries =
+ got_object_tree_get_entries(s->tree);
+ s->first_displayed_entry =
+ parent->first_displayed_entry;
+ s->selected_entry =
+ parent->selected_entry;
+ 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,
+ s->repo, s->selected_entry->id);
+ if (err)
break;
+ parent = calloc(1, sizeof(*parent));
+ if (parent == NULL) {
+ err = got_error_from_errno();
+ break;
}
- tree_scroll_down(&s->first_displayed_entry, 1,
- s->last_displayed_entry, s->entries);
- break;
- case KEY_NPAGE:
- tree_scroll_down(&s->first_displayed_entry,
- view->nlines, s->last_displayed_entry,
- s->entries);
- if (SIMPLEQ_NEXT(s->last_displayed_entry,
- entry))
+ 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)) {
+ err = blame_tree_entry(new_view, view,
+ s->selected_entry, &s->parents,
+ s->commit_id, s->repo);
+ if (err)
break;
- /* can't scroll any further; move cursor down */
- if (s->selected < s->ndisplayed - 1)
- s->selected = s->ndisplayed - 1;
- break;
- case KEY_ENTER:
- case '\r':
- if (s->selected_entry == NULL) {
- struct tog_parent_tree *parent;
- case KEY_BACKSPACE:
- /* user selected '..' */
- if (s->tree == s->root)
- break;
- parent = TAILQ_FIRST(&s->parents);
- TAILQ_REMOVE(&s->parents, parent,
- entry);
- got_object_tree_close(s->tree);
- s->tree = parent->tree;
- s->first_displayed_entry =
- parent->first_displayed_entry;
- s->selected_entry =
- parent->selected_entry;
- 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,
- s->repo, s->selected_entry->id);
- if (err)
- goto done;
- parent = calloc(1, sizeof(*parent));
- if (parent == NULL) {
- err = got_error_from_errno();
- goto done;
- }
- 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->selected = 0;
- s->first_displayed_entry = NULL;
- } else if (S_ISREG(s->selected_entry->mode)) {
- err = blame_tree_entry(view,
- s->selected_entry, &s->parents,
- s->commit_id, s->repo);
- if (err)
- goto done;
- }
- break;
- case KEY_RESIZE:
- err = view_resize(view);
- if (err)
- goto done;
- if (s->selected > view->nlines)
- s->selected = s->ndisplayed - 1;
- break;
- default:
- break;
- }
+ }
+ break;
+ case KEY_RESIZE:
+ if (s->selected > view->nlines)
+ s->selected = s->ndisplayed - 1;
+ break;
+ default:
+ break;
}
-done:
+
return err;
}
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);
+ error = view_loop(view);
done:
free(commit_id);
if (commit)