commit 1916c2111fb07adb0485c50211d75a35bcbac452 from: Stefan Sperling date: Mon Mar 11 09:49:09 2024 UTC pass notification config to session process commit - a994c1755a6f17171db0bd9a56efd28f03954949 commit + 1916c2111fb07adb0485c50211d75a35bcbac452 blob - 020795e6496b2f22da447417c67793d1b001f5f6 blob + 4ce0a0931df0eff3514a34017c6e52d0312cac1d --- gotd/gotd.c +++ gotd/gotd.c @@ -532,7 +532,7 @@ start_client_authentication(struct gotd_client *client err = ensure_client_is_not_writing(client); if (err) return err; - repo = gotd_find_repo_by_name(ireq.repo_name, &gotd); + repo = gotd_find_repo_by_name(ireq.repo_name, &gotd.repos); if (repo == NULL) return got_error(GOT_ERR_NOT_GIT_REPO); err = start_auth_child(client, GOTD_AUTH_READ, repo, @@ -544,7 +544,7 @@ start_client_authentication(struct gotd_client *client err = ensure_client_is_not_reading(client); if (err) return err; - repo = gotd_find_repo_by_name(ireq.repo_name, &gotd); + repo = gotd_find_repo_by_name(ireq.repo_name, &gotd.repos); if (repo == NULL) return got_error(GOT_ERR_NOT_GIT_REPO); err = start_auth_child(client, @@ -1286,7 +1286,7 @@ gotd_dispatch_auth_child(int fd, short event, void *ar goto done; } - repo = gotd_find_repo_by_name(client->auth->repo_name, &gotd); + repo = gotd_find_repo_by_name(client->auth->repo_name, &gotd.repos); if (repo == NULL) { err = got_error(GOT_ERR_NOT_GIT_REPO); goto done; @@ -1438,7 +1438,7 @@ gotd_dispatch_client_session(int fd, short event, void struct gotd_repo *repo; const char *name = client->session->repo_name; - repo = gotd_find_repo_by_name(name, &gotd); + repo = gotd_find_repo_by_name(name, &gotd.repos); if (repo != NULL) { enum gotd_procid proc_type; @@ -2184,8 +2184,16 @@ main(int argc, char **argv) apply_unveil_repo_readonly(repo_path, 1); else apply_unveil_repo_readwrite(repo_path); + repo = gotd_find_repo_by_path(repo_path, &gotd); + if (repo == NULL) + fatalx("no repository for path %s", repo_path); session_main(title, repo_path, pack_fds, temp_fds, - &gotd.request_timeout, proc_id); + &gotd.request_timeout, + &repo->notification_refs, + &repo->notification_ref_namespaces, + repo->summarize_notifications, + &repo->notification_targets, + proc_id); /* NOTREACHED */ break; case PROC_REPO_READ: blob - dcc070cb7fdab140e8aa219b04f1423c773bd7b0 blob + 97b77d29898f9e0859f385d519bf8e52600928f0 --- gotd/gotd.h +++ gotd/gotd.h @@ -506,7 +506,7 @@ struct gotd_imsg_notify { }; int parse_config(const char *, enum gotd_procid, struct gotd *); -struct gotd_repo *gotd_find_repo_by_name(const char *, struct gotd *); +struct gotd_repo *gotd_find_repo_by_name(const char *, struct gotd_repolist *); struct gotd_repo *gotd_find_repo_by_path(const char *, struct gotd *); struct gotd_uid_connection_limit *gotd_find_uid_connection_limit( struct gotd_uid_connection_limit *limits, size_t nlimits, uid_t uid); blob - bbb8bc71084a768db3ea5cabaf3053203b4ccfcc blob + d8541cd4c711e5330e5a012fabb0dcc19ef71550 --- gotd/notify.c +++ gotd/notify.c @@ -183,10 +183,7 @@ send_notifications(struct imsg *imsg) if (imsg->fd == -1) return got_error(GOT_ERR_PRIVSEP_NO_FD); - TAILQ_FOREACH(repo, gotd_notify.repos, entry) { - if (strcmp(repo->name, inotify.repo_name) == 0) - break; - } + repo = gotd_find_repo_by_name(inotify.repo_name, gotd_notify.repos); if (repo == NULL) return got_error(GOT_ERR_PRIVSEP_MSG); blob - e6b74faab16c4cb5b6fd21b2629f83b08210a2ed blob + 3b2080734f2ecae8a86ee65092221758aafc2f4a --- gotd/parse.y +++ gotd/parse.y @@ -1653,12 +1653,12 @@ symget(const char *nam) } struct gotd_repo * -gotd_find_repo_by_name(const char *repo_name, struct gotd *gotd) +gotd_find_repo_by_name(const char *repo_name, struct gotd_repolist *repos) { struct gotd_repo *repo; size_t namelen; - TAILQ_FOREACH(repo, &gotd->repos, entry) { + TAILQ_FOREACH(repo, repos, entry) { namelen = strlen(repo->name); if (strncmp(repo->name, repo_name, namelen) != 0) continue; blob - 8e8c38fdba8ea220bb277b5edc26a7f4bffa00f2 blob + 6bad495759fd5455d3e40a25cf588583054b3baa --- gotd/session.c +++ gotd/session.c @@ -64,6 +64,10 @@ static struct gotd_session { struct gotd_imsgev notifier_iev; struct timeval request_timeout; enum gotd_procid proc_id; + struct got_pathlist_head *notification_refs; + struct got_pathlist_head *notification_ref_namespaces; + int summarize_notifications; + struct gotd_notification_targets *notification_targets; } gotd_session; static struct gotd_session_client { @@ -394,6 +398,20 @@ begin_ref_updates(struct gotd_session_client *client, return got_error(GOT_ERR_PRIVSEP_MSG); client->nref_updates = istart.nref_updates; + return NULL; +} + +static const struct got_error * +validate_namespace(const char *namespace) +{ + size_t len = strlen(namespace); + + if (len < 5 || strncmp("refs/", namespace, 5) != 0 || + namespace[len - 1] != '/') { + return got_error_fmt(GOT_ERR_BAD_REF_NAME, + "reference namespace '%s'", namespace); + } + return NULL; } @@ -403,15 +421,50 @@ send_notification(struct got_object_id *old_id, struct { const struct got_error *err = NULL; struct gotd_imsgev *iev = &gotd_session.notifier_iev; + struct got_pathlist_entry *pe; + int fd = -1; if (iev->ibuf.fd == -1) return NULL; /* notifications unused */ + TAILQ_FOREACH(pe, gotd_session.notification_refs, entry) { + const char *refname = pe->path; + if (strcmp(got_ref_get_name(ref), refname) == 0) + break; + } + if (pe == NULL && !TAILQ_EMPTY(gotd_session.notification_refs)) + return NULL; + + TAILQ_FOREACH(pe, gotd_session.notification_ref_namespaces, entry) { + const char *namespace = pe->path; + + err = validate_namespace(namespace); + if (err) + return err; + if (strncmp(namespace, got_ref_get_name(ref), + strlen(namespace)) == 0) + break; + } + if (pe == NULL && + !TAILQ_EMPTY(gotd_session.notification_ref_namespaces)) + return NULL; + + fd = got_opentempfd(); + if (fd == -1) + return got_error_from_errno("got_opentempfd"); + if (old_id == NULL) { + dprintf(fd, "created %s\n", got_ref_get_name(ref)); } else if (new_id == NULL) { + dprintf(fd, "deleted %s\n", got_ref_get_name(ref)); } else { + dprintf(fd, "modified %s\n", got_ref_get_name(ref)); } + /* TODO: send imsg */ + + if (fd != -1 && close(fd) == -1 && err == NULL) + err = got_error_from_errno("close"); return err; } @@ -1572,6 +1625,10 @@ done: void session_main(const char *title, const char *repo_path, int *pack_fds, int *temp_fds, struct timeval *request_timeout, + struct got_pathlist_head *notification_refs, + struct got_pathlist_head *notification_ref_namespaces, + int summarize_notifications, + struct gotd_notification_targets *notification_targets, enum gotd_procid proc_id) { const struct got_error *err = NULL; @@ -1584,6 +1641,10 @@ session_main(const char *title, const char *repo_path, memcpy(&gotd_session.request_timeout, request_timeout, sizeof(gotd_session.request_timeout)); gotd_session.proc_id = proc_id; + gotd_session.notification_refs = notification_refs; + gotd_session.notification_ref_namespaces = notification_ref_namespaces; + gotd_session.summarize_notifications = summarize_notifications; + gotd_session.notification_targets = notification_targets; imsg_init(&gotd_session.notifier_iev.ibuf, -1); blob - de20117ce268c646687a1977e8e0c7086a7fb2d6 blob + f98879f84ca1815ba0e760a8995524e6205f7a7b --- gotd/session.h +++ gotd/session.h @@ -15,4 +15,5 @@ */ void session_main(const char *, const char *, int *, int *, struct timeval *, - enum gotd_procid); + struct got_pathlist_head *, struct got_pathlist_head *, int, + struct gotd_notification_targets *, enum gotd_procid);