diff --git a/hive-forge/src/main.rs b/hive-forge/src/main.rs index 1f1885d1..6a7ea892 100644 --- a/hive-forge/src/main.rs +++ b/hive-forge/src/main.rs @@ -199,43 +199,59 @@ fn run() -> Result<()> { let cli = Cli::parse(); let client = client::Client::from_env(cli.repo, cli.json, cli.forge) .context("initialize forge client")?; - match cli.verb { - Verb::View(a) => verbs::view::run(&client, a), - Verb::Issue(a) => verbs::issue_cmd::run(&client, a), - Verb::IssueCreate(a) => verbs::issue_create::run(&client, a), - Verb::IssueEdit(a) => verbs::issue_edit::run(&client, a), - Verb::Pr(a) => verbs::pr_cmd::run(&client, a), - Verb::PrCommits(a) => verbs::pr_commits::run(&client, a), - Verb::PrCreate(a) => verbs::pr_create::run(&client, a), - Verb::Comment(a) => verbs::comment::run(&client, a), - Verb::Comments(a) => verbs::comments::run(&client, a), - Verb::CommentShow(a) => verbs::comment_show::run(&client, a), - Verb::CommentEdit(a) => verbs::comment_edit::run(&client, a), - Verb::Assign(a) => verbs::assign::run(&client, a), - Verb::Close(a) => verbs::close::run(&client, a), - Verb::Labels(a) => verbs::labels::run(&client, a), - Verb::PrStatus(a) => verbs::pr_status::run(&client, a), - Verb::Clone(a) => verbs::clone::run(&client, a), - Verb::RepoCreate(a) => verbs::repo_create::run(&client, a), - Verb::RepoAddCollaborator(a) => verbs::repo_add_collaborator::run(&client, a), - Verb::RepoLabels(a) => verbs::repo_labels::run(&client, a), - Verb::RepoSearch(a) => verbs::repo_search::run(&client, a), - Verb::Lint(a) => verbs::lint::run(&client, a), - Verb::List(a) => verbs::list::run(&client, a), - Verb::Milestone(a) => verbs::milestone::run(&client, a), - Verb::PrMerge(a) => verbs::pr_merge::run(&client, a), - Verb::PrReviews(a) => verbs::pr_reviews::run(&client, a), - Verb::PrAssignReviewer(a) => verbs::pr_assign_reviewer::run(&client, a), - Verb::Branches(a) => verbs::branches::run(&client, a), - Verb::TreeSha(a) => verbs::tree_sha::run(&client, a), - Verb::Diff(a) => verbs::diff::run(&client, a), - Verb::Subscription(a) => verbs::subscription::run(&client, a), - Verb::Timeline(a) => verbs::timeline::run(&client, a), - Verb::AttachIssue(a) => verbs::attach::run_issue(&client, a), - Verb::AttachComment(a) => verbs::attach::run_comment(&client, a), - Verb::AttachmentGet(a) => verbs::attachment_get::run(&client, a), - Verb::ArtifactGet(a) => verbs::artifact_get::run(&client, a), - Verb::CiLog(a) => verbs::ci_log::run(&client, a), - Verb::CiRerun(a) => verbs::ci_rerun::run(&client, a), + // Attach the resolved repo to every verb's error uniformly here, + // rather than threading `.with_context` through 30-odd verb files + // individually. Most verb failures bottom out in `forgejo-api`'s + // `ForgejoError`, which for a body-decode failure (an empty/wrong + // body on a write) carries no status code or URL — see + // `client::check_status`'s doc comment for the raw-route case this + // can't reach. Without the repo in the message, a failure on a + // mistyped `owner/name` (nonexistent org/repo) is indistinguishable + // from a transient flake; this turns "EOF while parsing a value at + // line 1 column 0" into "repo typo-org/repo: EOF while parsing a + // value at line 1 column 0", which is diagnosable on sight. + let repo = client.repo().to_owned(); + dispatch(&client, cli.verb).with_context(|| format!("repo {repo}")) +} + +fn dispatch(client: &client::Client, verb: Verb) -> Result<()> { + match verb { + Verb::View(a) => verbs::view::run(client, a), + Verb::Issue(a) => verbs::issue_cmd::run(client, a), + Verb::IssueCreate(a) => verbs::issue_create::run(client, a), + Verb::IssueEdit(a) => verbs::issue_edit::run(client, a), + Verb::Pr(a) => verbs::pr_cmd::run(client, a), + Verb::PrCommits(a) => verbs::pr_commits::run(client, a), + Verb::PrCreate(a) => verbs::pr_create::run(client, a), + Verb::Comment(a) => verbs::comment::run(client, a), + Verb::Comments(a) => verbs::comments::run(client, a), + Verb::CommentShow(a) => verbs::comment_show::run(client, a), + Verb::CommentEdit(a) => verbs::comment_edit::run(client, a), + Verb::Assign(a) => verbs::assign::run(client, a), + Verb::Close(a) => verbs::close::run(client, a), + Verb::Labels(a) => verbs::labels::run(client, a), + Verb::PrStatus(a) => verbs::pr_status::run(client, a), + Verb::Clone(a) => verbs::clone::run(client, a), + Verb::RepoCreate(a) => verbs::repo_create::run(client, a), + Verb::RepoAddCollaborator(a) => verbs::repo_add_collaborator::run(client, a), + Verb::RepoLabels(a) => verbs::repo_labels::run(client, a), + Verb::RepoSearch(a) => verbs::repo_search::run(client, a), + Verb::Lint(a) => verbs::lint::run(client, a), + Verb::List(a) => verbs::list::run(client, a), + Verb::Milestone(a) => verbs::milestone::run(client, a), + Verb::PrMerge(a) => verbs::pr_merge::run(client, a), + Verb::PrReviews(a) => verbs::pr_reviews::run(client, a), + Verb::PrAssignReviewer(a) => verbs::pr_assign_reviewer::run(client, a), + Verb::Branches(a) => verbs::branches::run(client, a), + Verb::TreeSha(a) => verbs::tree_sha::run(client, a), + Verb::Diff(a) => verbs::diff::run(client, a), + Verb::Subscription(a) => verbs::subscription::run(client, a), + Verb::Timeline(a) => verbs::timeline::run(client, a), + Verb::AttachIssue(a) => verbs::attach::run_issue(client, a), + Verb::AttachComment(a) => verbs::attach::run_comment(client, a), + Verb::AttachmentGet(a) => verbs::attachment_get::run(client, a), + Verb::ArtifactGet(a) => verbs::artifact_get::run(client, a), + Verb::CiLog(a) => verbs::ci_log::run(client, a), + Verb::CiRerun(a) => verbs::ci_rerun::run(client, a), } }