args-cli 0.1.1

Command-line interface for args
Documentation
use std::io::{self, Write};

use anyhow::{Context, bail};

use args_api::endpoint::list_user_reviews::ListUserReviewsRequest;

use crate::{
    client::ArgsClient,
    config::UserConfig,
    client::GitClient,
    util::review::{get_remote_owner_repo, push_for_review},
};

pub async fn update_review(config: UserConfig, git: &GitClient) -> anyhow::Result<()> {
    // TODO: init client with token from store
    let client = ArgsClient::from_user_config(&config);
    let (owner, repo) = get_remote_owner_repo(git).await?;
    let reviews = client
        .list_user_reviews(
            &config.user_name,
            ListUserReviewsRequest {
                status: Some("in_progress".to_string()),
                owner: Some(owner.clone()),
                repo: Some(repo.clone()),
            },
        )
        .await?;

    if reviews.is_empty() {
        bail!("No reviews found for user '{}'", config.user_name);
    }

    let selected = if reviews.len() == 1 {
        0
    } else {
        println!("Your reviews:");
        for (i, review) in reviews.iter().enumerate() {
            println!(
                "  [{}] #{} {} ({}, {})",
                i + 1,
                review.number,
                review.title,
                review.status,
                review.target_branch,
            );
        }

        print!("Select a review [1-{}]: ", reviews.len());
        io::stdout().flush()?;

        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        let choice: usize = input.trim().parse().context("Invalid selection")?;

        if choice < 1 || choice > reviews.len() {
            bail!("Selection out of range");
        }

        choice - 1
    };

    let review = &reviews[selected];
    let default_branch = git.default_branch().await?;
    git.pull_rebase(&default_branch).await?;
    let result = push_for_review(git, &default_branch, Some(review.number)).await?;

    match result {
        Some(n) => {
            let url = format!(
                "{}/{}/{}/reviews/{}",
                config.args_web_url.trim_end_matches('/'),
                owner,
                repo,
                n
            );
            println!("Review updated: {}", url);
        }
        None => println!("Review updated"),
    }

    Ok(())
}