From 1e12021241bc7448acb45456d2c0c4d393d8ae23 Mon Sep 17 00:00:00 2001 From: michal Date: Tue, 14 Jun 2022 00:33:23 +0100 Subject: [PATCH] initial commit for clapv3 --- Cargo.toml | 2 +- src/args.rs | 67 ++++++++++++++++++++ src/main.rs | 129 ++++++++------------------------------- src/operations/build.rs | 32 ++-------- src/operations/mod.rs | 26 ++------ src/operations/pull.rs | 51 ++++++---------- src/repository/config.rs | 21 +++++-- src/repository/mod.rs | 14 +---- src/workspace/mod.rs | 6 +- 9 files changed, 141 insertions(+), 207 deletions(-) create mode 100644 src/args.rs diff --git a/Cargo.toml b/Cargo.toml index f44391b..d8ab345 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ codegen-units = 1 [dependencies] mimalloc = { version = "0.1.27", default-features = false } -clap = { version = "2.34.0", default-features = false } +clap = { version = "3.2.1", features = ["derive", "suggestions"] } toml = { version = "0.5.8", default-features = false } serde = { version = "1.0.134", default-features = false } serde_derive = { version = "1.0.134", default-features = false } diff --git a/src/args.rs b/src/args.rs new file mode 100644 index 0000000..33ef33b --- /dev/null +++ b/src/args.rs @@ -0,0 +1,67 @@ +use clap::{ArgAction, Parser, Subcommand}; + +#[derive(Debug, Clone, Parser)] +#[clap(name="Malachite", version=env!("CARGO_PKG_VERSION"), about=env!("CARGO_PKG_DESCRIPTION"))] +pub struct Args { + #[clap(subcommand)] + pub subcommand: Option, + + /// Sets the level of verbosity + #[clap(long, short, global(true), action=ArgAction::Count)] + pub verbose: u8, + + /// Complete operations without prompting user + #[clap(long="noconfirm", global(true), action=ArgAction::SetTrue)] + pub no_confirm: bool, +} + +#[derive(Debug, Clone, Subcommand)] +pub enum Operation { + /// Builds the given packages + #[clap(name="build", aliases=&["b"])] + Build { + /// The packages to operate on + #[clap(name="package(s)", action=ArgAction::Append, index=1)] + packages: Vec, + + /// Builds all packages in mlc.toml (except if -x is specified) + #[clap(long="all", action=ArgAction::Append, takes_value=true, conflicts_with="package(s)")] + all: bool, + + /// Excludes packages from given operation + #[clap(short='x', long="exclude", action=ArgAction::Append, takes_value=true)] + exclude: Vec, + + /// Does not regenerate repository after building given package(s) + #[clap(short='n', long="no-regen", action=ArgAction::SetTrue)] + no_regen: bool, + }, + + /// Generates repository from built packages + #[clap(name="repo-gen", aliases=&["r"])] + RepoGen, + + /// Prunes duplicate packages from the repository + #[clap(name="prune", aliases=&["p"])] + Prune, + + /// Clones all git repositories from mlc.toml branching from current directory + #[clap(name="init", aliases=&["i"])] + Init, + + /// Pulls in git repositories from mlc.toml branching from current directory + #[clap(name="pull", aliases=&["u"])] + Pull { + /// The packages to operate on + #[clap(name="package(s)", help="The packages to operate on", action=ArgAction::Append, index=1)] + packages: Vec, + + /// Pulls from all git repositories from mlc.toml branching from current directory + #[clap(long="all", action=ArgAction::SetTrue)] + all: bool, + }, + + /// Create and/or open local config file + #[clap(name="config", aliases=&["c"])] + Config, +} diff --git a/src/main.rs b/src/main.rs index ec19823..37a91b6 100755 --- a/src/main.rs +++ b/src/main.rs @@ -2,15 +2,18 @@ use std::env; use std::path::Path; use std::process::Command; +use crate::args::{Args, Operation}; use crate::internal::{crash, info}; use crate::repository::create_config; -use clap::{App, AppSettings, Arg, ArgSettings, SubCommand}; +use clap::Parser; use crate::workspace::read_cfg; #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +mod args; + mod internal; mod operations; mod repository; @@ -25,84 +28,7 @@ fn main() { crash("Running malachite as root is disallowed as it can lead to system breakage. Instead, malachite will prompt you when it needs superuser permissions".to_string(), 1); } - fn build_app() -> App<'static, 'static> { - let app = App::new("Malachite") - .version(env!("CARGO_PKG_VERSION")) - .about(env!("CARGO_PKG_DESCRIPTION")) - .arg( - Arg::with_name("verbose") - .short("v") - .long("verbose") - .multiple(true) - .set(ArgSettings::Global) - .help("Sets the level of verbosity"), - ) - .subcommand( - SubCommand::with_name("build") - .about("Builds the given packages") - .arg( - Arg::with_name("package(s)") - .help("The packages to operate on") - .multiple(true) - .index(1), - ) - .arg( - Arg::with_name("all") - .long("all") - .help("Builds all packages in mlc.toml (except if -x is specified)") - .conflicts_with("package(s)"), - ) - .arg( - Arg::with_name("exclude") - .short("x") - .long("exclude") - .multiple(true) - .takes_value(true) - .help("Excludes packages from given operation"), - ) - .arg( - Arg::with_name("no-regen") - .short("n") - .long("no-regen") - .help("Does not regenerate repository after building given package(s)"), - ), - ) - .subcommand( - SubCommand::with_name("repo-gen").about("Generates repository from built packages"), - ) - .subcommand( - SubCommand::with_name("prune") - .about("Prunes duplicate packages from the repository"), - ) - .subcommand(SubCommand::with_name("init").about( - "Clones all git repositories from mlc.toml branching from current directory", - )) - .subcommand( - SubCommand::with_name("pull") - .alias("update") - .about( - "Pulls all git repositories from mlc.toml branching from current directory", - ) - .arg( - Arg::with_name("package(s)") - .help("The packages to operate on") - .multiple(true) - .index(1), - ), - ) - .subcommand( - SubCommand::with_name("config").about("Create and/or open local config file"), - ) - .settings(&[ - AppSettings::GlobalVersion, - AppSettings::VersionlessSubcommands, - AppSettings::ArgRequiredElseHelp, - AppSettings::InferSubcommands, - ]); - app - } - - let matches = build_app().get_matches(); + let args: Args = Args::parse(); if Path::exists("mlc.toml".as_ref()) && Path::exists(".git".as_ref()) { info( @@ -130,32 +56,25 @@ fn main() { env::set_current_dir(dir).unwrap(); } - if let true = matches.is_present("init") { - operations::init(); - } - - if let true = matches.is_present("build") { - operations::build(&matches); - } - - if let true = matches.is_present("pull") { - operations::pull(&matches); - } - - if let true = matches.is_present("repo-gen") { - let config = read_cfg(); - if config.mode != "repository" { - panic!("Cannot build packages in workspace mode") + match args.subcommand.unwrap_or(Operation::Init) { + Operation::Init => operations::init(), + Operation::Build { + packages, + all, + exclude, + no_regen, + .. + } => operations::build(packages, all, exclude, no_regen), + Operation::Pull { packages, all, .. } => operations::pull(packages, all), + Operation::RepoGen => { + let config = read_cfg(); + if config.mode != "repository" { + panic!("Cannot build packages in workspace mode") + } + info(format!("Generating repository: {}", config.name.unwrap())); + repository::generate(); } - info(format!("Generating repository: {}", config.name.unwrap())); - repository::generate(); - } - - if let true = matches.is_present("prune") { - operations::prune(); - } - - if let true = matches.is_present("config") { - operations::config(); + Operation::Prune => operations::prune(), + Operation::Config => operations::config(), } } diff --git a/src/operations/build.rs b/src/operations/build.rs index af3b32f..8028326 100644 --- a/src/operations/build.rs +++ b/src/operations/build.rs @@ -1,20 +1,8 @@ use crate::repository::generate; use crate::{crash, info, repository, workspace}; -use clap::ArgMatches; -pub fn build(matches: &ArgMatches) { +pub fn build(mut packages: Vec, all: bool, exclude: Vec, no_regen: bool) { let config = workspace::read_cfg(); - let mut packages: Vec = matches - .subcommand_matches("build") - .unwrap() - .values_of_lossy("package(s)") - .unwrap_or_default(); - - let exclude: Vec = matches - .subcommand_matches("build") - .unwrap() - .values_of_lossy("exclude") - .unwrap_or_default(); for pkg in &exclude { packages.retain(|x| x != pkg); @@ -31,11 +19,7 @@ pub fn build(matches: &ArgMatches) { repos.push(a.parse().unwrap()); } - if matches - .subcommand_matches("build") - .unwrap() - .is_present("exclude") - { + if exclude.is_empty() { for ex in exclude { repos.retain(|x| *x != ex); } @@ -54,11 +38,7 @@ pub fn build(matches: &ArgMatches) { } } - if matches - .subcommand_matches("build") - .unwrap() - .is_present("all") - { + if all { for pkg in repos { let code = repository::build(&pkg); if code != 0 { @@ -68,11 +48,7 @@ pub fn build(matches: &ArgMatches) { generate(); } - if !matches - .subcommand_matches("build") - .unwrap() - .is_present("no-regen") - { + if !no_regen { repository::generate(); } diff --git a/src/operations/mod.rs b/src/operations/mod.rs index eee2d4b..f3e1f81 100644 --- a/src/operations/mod.rs +++ b/src/operations/mod.rs @@ -1,27 +1,11 @@ -use clap::ArgMatches; - mod build; mod config; mod init; mod prune; mod pull; -pub fn init() { - init::init(); -} - -pub fn build(matches: &ArgMatches) { - build::build(matches); -} - -pub fn pull(matches: &ArgMatches) { - pull::pull(matches); -} - -pub fn config() { - config::config(); -} - -pub fn prune() { - prune::prune(); -} +pub use build::*; +pub use config::*; +pub use init::*; +pub use prune::*; +pub use pull::*; diff --git a/src/operations/pull.rs b/src/operations/pull.rs index d462b71..5759216 100644 --- a/src/operations/pull.rs +++ b/src/operations/pull.rs @@ -1,47 +1,34 @@ use crate::info; -use clap::ArgMatches; use std::env; use std::process::Command; -pub fn pull(matches: &ArgMatches) { - let packages: Vec = matches - .subcommand_matches("pull") - .unwrap() - .values_of_lossy("package(s)") - .unwrap_or_default(); +fn do_the_pulling(packages: Vec) { + for dir in packages { + let current_dir = env::current_dir().unwrap(); + info(format!("Entering working directory: {}", dir)); + env::set_current_dir(dir).unwrap(); + Command::new("git") + .arg("pull") + .spawn() + .unwrap() + .wait() + .unwrap(); + env::set_current_dir(current_dir).unwrap(); + } +} - if packages.is_empty() { +pub fn pull(packages: Vec, all: bool) { + if all { let stdout = Command::new("ls").arg("-1").output().unwrap().stdout; let dirs_string = String::from_utf8_lossy(&stdout); let mut dirs = dirs_string.lines().collect::>(); dirs.retain(|x| *x != "mlc.toml"); + let dirs_mapped = dirs.iter().map(|x| x.to_string()).collect(); - for dir in dirs { - let cdir = env::current_dir().unwrap(); - info(format!("Entering working directory: {}", dir)); - env::set_current_dir(dir).unwrap(); - Command::new("git") - .arg("pull") - .spawn() - .unwrap() - .wait() - .unwrap(); - env::set_current_dir(cdir).unwrap(); - } + do_the_pulling(dirs_mapped); } else { - for dir in packages { - let cdir = env::current_dir().unwrap(); - info(format!("Entering working directory: {}", dir)); - env::set_current_dir(dir).unwrap(); - Command::new("git") - .arg("pull") - .spawn() - .unwrap() - .wait() - .unwrap(); - env::set_current_dir(cdir).unwrap(); - } + do_the_pulling(packages); } } diff --git a/src/repository/config.rs b/src/repository/config.rs index dab8a1f..c5740c5 100644 --- a/src/repository/config.rs +++ b/src/repository/config.rs @@ -4,10 +4,23 @@ use std::fs::File; use std::io::Write; use std::path::Path; -const DEFAULT_CONFIG: &str = r#"mode = "" # either "repository" or "workspace" -name = "" # only required when in repository mode, decides what to call the repository and relevant files -repo = [""] # an array of git repos to clone from, formatted url_index::repo_name, e.g. if you had urls = [ "https://example.com/%repo%" ], 1::package would expand to https://example.com/package -urls = [""] # an array of urls to clone from, in the format https://example.com/%repo% (the %repo% is NOT optional)"#; +const DEFAULT_CONFIG: &str = r#"# either "repository" or "workspace" +mode = "" + +# only required when in repository mode, decides what to call the repository and relevant files +name = "" + +# an array of git repos to clone from, formatted url_index::repo_name, e.g. if you had urls = [ "https://example.com/%repo%" ], 1::package would expand to https://example.com/package +repo = [ + "", + "" +] + +# an array of urls to clone from, in the format https://example.com/%repo% (the %repo% is NOT optional) +urls = [ + "", + "" +]"#; pub fn create_config() { if env::current_dir() diff --git a/src/repository/mod.rs b/src/repository/mod.rs index e5d3231..0d2ce29 100755 --- a/src/repository/mod.rs +++ b/src/repository/mod.rs @@ -2,14 +2,6 @@ mod config; mod package; mod repo; -pub fn build(pkg: &str) -> i32 { - package::build(pkg) -} - -pub fn generate() { - repo::generate(); -} - -pub fn create_config() { - config::create_config(); -} +pub use config::*; +pub use package::*; +pub use repo::*; diff --git a/src/workspace/mod.rs b/src/workspace/mod.rs index 1b19d47..cd2e912 100755 --- a/src/workspace/mod.rs +++ b/src/workspace/mod.rs @@ -1,7 +1,3 @@ -use crate::internal::structs::Config; - mod read; -pub fn read_cfg() -> Config { - read::read_cfg() -} +pub use read::*;