Commit 6fb7cd117fc5150498bd6135a2904a7c726ae49e

Stefan Sperling 2019-08-22T11:33:50

add cancellation support to commit graph and 'got blame'

diff --git a/got/got.c b/got/got.c
index 1242a08..9062a44 100644
--- a/got/got.c
+++ b/got/got.c
@@ -725,7 +725,7 @@ check_linear_ancestry(struct got_object_id *commit_id,
 	struct got_object_id *yca_id;
 
 	err = got_commit_graph_find_youngest_common_ancestor(&yca_id,
-	    commit_id, base_commit_id, repo);
+	    commit_id, base_commit_id, repo, check_cancelled, NULL);
 	if (err)
 		return err;
 
@@ -785,7 +785,8 @@ check_same_branch(struct got_object_id *commit_id,
 	if (err)
 		goto done;
 
-	err = got_commit_graph_iter_start(graph, head_commit_id, repo);
+	err = got_commit_graph_iter_start(graph, head_commit_id, repo,
+	    check_cancelled, NULL);
 	if (err)
 		goto done;
 
@@ -799,7 +800,7 @@ check_same_branch(struct got_object_id *commit_id,
 			} else if (err->code != GOT_ERR_ITER_NEED_MORE)
 				break;
 			err = got_commit_graph_fetch_commits(graph, 1,
-			    repo);
+			    repo, check_cancelled, NULL);
 			if (err)
 				break;
 		}
@@ -1505,7 +1506,8 @@ print_commits(struct got_object_id *root_id, struct got_repository *repo,
 	    first_parent_traversal, repo);
 	if (err)
 		return err;
-	err = got_commit_graph_iter_start(graph, root_id, repo);
+	err = got_commit_graph_iter_start(graph, root_id, repo,
+	    check_cancelled, NULL);
 	if (err)
 		goto done;
 	for (;;) {
@@ -1523,7 +1525,8 @@ print_commits(struct got_object_id *root_id, struct got_repository *repo,
 			}
 			if (err->code != GOT_ERR_ITER_NEED_MORE)
 				break;
-			err = got_commit_graph_fetch_commits(graph, 1, repo);
+			err = got_commit_graph_fetch_commits(graph, 1, repo,
+			    check_cancelled, NULL);
 			if (err)
 				break;
 			else
@@ -2438,7 +2441,8 @@ cmd_blame(int argc, char *argv[])
 	}
 	bca.repo = repo;
 
-	error = got_blame(in_repo_path, commit_id, repo, blame_cb, &bca);
+	error = got_blame(in_repo_path, commit_id, repo, blame_cb, &bca,
+	    check_cancelled, NULL);
 	if (error)
 		goto done;
 done:
