From 0351f3f9c3ddb1545f324f6902848e3abf6c3ce3 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 7 Apr 2021 20:28:23 +0200 Subject: Add CLI interface for project(s) Signed-off-by: Matthias Beyer --- src/cli.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) diff --git a/src/cli.rs b/src/cli.rs index 6fa6a23..e3a21c4 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -21,5 +21,115 @@ pub fn app<'a, 'b>() -> App<'a, 'b> { .help("Get problems for a repo REPO") ) ) + + .subcommand(App::new("project") + .version(crate_version!()) + .about("Query repology for a project") + + .arg(Arg::with_name("name") + .index(1) + .required(true) + .multiple(false) + .value_name("NAME") + .help("Get the project NAME") + ) + ) + + .subcommand(App::new("projects") + .version(crate_version!()) + .about("Query repology for a project by a certain filter") + + .arg(Arg::with_name("search") + .long("search") + .required(false) + .multiple(false) + .value_name("SEARCH") + .help("project name substring to look for") + ) + .arg(Arg::with_name("maintainer") + .long("maintainer") + .required(false) + .multiple(false) + .takes_value(true) + .value_name("MAINTAINER") + .help("return projects maintainer by specified person") + ) + .arg(Arg::with_name("category") + .long("category") + .required(false) + .multiple(false) + .takes_value(true) + .value_name("CATEGORY") + .help("return projects with specified category") + ) + .arg(Arg::with_name("in_repo_filter") + .long("in-repo") + .required(false) + .multiple(false) + .takes_value(true) + .value_name("REPO") + .help("return projects present in specified repository") + ) + .arg(Arg::with_name("not_in_repo_filter") + .long("not-in-repo") + .required(false) + .multiple(false) + .takes_value(true) + .value_name("REPO") + .help("return projects absent in specified repository") + ) + .arg(Arg::with_name("repos_filter") + .long("repos") + .required(false) + .multiple(false) + .takes_value(true) + .value_name("N") + .help("return projects present in specified number of repositories (exact values and open/closed ranges are allowed, e.g. 1, 5-, -5, 2-7") + ) + .arg(Arg::with_name("families_filter") + .long("families") + .required(false) + .multiple(false) + .takes_value(true) + .value_name("FAMS") + .help("return projects present in specified number of repository families (for instance, use 1 to get unique projects)") + ) + .arg(Arg::with_name("repos_newest") + .long("newest-repos") + .required(false) + .multiple(false) + .takes_value(false) + .help("return projects which are up to date in specified number of repositories") + ) + .arg(Arg::with_name("families_newest") + .long("newest-families") + .required(false) + .multiple(false) + .value_name("") + .takes_value(false) + .help("return projects which are up to date in specified number of repository families") + ) + .arg(Arg::with_name("newest") + .long("newest") + .required(false) + .multiple(false) + .takes_value(false) + .help("return newest projects only") + ) + .arg(Arg::with_name("outdated") + .long("outdated") + .required(false) + .multiple(false) + .takes_value(false) + .help("return outdated projects only") + ) + .arg(Arg::with_name("problematic") + .long("problematic") + .required(false) + .multiple(false) + .takes_value(false) + .help("return problematic projects only") + ) + ) } diff --git a/src/main.rs b/src/main.rs index e0455ca..84a60a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use anyhow::anyhow; +use anyhow::Error; use anyhow::Result; use clap::ArgMatches; use result_inspect::*; @@ -16,6 +17,9 @@ async fn main() -> Result<()> { match app.get_matches().subcommand() { ("problems", Some(mtch)) => problems(mtch).await, + ("projects", Some(mtch)) => projects(mtch).await, + ("project", Some(mtch)) => project(mtch).await, + ("repo", Some(mtch)) => problems(mtch).await, (other, _) => Err(anyhow!("No such subcommand: {}", other)), } } @@ -36,3 +40,82 @@ async fn problems<'a>(matches: &ArgMatches<'a>) -> Result<()> { Ok(()) } + +async fn projects<'a>(matches: &ArgMatches<'a>) -> Result<()> { + trait FromCliArg: Sized { + fn from_cli_arg(arg: &str) -> Result; + } + + impl FromCliArg for String { + fn from_cli_arg(arg: &str) -> Result { + Ok(String::from(arg)) + } + } + + impl FromCliArg for usize { + fn from_cli_arg(arg: &str) -> Result { + use std::str::FromStr; + usize::from_str(arg).map_err(Error::from) + } + } + + impl FromCliArg for bool { + fn from_cli_arg(arg: &str) -> Result { + use std::str::FromStr; + bool::from_str(arg).map_err(Error::from) + } + } + + impl FromCliArg for librepology::v1::api::NumberOrRange { + fn from_cli_arg(arg: &str) -> Result { + // TODO: Parse arg to NumberOrRange + unimplemented!() + } + } + + fn cliarg<'a, T: FromCliArg>(matches: &ArgMatches<'a>, s: &'static str) -> Result> { + matches.value_of(s).map(FromCliArg::from_cli_arg).transpose() + } + + ApiClient::new::()? + .projects() + .filtered() + .with_search(cliarg(matches, "search")?) + .with_maintainer(cliarg(matches, "maintainer")?) + .with_category(cliarg(matches, "category")?) + .with_in_repo_filter(cliarg(matches, "in_repo_filter")?) + .with_not_in_repo_filter(cliarg(matches, "not_in_repo_filter")?) + .with_repos_filter(cliarg(matches, "repos_filter")?) + .with_families_filter(cliarg(matches, "families_filter")?) + .with_repos_newest(cliarg(matches, "repos_newest")?) + .with_families_newest(cliarg(matches, "families_newest")?) + .with_newest(cliarg(matches, "newest")?) + .with_outdated(cliarg(matches, "outdated")?) + .with_problematic(cliarg(matches, "problematic")?) + .to_request() + .perform() + .await? + .into_iter() + .for_each(|project| { + println!("Project: {:?}", project); + }); + + Ok(()) +} + +async fn project<'a>(matches: &ArgMatches<'a>) -> Result<()> { + let name = matches.value_of("name").map(String::from).unwrap(); // safe by clap + let client = ApiClient::new::()?; + client.projects() + .with_name(name) + .to_request() + .perform() + .await + .inspect(|response| log::debug!("Response: {:?}", response))? + .into_iter() + .for_each(|project| { + println!("Project: {:?}", project); + }); + + Ok(()) +} -- cgit v1.2.3