initial commit for clapv3

main
michal 2 years ago
parent 1910fc8fdd
commit 1e12021241

@ -18,7 +18,7 @@ codegen-units = 1
[dependencies] [dependencies]
mimalloc = { version = "0.1.27", default-features = false } 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 } toml = { version = "0.5.8", default-features = false }
serde = { version = "1.0.134", default-features = false } serde = { version = "1.0.134", default-features = false }
serde_derive = { version = "1.0.134", default-features = false } serde_derive = { version = "1.0.134", default-features = false }

@ -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<Operation>,
/// 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<String>,
/// 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<String>,
/// 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<String>,
/// 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,
}

@ -2,15 +2,18 @@ use std::env;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use crate::args::{Args, Operation};
use crate::internal::{crash, info}; use crate::internal::{crash, info};
use crate::repository::create_config; use crate::repository::create_config;
use clap::{App, AppSettings, Arg, ArgSettings, SubCommand}; use clap::Parser;
use crate::workspace::read_cfg; use crate::workspace::read_cfg;
#[global_allocator] #[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
mod args;
mod internal; mod internal;
mod operations; mod operations;
mod repository; 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); 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 args: Args = Args::parse();
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();
if Path::exists("mlc.toml".as_ref()) && Path::exists(".git".as_ref()) { if Path::exists("mlc.toml".as_ref()) && Path::exists(".git".as_ref()) {
info( info(
@ -130,32 +56,25 @@ fn main() {
env::set_current_dir(dir).unwrap(); env::set_current_dir(dir).unwrap();
} }
if let true = matches.is_present("init") { match args.subcommand.unwrap_or(Operation::Init) {
operations::init(); Operation::Init => operations::init(),
} Operation::Build {
packages,
if let true = matches.is_present("build") { all,
operations::build(&matches); exclude,
} no_regen,
..
if let true = matches.is_present("pull") { } => operations::build(packages, all, exclude, no_regen),
operations::pull(&matches); Operation::Pull { packages, all, .. } => operations::pull(packages, all),
} Operation::RepoGen => {
let config = read_cfg();
if let true = matches.is_present("repo-gen") { if config.mode != "repository" {
let config = read_cfg(); panic!("Cannot build packages in workspace mode")
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())); Operation::Prune => operations::prune(),
repository::generate(); Operation::Config => operations::config(),
}
if let true = matches.is_present("prune") {
operations::prune();
}
if let true = matches.is_present("config") {
operations::config();
} }
} }

@ -1,20 +1,8 @@
use crate::repository::generate; use crate::repository::generate;
use crate::{crash, info, repository, workspace}; use crate::{crash, info, repository, workspace};
use clap::ArgMatches;
pub fn build(matches: &ArgMatches) { pub fn build(mut packages: Vec<String>, all: bool, exclude: Vec<String>, no_regen: bool) {
let config = workspace::read_cfg(); let config = workspace::read_cfg();
let mut packages: Vec<String> = matches
.subcommand_matches("build")
.unwrap()
.values_of_lossy("package(s)")
.unwrap_or_default();
let exclude: Vec<String> = matches
.subcommand_matches("build")
.unwrap()
.values_of_lossy("exclude")
.unwrap_or_default();
for pkg in &exclude { for pkg in &exclude {
packages.retain(|x| x != pkg); packages.retain(|x| x != pkg);
@ -31,11 +19,7 @@ pub fn build(matches: &ArgMatches) {
repos.push(a.parse().unwrap()); repos.push(a.parse().unwrap());
} }
if matches if exclude.is_empty() {
.subcommand_matches("build")
.unwrap()
.is_present("exclude")
{
for ex in exclude { for ex in exclude {
repos.retain(|x| *x != ex); repos.retain(|x| *x != ex);
} }
@ -54,11 +38,7 @@ pub fn build(matches: &ArgMatches) {
} }
} }
if matches if all {
.subcommand_matches("build")
.unwrap()
.is_present("all")
{
for pkg in repos { for pkg in repos {
let code = repository::build(&pkg); let code = repository::build(&pkg);
if code != 0 { if code != 0 {
@ -68,11 +48,7 @@ pub fn build(matches: &ArgMatches) {
generate(); generate();
} }
if !matches if !no_regen {
.subcommand_matches("build")
.unwrap()
.is_present("no-regen")
{
repository::generate(); repository::generate();
} }

@ -1,27 +1,11 @@
use clap::ArgMatches;
mod build; mod build;
mod config; mod config;
mod init; mod init;
mod prune; mod prune;
mod pull; mod pull;
pub fn init() { pub use build::*;
init::init(); pub use config::*;
} pub use init::*;
pub use prune::*;
pub fn build(matches: &ArgMatches) { pub use pull::*;
build::build(matches);
}
pub fn pull(matches: &ArgMatches) {
pull::pull(matches);
}
pub fn config() {
config::config();
}
pub fn prune() {
prune::prune();
}

@ -1,47 +1,34 @@
use crate::info; use crate::info;
use clap::ArgMatches;
use std::env; use std::env;
use std::process::Command; use std::process::Command;
pub fn pull(matches: &ArgMatches) { fn do_the_pulling(packages: Vec<String>) {
let packages: Vec<String> = matches for dir in packages {
.subcommand_matches("pull") let current_dir = env::current_dir().unwrap();
.unwrap() info(format!("Entering working directory: {}", dir));
.values_of_lossy("package(s)") env::set_current_dir(dir).unwrap();
.unwrap_or_default(); 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<String>, all: bool) {
if all {
let stdout = Command::new("ls").arg("-1").output().unwrap().stdout; let stdout = Command::new("ls").arg("-1").output().unwrap().stdout;
let dirs_string = String::from_utf8_lossy(&stdout); let dirs_string = String::from_utf8_lossy(&stdout);
let mut dirs = dirs_string.lines().collect::<Vec<&str>>(); let mut dirs = dirs_string.lines().collect::<Vec<&str>>();
dirs.retain(|x| *x != "mlc.toml"); dirs.retain(|x| *x != "mlc.toml");
let dirs_mapped = dirs.iter().map(|x| x.to_string()).collect();
for dir in dirs { do_the_pulling(dirs_mapped);
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();
}
} else { } else {
for dir in packages { do_the_pulling(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();
}
} }
} }

@ -4,10 +4,23 @@ use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::Path; use std::path::Path;
const DEFAULT_CONFIG: &str = r#"mode = "" # either "repository" or "workspace" const DEFAULT_CONFIG: &str = r#"# either "repository" or "workspace"
name = "" # only required when in repository mode, decides what to call the repository and relevant files mode = ""
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)"#; # 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() { pub fn create_config() {
if env::current_dir() if env::current_dir()

@ -2,14 +2,6 @@ mod config;
mod package; mod package;
mod repo; mod repo;
pub fn build(pkg: &str) -> i32 { pub use config::*;
package::build(pkg) pub use package::*;
} pub use repo::*;
pub fn generate() {
repo::generate();
}
pub fn create_config() {
config::create_config();
}

@ -1,7 +1,3 @@
use crate::internal::structs::Config;
mod read; mod read;
pub fn read_cfg() -> Config { pub use read::*;
read::read_cfg()
}

Loading…
Cancel
Save