| 998 | } |
| 999 | |
| 1000 | void cbm_watcher_unwatch(cbm_watcher_t *w, const char *project_name) { |
| 1001 | if (!w || !project_name) { |
| 1002 | return; |
| 1003 | } |
| 1004 | bool removed = false; |
| 1005 | cbm_mutex_lock(&w->projects_lock); |
| 1006 | project_state_t *s = cbm_ht_get(w->projects, project_name); |
| 1007 | if (s && defer_state_free(w, s)) { |
| 1008 | /* The entry leaves the table only once its state is safely on |
| 1009 | * the deferred-free list; on OOM the watch stays registered. */ |
| 1010 | atomic_store_explicit(&s->registered, false, memory_order_release); |
| 1011 | if (s->active_git) { |
| 1012 | (void)cbm_subprocess_request_cancel(s->active_git); |
| 1013 | } |
| 1014 | cbm_ht_delete(w->projects, project_name); |
| 1015 | removed = true; |
| 1016 | } |
| 1017 | cbm_mutex_unlock(&w->projects_lock); |
| 1018 | if (removed) { |
| 1019 | cbm_log_info("watcher.unwatch", "project", project_name); |
| 1020 | } |
| 1021 | } |
| 1022 | |
| 1023 | void cbm_watcher_touch(cbm_watcher_t *w, const char *project_name) { |
| 1024 | if (!w || !project_name) { |