reliably switch to next commit in tog diff view; don't lose key presses
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
diff --git a/tog/tog.c b/tog/tog.c
index 2c22a4c..8f47bf4 100644
--- a/tog/tog.c
+++ b/tog/tog.c
@@ -1243,24 +1243,16 @@ scroll_up(struct commit_queue_entry **first_displayed_entry, int maxscroll,
}
static const struct got_error *
-scroll_down(struct commit_queue_entry **first_displayed_entry, int maxscroll,
- struct commit_queue_entry **last_displayed_entry,
- struct commit_queue *commits, int *log_complete, int *commits_needed,
+trigger_log_thread(int load_all, int *commits_needed, int *log_complete,
pthread_cond_t *need_commits)
{
- const struct got_error *err = NULL;
- struct commit_queue_entry *pentry;
- int nscrolled = 0;
+ int errcode;
- if (*last_displayed_entry == NULL)
- return NULL;
+ while (*commits_needed > 0) {
+ if (*log_complete)
+ break;
- pentry = TAILQ_NEXT(*last_displayed_entry, entry);
- if (pentry == NULL && !*log_complete) {
- int errcode;
- if (*commits_needed > 0)
- return NULL;
- (*commits_needed) = maxscroll;
+ /* Wake the log thread. */
errcode = pthread_cond_signal(need_commits);
if (errcode)
return got_error_set_errno(errcode);
@@ -1271,13 +1263,43 @@ scroll_down(struct commit_queue_entry **first_displayed_entry, int maxscroll,
errcode = pthread_mutex_lock(&tog_mutex);
if (errcode)
return got_error_set_errno(errcode);
- if (*commits_needed > 0) {
- /* Thread is not done yet; lose a key press
- * and let the user retry... */
+
+ if (*commits_needed > 0 && !load_all) {
+ /*
+ * Thread is not done yet; lose a key press
+ * and let the user retry... this way the GUI
+ * remains interactive while logging deep paths
+ * with few commits in history.
+ */
return NULL;
}
}
+ return NULL;
+}
+
+static const struct got_error *
+scroll_down(struct commit_queue_entry **first_displayed_entry, int maxscroll,
+ struct commit_queue_entry **last_displayed_entry,
+ struct commit_queue *commits, int *log_complete, int *commits_needed,
+ pthread_cond_t *need_commits)
+{
+ const struct got_error *err = NULL;
+ struct commit_queue_entry *pentry;
+ int nscrolled = 0;
+
+ if (*last_displayed_entry == NULL)
+ return NULL;
+
+ pentry = TAILQ_NEXT(*last_displayed_entry, entry);
+ if (pentry == NULL && !*log_complete) {
+ (*commits_needed) += maxscroll;
+ err = trigger_log_thread(0, commits_needed, log_complete,
+ need_commits);
+ if (err)
+ return err;
+ }
+
do {
pentry = TAILQ_NEXT(*last_displayed_entry, entry);
if (pentry == NULL)
@@ -2281,6 +2303,22 @@ input_diff_view(struct tog_view **new_view, struct tog_view **dead_view,
if (s->log_view == NULL)
break;
ls = &s->log_view->state.log;
+
+ if (ls->thread_args.commits_needed == 0) {
+ ls->thread_args.commits_needed++;
+
+ /* Display "loading..." in log view. */
+ show_log_view(s->log_view);
+ update_panels();
+ doupdate();
+ }
+ err = trigger_log_thread(1 /* load_all */,
+ &ls->thread_args.commits_needed,
+ &ls->thread_args.log_complete,
+ &ls->thread_args.need_commits);
+ if (err)
+ break;
+
err = input_log_view(NULL, NULL, NULL, s->log_view,
KEY_DOWN);
if (err)