@@ -4346,7 +4350,8 @@ collect_commits(struct got_object_id_queue *commits,
 	if (err)
 		return err;
 
-	err = got_commit_graph_iter_start(graph, iter_start_id, repo);
+	err = got_commit_graph_iter_start(graph, iter_start_id, repo,
+	    check_cancelled, NULL);
 	if (err)
 		goto done;
 	while (got_object_id_cmp(commit_id, iter_stop_id) != 0) {
@@ -4360,7 +4365,8 @@ collect_commits(struct got_object_id_queue *commits,
 				goto done;
 			} else if (err->code != GOT_ERR_ITER_NEED_MORE)
 				goto done;
-			err = got_commit_graph_fetch_commits(graph, 1, repo);
+			err = got_commit_graph_fetch_commits(graph, 1, repo,
+			    check_cancelled, NULL);
 			if (err)
 				goto done;
 		} else {
@@ -4514,7 +4520,8 @@ cmd_rebase(int argc, char *argv[])
 
 		base_commit_id = got_worktree_get_base_commit_id(worktree);
 		error = got_commit_graph_find_youngest_common_ancestor(&yca_id,
-		    base_commit_id, branch_head_commit_id, repo);
+		    base_commit_id, branch_head_commit_id, repo,
+		    check_cancelled, NULL);
 		if (error)
 			goto done;
 		if (yca_id == NULL) {
diff --git a/include/got_blame.h b/include/got_blame.h
index 9258c77..c4c15ba 100644
--- a/include/got_blame.h
+++ b/include/got_blame.h
@@ -34,4 +34,4 @@
 const struct got_error *got_blame(const char *,
     struct got_object_id *, struct got_repository *,
     const struct got_error *(*cb)(void *, int, int, struct got_object_id *),
-    void *);
+    void *, got_cancel_cb, void *);
diff --git a/include/got_commit_graph.h b/include/got_commit_graph.h
index 3841e17..488763b 100644
--- a/include/got_commit_graph.h
+++ b/include/got_commit_graph.h
@@ -22,9 +22,11 @@ const struct got_error *got_commit_graph_open(struct got_commit_graph **,
 void got_commit_graph_close(struct got_commit_graph *);
 
 const struct got_error *got_commit_graph_fetch_commits(
-    struct got_commit_graph *, int, struct got_repository *);
+    struct got_commit_graph *, int, struct got_repository *,
+    got_cancel_cb, void *);
 const struct got_error *got_commit_graph_iter_start(
-    struct got_commit_graph *, struct got_object_id *, struct got_repository *);
+    struct got_commit_graph *, struct got_object_id *, struct got_repository *,
+    got_cancel_cb, void *);
 const struct got_error *got_commit_graph_iter_next(struct got_object_id **,
     struct got_commit_graph *);
 const struct got_error *got_commit_graph_intersect(struct got_object_id **,
@@ -34,4 +36,4 @@ const struct got_error *got_commit_graph_intersect(struct got_object_id **,
 /* Find the youngest common ancestor of two commits. */
 const struct got_error *got_commit_graph_find_youngest_common_ancestor(
     struct got_object_id **, struct got_object_id *, struct got_object_id *,
-    struct got_repository *);
+    struct got_repository *, got_cancel_cb, void *);
diff --git a/lib/blame.c b/lib/blame.c
index 6f7839e..a602d0a 100644
--- a/lib/blame.c
+++ b/lib/blame.c
@@ -27,14 +27,15 @@
 
 #include "got_error.h"
 #include "got_object.h"
+#include "got_cancel.h"
 #include "got_blame.h"
+#include "got_commit_graph.h"
 #include "got_opentemp.h"
 
 #include "got_lib_inflate.h"
 #include "got_lib_delta.h"
 #include "got_lib_object.h"
 #include "got_lib_diff.h"
-#include "got_commit_graph.h"
 
 struct got_blame_line {
 	int annotated;
@@ -181,7 +182,7 @@ static const struct got_error *
 blame_open(struct got_blame **blamep, const char *path,
     struct got_object_id *start_commit_id, struct got_repository *repo,
     const struct got_error *(*cb)(void *, int, int, struct got_object_id *),
-    void *arg)
+    void *arg, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err = NULL;
 	struct got_object *obj = NULL;
@@ -238,7 +239,8 @@ blame_open(struct got_blame **blamep, const char *path,
 	err = got_commit_graph_open(&graph, start_commit_id, path, 1, repo);
 	if (err)
 		return err;
-	err = got_commit_graph_iter_start(graph, start_commit_id, repo);
+	err = got_commit_graph_iter_start(graph, start_commit_id, repo,
+	    cancel_cb, cancel_arg);
 	if (err)
 		goto done;
 	id = start_commit_id;
@@ -251,7 +253,8 @@ blame_open(struct got_blame **blamep, const char *path,
 			}
 			if (err->code != GOT_ERR_ITER_NEED_MORE)
 				break;
-			err = got_commit_graph_fetch_commits(graph, 1, repo);
+			err = got_commit_graph_fetch_commits(graph, 1, repo,
+			    cancel_cb, cancel_arg);
 			if (err)
 				break;
 			continue;
@@ -299,7 +302,7 @@ const struct got_error *
 got_blame(const char *path, struct got_object_id *commit_id,
     struct got_repository *repo,
     const struct got_error *(*cb)(void *, int, int, struct got_object_id *),
-    void *arg)
+    void *arg, got_cancel_cb cancel_cb, void* cancel_arg)
 {
 	const struct got_error *err = NULL, *close_err = NULL;
 	struct got_blame *blame;
@@ -308,7 +311,8 @@ got_blame(const char *path, struct got_object_id *commit_id,
 	if (asprintf(&abspath, "%s%s", path[0] == '/' ? "" : "/", path) == -1)
 		return got_error_from_errno2("asprintf", path);
 
-	err = blame_open(&blame, abspath, commit_id, repo, cb, arg);
+	err = blame_open(&blame, abspath, commit_id, repo, cb, arg,
+	    cancel_cb, cancel_arg);
 	free(abspath);
 	if (blame)
 		close_err = blame_close(blame);
diff --git a/lib/commit_graph.c b/lib/commit_graph.c
index 9b907af..51eb773 100644
--- a/lib/commit_graph.c
+++ b/lib/commit_graph.c
@@ -28,6 +28,7 @@
 
 #include "got_error.h"
 #include "got_object.h"
+#include "got_cancel.h"
 #include "got_commit_graph.h"
 #include "got_path.h"
 
@@ -467,7 +468,7 @@ add_branch_tip(struct got_object_id *commit_id, void *data, void *arg)
 static const struct got_error *
 fetch_commits_from_open_branches(int *nfetched,
     struct got_object_id **changed_id, struct got_commit_graph *graph,
-    struct got_repository *repo)
+    struct got_repository *repo, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err;
 	struct add_branch_tip_arg arg;
@@ -506,6 +507,12 @@ fetch_commits_from_open_branches(int *nfetched,
 		struct got_commit_graph_node *new_node;
 		int branch_done, changed;
 
+		if (cancel_cb) {
+			err = (*cancel_cb)(cancel_arg);
+			if (err)
+				break;
+		}
+
 		commit_id = arg.tips[i].commit_id;
 		commit = arg.tips[i].commit;
 		new_node = arg.tips[i].new_node;
@@ -531,15 +538,20 @@ done:
 
 const struct got_error *
 got_commit_graph_fetch_commits(struct got_commit_graph *graph, int limit,
-    struct got_repository *repo)
+    struct got_repository *repo, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err;
 	int nfetched = 0, ncommits;
 	struct got_object_id *changed_id = NULL;
 
 	while (nfetched < limit) {
+		if (cancel_cb) {
+			err = (*cancel_cb)(cancel_arg);
+			if (err)
+				return err;
+		}
 		err = fetch_commits_from_open_branches(&ncommits,
-		    &changed_id, graph, repo);
+		    &changed_id, graph, repo, cancel_cb, cancel_arg);
 		if (err)
 			return err;
 		if (ncommits == 0)
@@ -572,7 +584,8 @@ got_commit_graph_close(struct got_commit_graph *graph)
 
 const struct got_error *
 got_commit_graph_iter_start(struct got_commit_graph *graph,
-    struct got_object_id *id, struct got_repository *repo)
+    struct got_object_id *id, struct got_repository *repo,
+    got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err = NULL;
 	struct got_commit_graph_node *start_node;
@@ -583,7 +596,7 @@ got_commit_graph_iter_start(struct got_commit_graph *graph,
 	while (start_node == NULL) {
 		int ncommits;
 		err = fetch_commits_from_open_branches(&ncommits, NULL, graph,
-		    repo);
+		    repo, cancel_cb, cancel_arg);
 		if (err)
 			return err;
 		if (ncommits == 0)
@@ -608,7 +621,7 @@ got_commit_graph_iter_start(struct got_commit_graph *graph,
 		while (changed_id == NULL) {
 			int ncommits;
 			err = fetch_commits_from_open_branches(&ncommits,
-			    &changed_id, graph, repo);
+			    &changed_id, graph, repo, cancel_cb, cancel_arg);
 			if (err) {
 				got_object_commit_close(commit);
 				return err;
@@ -653,7 +666,7 @@ got_commit_graph_iter_next(struct got_object_id **id,
 const struct got_error *
 got_commit_graph_find_youngest_common_ancestor(struct got_object_id **yca_id,
     struct got_object_id *commit_id, struct got_object_id *commit_id2,
-    struct got_repository *repo)
+    struct got_repository *repo, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err = NULL;
 	struct got_commit_graph *graph = NULL, *graph2 = NULL;
@@ -674,17 +687,25 @@ got_commit_graph_find_youngest_common_ancestor(struct got_object_id **yca_id,
 	if (err)
 		goto done;
 
-	err = got_commit_graph_iter_start(graph, commit_id, repo);
+	err = got_commit_graph_iter_start(graph, commit_id, repo,
+	    cancel_cb, cancel_arg);
 	if (err)
 		goto done;
 
-	err = got_commit_graph_iter_start(graph2, commit_id2, repo);
+	err = got_commit_graph_iter_start(graph2, commit_id2, repo,
+	    cancel_cb, cancel_arg);
 	if (err)
 		goto done;
 
 	for (;;) {
 		struct got_object_id *id, *id2;
 
+		if (cancel_cb) {
+			err = (*cancel_cb)(cancel_arg);
+			if (err)
+				break;
+		}
+
 		if (!completed) {
 			err = got_commit_graph_iter_next(&id, graph);
 			if (err) {
@@ -693,7 +714,7 @@ got_commit_graph_find_youngest_common_ancestor(struct got_object_id **yca_id,
 				else if (err->code != GOT_ERR_ITER_NEED_MORE)
 					break;
 				err = got_commit_graph_fetch_commits(graph, 1,
-				    repo);
+				    repo, cancel_cb, cancel_arg);
 				if (err)
 					break;
 			}
@@ -707,7 +728,7 @@ got_commit_graph_find_youngest_common_ancestor(struct got_object_id **yca_id,
 				else if (err->code != GOT_ERR_ITER_NEED_MORE)
 					break;
 				err = got_commit_graph_fetch_commits(graph2, 1,
-				    repo);
+				    repo, cancel_cb, cancel_arg);
 				if (err)
 					break;
 			}
diff --git a/tog/tog.c b/tog/tog.c
index c92a4d0..c8b1e45 100644
--- a/tog/tog.c
+++ b/tog/tog.c
@@ -45,12 +45,12 @@
 #include "got_repository.h"
 #include "got_diff.h"
 #include "got_opentemp.h"
-#include "got_commit_graph.h"
 #include "got_utf8.h"
+#include "got_cancel.h"
+#include "got_commit_graph.h"
 #include "got_blame.h"
 #include "got_privsep.h"
 #include "got_path.h"
-#include "got_cancel.h"
 #include "got_worktree.h"
 
 #ifndef MIN
@@ -1182,7 +1182,7 @@ queue_commits(struct got_commit_graph *graph, struct commit_queue *commits,
 			if (err->code != GOT_ERR_ITER_NEED_MORE)
 				break;
 			err = got_commit_graph_fetch_commits(graph,
-			    minqueue, repo);
+			    minqueue, repo, NULL, NULL);
 			if (err)
 				return err;
 			continue;
@@ -1637,7 +1637,8 @@ log_thread(void *arg)
 	struct tog_log_thread_args *a = arg;
 	int done = 0;
 
-	err = got_commit_graph_iter_start(a->graph, a->start_id, a->repo);
+	err = got_commit_graph_iter_start(a->graph, a->start_id, a->repo,
+	    NULL, NULL);
 	if (err)
 		return (void *)err;
 
@@ -3137,7 +3138,7 @@ blame_thread(void *arg)
 	int errcode;
 
 	err = got_blame(ta->path, a->commit_id, ta->repo,
-	    blame_cb, ta->cb_args);
+	    blame_cb, ta->cb_args, NULL, NULL);
 
 	errcode = pthread_mutex_lock(&tog_mutex);
 	if (errcode)