diff --git a/docs/tools/forge-cli.md b/docs/tools/forge-cli.md index 63876e89..3aec91ea 100644 --- a/docs/tools/forge-cli.md +++ b/docs/tools/forge-cli.md @@ -1278,7 +1278,7 @@ Get/set this user's watch subscription on a repo, or --list all watched repos ###### **Options:** * `--watch` — Subscribe (watch the repo) -* `--ignore` — Mute (mark ignored) +* `--ignore` — Unsupported: Forgejo's subscription endpoint can't mark a repo ignored without also watching it. Always refuses with an error * `--unwatch` — Unsubscribe (clear watch + ignore) * `--list` — List every repo the current user watches (ignores `[repo]`) diff --git a/hive-forge/src/verbs/subscription.rs b/hive-forge/src/verbs/subscription.rs index 5dabb859..46161cdf 100644 --- a/hive-forge/src/verbs/subscription.rs +++ b/hive-forge/src/verbs/subscription.rs @@ -40,7 +40,26 @@ pub struct Args { /// # Errors /// Propagates transport / non-2xx errors from the Forgejo client calls /// and from `print_json`. +/// Error text for a refused `--ignore`. Forgejo's PUT subscription endpoint +/// takes no body — it always subscribes (watch), with no way to mark a repo +/// ignored without also watching it. The old raw client sent a +/// `{subscribed, ignored}` body which the server ignored, so `--ignore` +/// silently behaved like `--watch` (the opposite of what it promises) +/// instead of failing. Refuse instead of lying about what happened. A free +/// function (rather than inlined in `run`) so it's testable without a real +/// `Client` — the refusal fires before any API call is made. +fn ignore_refusal_message() -> String { + "subscription --ignore is not supported: Forgejo's subscription endpoint \ + has no way to mark a repo ignored without also watching it. Use \ + --unwatch to stop watching, or --watch if muted-but-watched is what \ + you actually want." + .to_owned() +} + pub fn run(client: &Client, args: Args) -> Result<()> { + if args.ignore { + anyhow::bail!(ignore_refusal_message()); + } if args.list { // List every repo the authed user watches, so an agent can audit // its notification firehose and decide what to `--unwatch`. Not @@ -73,21 +92,6 @@ pub fn run(client: &Client, args: Args) -> Result<()> { println!("unsubscribed"); return Ok(()); } - if args.ignore { - // Forgejo's PUT subscription endpoint takes no body — it always - // subscribes (watch), it has no way to mark a repo ignored - // without also watching it. The old raw client sent a - // `{subscribed, ignored}` body which the server ignored, so - // `--ignore` silently behaved like `--watch` (the opposite of - // what it promises) instead of failing. Refuse instead of lying - // about what happened. - anyhow::bail!( - "subscription --ignore is not supported: Forgejo's subscription \ - endpoint has no way to mark a repo ignored without also \ - watching it. Use --unwatch to stop watching, or --watch if \ - muted-but-watched is what you actually want." - ); - } if args.watch { let resp = client .api() @@ -113,3 +117,16 @@ pub fn run(client: &Client, args: Args) -> Result<()> { Err(e) => Err(e.into()), } } + +#[cfg(test)] +mod tests { + use super::ignore_refusal_message; + + #[test] + fn ignore_is_rejected_pointing_at_unwatch() { + let msg = ignore_refusal_message(); + assert!(msg.contains("--unwatch")); + assert!(msg.contains("--watch")); + assert!(msg.contains("not supported")); + } +}