commit - 90dfaa0114b254eff2147735ed23dca09b571635
commit + 8285e71aecfd159643f1705f24709fc30a8cbda0
blob - 6e68ff331dae7881c9b5fdd240f869c658aedce6
blob + 2e293cfda482ac271343e8604d92b018614777f7
--- gotd/repo_write.c
+++ gotd/repo_write.c
iev, imsg->fd);
break;
}
+
+ /* TODO send GOTD_IMSG_NOTIFY */
free(refname);
return err;
blob - d62256a1b20427e1dd67b05242a133f23a7ee0ea
blob + 133e70534548d1d8d4987921c6de3a96618c9da2
--- gotd/session.c
+++ gotd/session.c
struct gotd_session_notif {
STAILQ_ENTRY(gotd_session_notif) entry;
+ int fd;
enum gotd_notification_action action;
char *refname;
struct got_object_id old_id;
if (notif == NULL)
return got_error_from_errno("calloc");
+ notif->fd = -1;
+
if (old_id == NULL)
notif->action = GOTD_NOTIF_ACTION_CREATED;
else if (new_id == NULL)
return err;
}
+/*
+ * Forward notification content to the NOTIFY process.
+ * Request additional notifications from REPO_WRITE if any remain queued.
+ */
static const struct got_error *
-send_notification(struct gotd_session_client *client, struct imsg *imsg)
+forward_notification(struct gotd_session_client *client, struct imsg *imsg)
{
const struct got_error *err = NULL;
struct gotd_imsgev *iev = &client->repo_child_iev;
client->nref_updates == 0)
client->flush_disconnect = 1;
free(refname);
+ return err;
+}
+
+/* Request notification content from REPO_WRITE process. */
+static const struct got_error *
+request_notification(struct gotd_session_notif *notif)
+{
+ const struct got_error *err = NULL;
+ struct gotd_session_client *client = &gotd_session_client;
+ struct gotd_imsgev *iev = &client->repo_child_iev;
+ struct gotd_imsg_notification_content icontent;
+ struct ibuf *wbuf;
+ size_t len;
+ int fd;
+
+ fd = got_opentempfd();
+ if (fd == -1)
+ return got_error_from_errno("got_opentemp");
+
+ memset(&icontent, 0, sizeof(icontent));
+ icontent.client_id = client->id;
+
+ icontent.action = notif->action;
+ memcpy(&icontent.old_id, ¬if->old_id, sizeof(notif->old_id));
+ memcpy(&icontent.new_id, ¬if->new_id, sizeof(notif->new_id));
+ icontent.refname_len = strlen(notif->refname);
+
+ len = sizeof(icontent) + icontent.refname_len;
+ wbuf = imsg_create(&iev->ibuf, GOTD_IMSG_NOTIFY,
+ gotd_session.proc_id, gotd_session.pid, len);
+ if (wbuf == NULL) {
+ err = got_error_from_errno("imsg_create NOTIFY");
+ goto done;
+ }
+ if (imsg_add(wbuf, &icontent, sizeof(icontent)) == -1) {
+ err = got_error_from_errno("imsg_add NOTIFY");
+ goto done;
+ }
+ if (imsg_add(wbuf, notif->refname, icontent.refname_len) == -1) {
+ err = got_error_from_errno("imsg_add NOTIFY");
+ goto done;
+ }
+
+ notif->fd = dup(fd);
+ if (notif->fd == -1) {
+ err = got_error_from_errno("dup");
+ goto done;
+ }
+
+ ibuf_fd_set(wbuf, fd);
+ fd = -1;
+
+ imsg_close(&iev->ibuf, wbuf);
+ gotd_imsg_event_add(iev);
+done:
+ if (err && fd != -1)
+ close(fd);
return err;
}
struct got_reference *ref = NULL;
struct gotd_imsg_ref_update iref;
struct got_object_id old_id, new_id;
+ struct gotd_session_notif *notif;
struct got_object_id *id = NULL;
char *refname = NULL;
size_t datalen;
client->nref_updates--;
if (client->nref_updates == 0) {
send_refs_updated(client);
- if (STAILQ_EMPTY(¬ifications))
+ notif = STAILQ_FIRST(¬ifications);
+ if (notif) {
+ err = request_notification(notif);
+ if (err) {
+ /*
+ * Just log a warning.
+ * Notifications are best-effort.
+ */
+ log_warn("could not send notification: "
+ "%s", err->msg);
+ }
+ } else
client->flush_disconnect = 1;
}
err = update_ref(&shut, client,
gotd_session.repo->path, &imsg);
else if (do_notify)
- err = send_notification(client, &imsg);
+ err = forward_notification(client, &imsg);
if (err)
log_warnx("uid %d: %s", client->euid, err->msg);
}
while (!STAILQ_EMPTY(¬ifications)) {
notif = STAILQ_FIRST(¬ifications);
STAILQ_REMOVE_HEAD(¬ifications, entry);
+ if (notif->fd != -1)
+ close(notif->fd);
free(notif->refname);
free(notif);
}