development
rs 107 lines 3.23 KB
Raw
1 use {
2 crate::{cli::PrCommand, context::Ctx, git, ui},
3 anyhow::{anyhow, Result},
4 sigit_si_api::State,
5 };
6
7 pub async fn run(ctx: &Ctx, command: PrCommand) -> Result<()> {
8 ctx.require_token()?;
9
10 match command {
11 PrCommand::List { repo, state } => list(ctx, repo, state).await,
12 PrCommand::View { number, repo } => view(ctx, number, repo).await,
13 PrCommand::Diff { number, repo } => diff(ctx, number, repo).await,
14 PrCommand::Create {
15 title,
16 head,
17 base,
18 body,
19 repo,
20 } => create(ctx, title, head, base, body, repo).await,
21 PrCommand::Comment { number, body, repo } => comment(ctx, number, body, repo).await,
22 }
23 }
24
25 async fn list(ctx: &Ctx, repo: Option<String>, state: String) -> Result<()> {
26 let slug = ctx.resolve_repo(repo)?;
27 let state = parse_state(&state)?;
28 let pulls = ctx.client.pulls(&slug.to_string(), state).await?;
29 ui::emit(ctx.json, &pulls, |pulls| ui::render::pulls(pulls))
30 }
31
32 async fn view(ctx: &Ctx, number: i64, repo: Option<String>) -> Result<()> {
33 let slug = ctx.resolve_repo(repo)?;
34 let pr = ctx.client.pull(&slug.to_string(), number).await?;
35 ui::emit(ctx.json, &pr, ui::render::pull_detail)
36 }
37
38 async fn diff(ctx: &Ctx, number: i64, repo: Option<String>) -> Result<()> {
39 let slug = ctx.resolve_repo(repo)?;
40 let pr = ctx.client.pull(&slug.to_string(), number).await?;
41
42 match pr.diff {
43 Some(diff) => {
44 print!("{diff}");
45 if let Some(note) = pr.diff_note {
46 ui::note(note);
47 }
48 }
49 None => {
50 ui::note(
51 pr.diff_note
52 .unwrap_or_else(|| "No diff available.".to_string()),
53 );
54 }
55 }
56 Ok(())
57 }
58
59 async fn create(
60 ctx: &Ctx,
61 title: String,
62 head: Option<String>,
63 base: String,
64 body: Option<String>,
65 repo: Option<String>,
66 ) -> Result<()> {
67 let slug = ctx.resolve_repo(repo)?;
68 let head = match head {
69 Some(head) => head,
70 None => git::current_branch(&std::env::current_dir()?)
71 .ok_or_else(|| anyhow!("Could not determine the current branch. Pass --head."))?,
72 };
73
74 let created = ctx
75 .client
76 .create_pull(&slug.to_string(), &title, &head, &base, body.as_deref())
77 .await?;
78
79 ui::emit(ctx.json, &created, |created| {
80 ui::success(format!("Opened pull request #{}.", created.number));
81 println!(" {}", created.url);
82 })
83 }
84
85 async fn comment(ctx: &Ctx, number: i64, body: String, repo: Option<String>) -> Result<()> {
86 let slug = ctx.resolve_repo(repo)?;
87 let comment = ctx
88 .client
89 .add_comment(&slug.to_string(), number, &body)
90 .await?;
91 ui::emit(ctx.json, &comment, |comment| {
92 ui::success(format!("Commented on #{number}."));
93 println!(" {}", comment.url);
94 })
95 }
96
97 fn parse_state(input: &str) -> Result<State> {
98 match input.to_ascii_lowercase().as_str() {
99 "open" => Ok(State::Open),
100 "closed" => Ok(State::Closed),
101 "merged" => Ok(State::Merged),
102 "all" => Ok(State::All),
103 other => Err(anyhow!(
104 "Unknown state {other:?}. Expected one of: open, closed, merged, all."
105 )),
106 }
107 }