commit - b2f7af546d38b360167a7e30a795ea9f2e91ddf7
commit + 99437157b9e800c9893cc896f72c552613dd0cbd
blob - 0c2e16f0122e7333307b41c59b0e75ded7852697
blob + b0622d7e7922159864c1eb5833a27896e1480bad
--- got/got.c
+++ got/got.c
#include <err.h>
#include <errno.h>
#include <locale.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
+
+static volatile sig_atomic_t sigint_received;
+static volatile sig_atomic_t sigpipe_received;
+
+static void
+catch_sigint(int signo)
+{
+ sigint_received = 1;
+}
+
+static void
+catch_sigpipe(int signo)
+{
+ sigpipe_received = 1;
+}
+
struct cmd {
const char *cmd_name;
const struct got_error *(*cmd_main)(int, char *[]);
if (argc <= 0)
usage();
+ signal(SIGINT, catch_sigint);
+ signal(SIGPIPE, catch_sigpipe);
+
for (i = 0; i < nitems(got_commands); i++) {
const struct got_error *error;
path++;
printf("A %s/%s\n", worktree_path, path);
+}
+
+static const struct got_error *
+checkout_cancel(void *arg)
+{
+ if (sigint_received || sigpipe_received)
+ return got_error(GOT_ERR_CANCELLED);
+ return NULL;
}
static const struct got_error *
goto done;
error = got_worktree_checkout_files(worktree, head_ref, repo,
- checkout_progress, worktree_path);
+ checkout_progress, worktree_path, checkout_cancel, NULL);
if (error != NULL)
goto done;
blob - 4376f1b7a87bae66bf181b0a5134e50a53b24b93
blob + 1a82e737da3bdb1b65c894d3ba816343eb9e0910
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_ITER_COMPLETED 46
#define GOT_ERR_RANGE 47
#define GOT_ERR_EXPECTED 48 /* for use in regress tests only */
+#define GOT_ERR_CANCELLED 49
static const struct got_error {
int code;
{ GOT_ERR_ITER_COMPLETED,"iteration completed" },
{ GOT_ERR_RANGE, "value out of range" },
{ GOT_ERR_EXPECTED, "expected an error but have no error" },
+ { GOT_ERR_CANCELLED, "operation in progress has been cancelled" },
};
/*
blob - f4b03a494564fac33bc5f2de11b332218ec37eed
blob + 806d598ff338396a2c65dc8d684657dde47f4316
--- include/got_worktree.h
+++ include/got_worktree.h
/* A callback function which is invoked when a path is checked out. */
typedef void (*got_worktree_checkout_cb)(void *, const char *);
+/* A callback function which is invoked at cancellation points.
+ * May return GOT_ERR_CANCELLED to abort the runing operation. */
+typedef const struct got_error *(*got_worktree_cancel_cb)(void *);
+
/*
* Attempt to check out files into a work tree from its associated repository
* and path prefix, and update the work tree's file index accordingly.
*/
const struct got_error *got_worktree_checkout_files(struct got_worktree *,
struct got_reference *, struct got_repository *,
- got_worktree_checkout_cb progress, void *);
+ got_worktree_checkout_cb progress, void *,
+ got_worktree_cancel_cb, void *);
blob - d93818fe53197d1dd8f8e7737b6837d4411b46c6
blob + 20f110b3b35b2536e85df68f177a3d4dde90379c
--- lib/worktree.c
+++ lib/worktree.c
static const struct got_error *
tree_checkout(struct got_worktree *, struct got_fileindex *,
struct got_tree_object *, const char *, struct got_repository *,
- got_worktree_checkout_cb progress_cb, void *progress_arg);
+ got_worktree_checkout_cb progress_cb, void *progress_arg,
+ got_worktree_cancel_cb cancel_cb, void *cancel_arg);
static const struct got_error *
tree_checkout_entry(struct got_worktree *worktree,
struct got_fileindex *fileindex, struct got_tree_entry *te,
const char *parent, struct got_repository *repo,
- got_worktree_checkout_cb progress_cb, void *progress_arg)
+ got_worktree_checkout_cb progress_cb, void *progress_arg,
+ got_worktree_cancel_cb cancel_cb, void *cancel_arg)
{
const struct got_error *err = NULL;
struct got_object *obj = NULL;
if (err)
break;
}
+ /* XXX infinite recursion possible */
err = tree_checkout(worktree, fileindex, tree, path, repo,
- progress_cb, progress_arg);
+ progress_cb, progress_arg, cancel_cb, cancel_arg);
break;
default:
break;
tree_checkout(struct got_worktree *worktree,
struct got_fileindex *fileindex, struct got_tree_object *tree,
const char *path, struct got_repository *repo,
- got_worktree_checkout_cb progress_cb, void *progress_arg)
+ got_worktree_checkout_cb progress_cb, void *progress_arg,
+ got_worktree_cancel_cb cancel_cb, void *cancel_arg)
{
const struct got_error *err = NULL;
const struct got_tree_entries *entries;
entries = got_object_tree_get_entries(tree);
SIMPLEQ_FOREACH(te, &entries->head, entry) {
+ if (cancel_cb) {
+ err = (*cancel_cb)(cancel_arg);
+ if (err)
+ break;
+ }
err = tree_checkout_entry(worktree, fileindex, te, path, repo,
- progress_cb, progress_arg);
+ progress_cb, progress_arg, cancel_cb, cancel_arg);
if (err)
break;
}
const struct got_error *
got_worktree_checkout_files(struct got_worktree *worktree,
struct got_reference *head_ref, struct got_repository *repo,
- got_worktree_checkout_cb progress_cb, void *progress_arg)
+ got_worktree_checkout_cb progress_cb, void *progress_arg,
+ got_worktree_cancel_cb cancel_cb, void *cancel_arg)
{
const struct got_error *err = NULL, *unlockerr;
struct got_object_id *commit_id = NULL;
goto done;
err = tree_checkout(worktree, fileindex, tree, "/", repo,
- progress_cb, progress_arg);
+ progress_cb, progress_arg, cancel_cb, cancel_arg);
if (err)
goto done;
blob - 071331070dc68817f9f11f2dee7249493215e227
blob + d33d70db40ff1313b717c0429c1b3ac7209086d0
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
#include <stdint.h>
#include <imsg.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "got_lib_object_parse.h"
#include "got_lib_privsep.h"
+static volatile sig_atomic_t sigint_received;
+
+static void
+catch_sigint(int signo)
+{
+ sigint_received = 1;
+}
+
int
main(int argc, char *argv[])
{
struct imsgbuf ibuf;
size_t datalen;
+ signal(SIGINT, catch_sigint);
+
imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
#ifndef PROFILE
memset(&imsg_outfd, 0, sizeof(imsg_outfd));
imsg_outfd.fd = -1;
+ if (sigint_received) {
+ err = got_error(GOT_ERR_CANCELLED);
+ break;
+ }
+
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
if (err->code == GOT_ERR_PRIVSEP_PIPE)
close(imsg_outfd.fd);
imsg_free(&imsg);
imsg_free(&imsg_outfd);
- if (err) {
- if (err->code == GOT_ERR_PRIVSEP_PIPE)
- err = NULL;
- else
- got_privsep_send_error(&ibuf, err);
+ if (err)
break;
- }
}
imsg_clear(&ibuf);
- if (err)
+ if (err) {
fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
+ if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE)
+ got_privsep_send_error(&ibuf, err);
+ }
close(GOT_IMSG_FD_CHILD);
return err ? 1 : 0;
}
blob - f6b5435605333d42433c5981a64efdc3cb4b18e6
blob + 56aac6aa18b45fe6f13d9723d5bfbdb18fc6024a
--- libexec/got-read-commit/got-read-commit.c
+++ libexec/got-read-commit/got-read-commit.c
#include <stdint.h>
#include <imsg.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "got_lib_object_parse.h"
#include "got_lib_privsep.h"
+static volatile sig_atomic_t sigint_received;
+
+static void
+catch_sigint(int signo)
+{
+ sigint_received = 1;
+}
+
static const struct got_error *
read_commit_object(struct got_commit_object **commit, struct got_object *obj,
FILE *f)
struct imsgbuf ibuf;
size_t datalen;
+ signal(SIGINT, catch_sigint);
+
imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
#ifndef PROFILE
struct got_imsg_object iobj;
FILE *f = NULL;
struct got_object *obj = NULL;
+
+ if (sigint_received) {
+ err = got_error(GOT_ERR_CANCELLED);
+ break;
+ }
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
imsg_free(&imsg);
if (obj)
got_object_close(obj);
- if (err) {
- if (err->code == GOT_ERR_PRIVSEP_PIPE)
- err = NULL;
- else
- got_privsep_send_error(&ibuf, err);
+ if (err)
break;
- }
}
imsg_clear(&ibuf);
- if (err)
+ if (err) {
fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
+ if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE)
+ got_privsep_send_error(&ibuf, err);
+ }
close(GOT_IMSG_FD_CHILD);
return err ? 1 : 0;
}
blob - baca7732ad9c42e87766cbc54a518a7321fb69ea
blob + 8f4ccd362c7963a8af97740e51adb99adef55a5f
--- libexec/got-read-object/got-read-object.c
+++ libexec/got-read-object/got-read-object.c
#include <stdint.h>
#include <imsg.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GOT_OBJ_TAG_TREE "tree"
#define GOT_OBJ_TAG_BLOB "blob"
+static volatile sig_atomic_t sigint_received;
+
+static void
+catch_sigint(int signo)
+{
+ sigint_received = 1;
+}
+
static const struct got_error *
parse_object_header(struct got_object **obj, char *buf, size_t len)
{
struct imsgbuf ibuf;
size_t datalen;
+ signal(SIGINT, catch_sigint);
+
imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
#ifndef PROFILE
#endif
while (1) {
+ if (sigint_received) {
+ err = got_error(GOT_ERR_CANCELLED);
+ break;
+ }
+
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
if (err->code == GOT_ERR_PRIVSEP_PIPE)
imsg_free(&imsg);
if (obj)
got_object_close(obj);
- if (err) {
- if (err->code == GOT_ERR_PRIVSEP_PIPE)
- err = NULL;
- else
- got_privsep_send_error(&ibuf, err);
+ if (err)
break;
- }
}
imsg_clear(&ibuf);
- if (err)
+ if (err) {
fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
+ if(!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE)
+ got_privsep_send_error(&ibuf, err);
+ }
close(GOT_IMSG_FD_CHILD);
return err ? 1 : 0;
}
blob - 010b14b5519db260c50522b9ffb8d93182af1675
blob + debf11401b6553196d83b1b302a0426e77b030a6
--- libexec/got-read-pack/got-read-pack.c
+++ libexec/got-read-pack/got-read-pack.c
#include <sys/mman.h>
#include <limits.h>
+#include <signal.h>
#include <stdint.h>
#include <imsg.h>
#include <stdio.h>
#include "got_lib_privsep.h"
#include "got_lib_pack.h"
+static volatile sig_atomic_t sigint_received;
+
+static void
+catch_sigint(int signo)
+{
+ sigint_received = 1;
+}
+
static const struct got_error *
object_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
struct got_packidx *packidx, struct got_object_cache *objcache)
//static int attached;
//while (!attached) sleep(1);
+ signal(SIGINT, catch_sigint);
+
imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
err = got_object_cache_init(&objcache, GOT_OBJECT_CACHE_TYPE_OBJ);
while (1) {
imsg.fd = -1;
+
+ if (sigint_received) {
+ err = got_error(GOT_ERR_CANCELLED);
+ break;
+ }
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
if (imsg.fd != -1)
close(imsg.fd);
imsg_free(&imsg);
- if (err) {
- if (err->code == GOT_ERR_PRIVSEP_PIPE)
- err = NULL;
- else
- got_privsep_send_error(&ibuf, err);
+ if (err)
break;
- }
}
if (packidx)
got_pack_close(pack);
got_object_cache_close(&objcache);
imsg_clear(&ibuf);
- if (err)
+ if (err) {
fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
+ if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE)
+ got_privsep_send_error(&ibuf, err);
+ }
close(GOT_IMSG_FD_CHILD);
return err ? 1 : 0;
}
blob - 5abd5641f7bf4ae26e07d409b477b3de8140d6bf
blob + 176d429702fa94a803327cbdae31975f748bf235
--- libexec/got-read-tree/got-read-tree.c
+++ libexec/got-read-tree/got-read-tree.c
#include <stdint.h>
#include <imsg.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "got_lib_object_parse.h"
#include "got_lib_privsep.h"
+static volatile sig_atomic_t sigint_received;
+
+static void
+catch_sigint(int signo)
+{
+ sigint_received = 1;
+}
static const struct got_error *
read_tree_object(struct got_tree_object **tree, struct got_object *obj, FILE *f)
{
struct imsgbuf ibuf;
size_t datalen;
+ signal(SIGINT, catch_sigint);
+
imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
#ifndef PROFILE
struct got_imsg_object iobj;
FILE *f = NULL;
struct got_object *obj = NULL;
+
+ if (sigint_received) {
+ err = got_error(GOT_ERR_CANCELLED);
+ break;
+ }
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
imsg_free(&imsg);
if (obj)
got_object_close(obj);
- if (err) {
- if (err->code == GOT_ERR_PRIVSEP_PIPE)
- err = NULL;
- else
- got_privsep_send_error(&ibuf, err);
+ if (err)
break;
- }
}
imsg_clear(&ibuf);
- if (err)
+ if (err) {
fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
+ if (!sigint_received && err->code != GOT_ERR_PRIVSEP_PIPE)
+ got_privsep_send_error(&ibuf, err);
+ }
close(GOT_IMSG_FD_CHILD);
return err ? 1 : 0;
}
blob - 1b97298bec1b9a653524d535083509cbe7aa0d27
blob + f5e074fbbd708429bf097a89be6a2ad5af0605aa
--- regress/worktree/worktree_test.c
+++ regress/worktree/worktree_test.c
goto done;
err = got_worktree_checkout_files(worktree, head_ref, repo,
- process_cb, NULL);
+ process_cb, NULL, NULL, NULL);
if (err != NULL)
goto done;