commit - ccdddf69864eb9ac5c10c0f5d58b68df1cf26ea1
commit + 99301cec42290cd26b9757c17eaaab5d70781bf1
blob - 07cb22fd98f7b10c110a8a5d0c0627770c5b7e76
blob + 02e203f9626eba60a84658a1f9e7a8d0fb043418
--- include/got_worktree.h
+++ include/got_worktree.h
* Get the state of the work tree. If the work tree's global base commit is
* the tip of the work tree's current branch, and each file in the index is
* based on this same commit, the char out parameter will be
- * GOT_WORKTREE_UPTODATE, else it will be GOT_WORKTREE_OUTOFDATE.
+ * GOT_WORKTREE_STATE_UPTODATE, else it will be GOT_WORKTREE_STATE_OUTOFDATE.
*/
const struct got_error *got_worktree_get_state(char *,
struct got_repository *, struct got_worktree *);
-#define GOT_WORKTREE_UPTODATE '*'
-#define GOT_WORKTREE_OUTOFDATE '~'
+#define GOT_WORKTREE_STATE_UNKNOWN ' '
+#define GOT_WORKTREE_STATE_UPTODATE '*'
+#define GOT_WORKTREE_STATE_OUTOFDATE '~'
/*
* Obtain a parsed representation of this worktree's got.conf file.
blob - 6b14bc178bf5fbc6065088656b0ecae4a8fd2aad
blob + e0c7318204bffd754947e3848dcb9e7b6ad3ae9e
--- lib/worktree.c
+++ lib/worktree.c
if (err)
goto done;
- *state = GOT_WORKTREE_OUTOFDATE;
+ *state = GOT_WORKTREE_STATE_UNKNOWN;
base_id = got_worktree_get_base_commit_id(worktree);
if (got_object_id_cmp(base_id, head_id) == 0) {
err = got_fileindex_for_each_entry_safe(fileindex,
check_mixed_commits, worktree);
if (err == NULL)
- *state = GOT_WORKTREE_UPTODATE;
- else if (err->code == GOT_ERR_MIXED_COMMITS)
+ *state = GOT_WORKTREE_STATE_UPTODATE;
+ else if (err->code == GOT_ERR_MIXED_COMMITS) {
+ *state = GOT_WORKTREE_STATE_OUTOFDATE;
err = NULL;
- }
+ }
+ } else
+ *state = GOT_WORKTREE_STATE_OUTOFDATE;
done:
free(head_id);
blob - d10c8e4e269c29522a88fa8b7f94b5658cacd469
blob + a7c92801a63e2df3de71afd808cde146986b7efc
--- regress/tog/log.sh
+++ regress/tog/log.sh
done
cat <<-EOF >$TOG_TEST_SCRIPT
+ WAIT_FOR_UI wait for log thread to finish
SCREENDUMP
EOF
# check up-to-date base commit marker prefixes base commit log message
cat <<-EOF >$TOG_TEST_SCRIPT
+ WAIT_FOR_UI wait for log thread to finish
SCREENDUMP
EOF
head_id=$(git_show_head "$repo")
cat <<-EOF >$TOG_TEST_SCRIPT
+ WAIT_FOR_UI wait for log thread to finish
SCREENDUMP
EOF
blob - 897b0c14098c0b8440dbdfbedd2bb8c0792e6efb
blob + 1bd75430ffde37cc2e0c9ceb60677641c9813dc3
--- tog/tog.c
+++ tog/tog.c
struct got_repository *repo;
int *pack_fds;
int log_complete;
+ pthread_cond_t log_loaded;
sig_atomic_t *quit;
struct commit_queue_entry **first_displayed_entry;
struct commit_queue_entry **selected_entry;
int limit_match;
regex_t *limit_regex;
struct commit_queue *limit_commits;
+ struct got_worktree *worktree;
+ int need_commit_marker;
};
struct tog_log_view_state {
static const struct got_error *open_log_view(struct tog_view *,
struct got_object_id *, struct got_repository *,
- const char *, const char *, int);
+ const char *, const char *, int, struct got_worktree *);
static const struct got_error * show_log_view(struct tog_view *);
static const struct got_error *input_log_view(struct tog_view **,
struct tog_view *, int);
struct tog_color *tc;
struct got_reflist_head *refs;
+ if (tog_base_commit.id != NULL && tog_base_commit.idx == -1 &&
+ got_object_id_cmp(id, tog_base_commit.id) == 0)
+ tog_base_commit.idx = entry->idx;
+
committer_time = got_object_commit_get_committer_time(commit);
if (gmtime_r(&committer_time, &tm) == NULL)
return got_error_from_errno("gmtime_r");
waddwstr(view->window, wauthor);
col += author_width;
while (col < avail && author_width < author_display_cols + 2) {
- if (tog_base_commit.id != NULL &&
+ if (tog_base_commit.marker != GOT_WORKTREE_STATE_UNKNOWN &&
author_width == marker_column &&
entry->idx == tog_base_commit.idx) {
tc = get_color(&s->colors, TOG_COLOR_COMMIT);
TAILQ_INSERT_TAIL(&a->real_commits->head, entry, entry);
a->real_commits->ncommits++;
- if (tog_base_commit.id != NULL && tog_base_commit.idx == -1 &&
- got_object_id_cmp(&id, tog_base_commit.id) == 0)
- tog_base_commit.idx = entry->idx;
-
if (*a->limiting) {
err = match_commit(&limit_match, &id, commit,
a->limit_regex);
goto done;
err = NULL;
done = 1;
+ a->commits_needed = 0;
} else if (a->commits_needed > 0 && !a->load_all) {
if (*a->limiting) {
if (a->limit_match)
goto done;
}
+ if (a->commits_needed == 0 &&
+ a->need_commit_marker && a->worktree) {
+ errcode = pthread_mutex_unlock(&tog_mutex);
+ if (errcode) {
+ err = got_error_set_errno(errcode,
+ "pthread_mutex_unlock");
+ goto done;
+ }
+ err = got_worktree_get_state(&tog_base_commit.marker,
+ a->repo, a->worktree);
+ if (err)
+ goto done;
+ errcode = pthread_mutex_lock(&tog_mutex);
+ if (errcode) {
+ err = got_error_set_errno(errcode,
+ "pthread_mutex_lock");
+ goto done;
+ }
+ a->need_commit_marker = 0;
+ /*
+ * The main thread did not close this
+ * work tree yet. Close it now.
+ */
+ got_worktree_close(a->worktree);
+ a->worktree = NULL;
+
+ if (*a->quit)
+ done = 1;
+ }
+
if (done)
a->commits_needed = 0;
else {
if (a->commits_needed == 0 && !a->load_all) {
+ if (tog_io.wait_for_ui) {
+ errcode = pthread_cond_signal(
+ &a->log_loaded);
+ if (errcode && err == NULL)
+ err = got_error_set_errno(
+ errcode,
+ "pthread_cond_signal");
+ }
+
errcode = pthread_cond_wait(&a->need_commits,
&tog_mutex);
if (errcode) {
}
}
a->log_complete = 1;
+ if (tog_io.wait_for_ui) {
+ errcode = pthread_cond_signal(&a->log_loaded);
+ if (errcode && err == NULL)
+ err = got_error_set_errno(errcode,
+ "pthread_cond_signal");
+ }
+
errcode = pthread_mutex_unlock(&tog_mutex);
if (errcode)
err = got_error_set_errno(errcode, "pthread_mutex_unlock");
if (err) {
tog_thread_error = 1;
pthread_cond_signal(&a->commit_loaded);
+ if (a->worktree) {
+ got_worktree_close(a->worktree);
+ a->worktree = NULL;
+ }
}
return (void *)err;
}
static const struct got_error *
open_log_view(struct tog_view *view, struct got_object_id *start_id,
struct got_repository *repo, const char *head_ref_name,
- const char *in_repo_path, int log_branches)
+ const char *in_repo_path, int log_branches,
+ struct got_worktree *worktree)
{
const struct got_error *err = NULL;
struct tog_log_view_state *s = &view->state.log;
goto done;
}
+ if (using_mock_io) {
+ int rc;
+
+ rc = pthread_cond_init(&s->thread_args.log_loaded, NULL);
+ if (rc)
+ return got_error_set_errno(rc, "pthread_cond_init");
+ }
+
s->thread_args.commits_needed = view->nlines;
s->thread_args.graph = thread_graph;
s->thread_args.real_commits = &s->real_commits;
s->thread_args.limiting = &s->limit_view;
s->thread_args.limit_regex = &s->limit_regex;
s->thread_args.limit_commits = &s->limit_commits;
+ s->thread_args.worktree = worktree;
+ if (worktree)
+ s->thread_args.need_commit_marker = 1;
done:
if (err) {
if (view->close == NULL)
err = trigger_log_thread(view, 1);
if (err)
return err;
+ if (tog_io.wait_for_ui) {
+ int rc;
+
+ rc = pthread_cond_wait(&s->thread_args.log_loaded,
+ &tog_mutex);
+ if (rc)
+ return got_error_set_errno(rc,
+ "pthread_cond_wait");
+ tog_io.wait_for_ui = 0;
+ }
}
}
if (tog_base_commit.id == NULL)
return got_error_from_errno( "got_object_id_dup");
- tog_base_commit.idx = -1;
-
- return got_worktree_get_state(&tog_base_commit.marker, repo,
- worktree);
+ return NULL;
}
static const struct got_error *
error = got_error_from_errno("view_open");
goto done;
}
- error = open_log_view(view, start_id, repo, head_ref_name,
- in_repo_path, log_branches);
- if (error)
- goto done;
if (worktree) {
error = set_tog_base_commit(repo, worktree);
if (error != NULL)
goto done;
+ }
- /* Release work tree lock. */
- got_worktree_close(worktree);
+ error = open_log_view(view, start_id, repo, head_ref_name,
+ in_repo_path, log_branches, worktree);
+ if (error)
+ goto done;
+
+ if (worktree) {
+ /* The work tree will be closed by the log thread. */
worktree = NULL;
}
if (log_view == NULL)
return got_error_from_errno("view_open");
- err = open_log_view(log_view, id, repo, GOT_REF_HEAD, "", 0);
+ err = open_log_view(log_view, id, repo, GOT_REF_HEAD, "", 0, NULL);
if (err)
view_close(log_view);
else
return err;
err = open_log_view(log_view, s->commit_id, s->repo, s->head_ref_name,
- path, 0);
+ path, 0, NULL);
if (err)
view_close(log_view);
else
}
err = open_log_view(log_view, commit_id, repo,
- got_ref_get_name(re->ref), "", 0);
+ got_ref_get_name(re->ref), "", 0, NULL);
done:
if (err)
view_close(log_view);
tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
}
+ tog_base_commit.idx = -1;
+ tog_base_commit.marker = GOT_WORKTREE_STATE_UNKNOWN;
+
if (cmd == NULL) {
if (argc != 1)
usage(0, 1);