| 1 | use { |
| 2 | crate::{cli::IssueCommand, context::Ctx, ui}, |
| 3 | anyhow::{anyhow, Result}, |
| 4 | sigit_si_api::State, |
| 5 | }; |
| 6 | |
| 7 | pub async fn run(ctx: &Ctx, command: IssueCommand) -> Result<()> { |
| 8 | ctx.require_token()?; |
| 9 | |
| 10 | match command { |
| 11 | IssueCommand::List { repo, state, query } => list(ctx, repo, state, query).await, |
| 12 | IssueCommand::View { number, repo } => view(ctx, number, repo).await, |
| 13 | IssueCommand::Create { title, body, repo } => create(ctx, title, body, repo).await, |
| 14 | IssueCommand::Comment { number, body, repo } => comment(ctx, number, body, repo).await, |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | async fn list(ctx: &Ctx, repo: Option<String>, state: String, query: Option<String>) -> Result<()> { |
| 19 | let slug = ctx.resolve_repo(repo)?; |
| 20 | let state = parse_state(&state)?; |
| 21 | let issues = ctx |
| 22 | .client |
| 23 | .issues(&slug.to_string(), state, query.as_deref()) |
| 24 | .await?; |
| 25 | ui::emit(ctx.json, &issues, |issues| ui::render::issues(issues)) |
| 26 | } |
| 27 | |
| 28 | async fn view(ctx: &Ctx, number: i64, repo: Option<String>) -> Result<()> { |
| 29 | let slug = ctx.resolve_repo(repo)?; |
| 30 | let issue = ctx.client.issue(&slug.to_string(), number).await?; |
| 31 | ui::emit(ctx.json, &issue, ui::render::issue_detail) |
| 32 | } |
| 33 | |
| 34 | async fn create( |
| 35 | ctx: &Ctx, |
| 36 | title: String, |
| 37 | body: Option<String>, |
| 38 | repo: Option<String>, |
| 39 | ) -> Result<()> { |
| 40 | let slug = ctx.resolve_repo(repo)?; |
| 41 | let created = ctx |
| 42 | .client |
| 43 | .create_issue(&slug.to_string(), &title, body.as_deref()) |
| 44 | .await?; |
| 45 | |
| 46 | ui::emit(ctx.json, &created, |created| { |
| 47 | ui::success(format!("Opened issue #{}.", created.number)); |
| 48 | println!(" {}", created.url); |
| 49 | }) |
| 50 | } |
| 51 | |
| 52 | async fn comment(ctx: &Ctx, number: i64, body: String, repo: Option<String>) -> Result<()> { |
| 53 | let slug = ctx.resolve_repo(repo)?; |
| 54 | let comment = ctx |
| 55 | .client |
| 56 | .add_comment(&slug.to_string(), number, &body) |
| 57 | .await?; |
| 58 | ui::emit(ctx.json, &comment, |comment| { |
| 59 | ui::success(format!("Commented on #{number}.")); |
| 60 | println!(" {}", comment.url); |
| 61 | }) |
| 62 | } |
| 63 | |
| 64 | fn parse_state(input: &str) -> Result<State> { |
| 65 | match input.to_ascii_lowercase().as_str() { |
| 66 | "open" => Ok(State::Open), |
| 67 | "closed" => Ok(State::Closed), |
| 68 | "all" => Ok(State::All), |
| 69 | other => Err(anyhow!( |
| 70 | "Unknown state {other:?}. Expected one of: open, closed, all." |
| 71 | )), |
| 72 | } |
| 73 | } |