Commit Diff


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);