use anyhow::Result;
use clap::{ArgAction, Parser};
use inquire::Confirm;
use ptree::TreeBuilder;
use preamble::{bins, cargo, ci, etc, git, gitignore, libs, license, root, telemetry, utils};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Args {
#[arg(long, short, action = ArgAction::Count, default_value = "0")]
v: u8,
#[arg(long)]
dry_run: bool,
#[arg(long)]
overwrite: bool,
#[arg(long)]
bare: bool,
#[arg(long, short, default_value = "example")]
name: String,
#[arg(long, short)]
with_ci: bool,
#[arg(long, short)]
ci_yml: Option<String>,
#[arg(long, short)]
authors: Option<Vec<String>>,
#[arg(long, short)]
bin: bool,
#[arg(long, short)]
lib: bool,
#[arg(long)]
without_readme: bool,
#[arg(long)]
full: bool,
#[arg(long)]
etc: bool,
#[arg(long)]
assets: bool,
#[arg(long)]
license: bool,
#[arg(long)]
gitignore: bool,
#[arg(long, short)]
description: Option<String>,
#[arg(long)]
dependencies: Option<Vec<String>>,
#[arg(long)]
list: bool,
#[arg(long)]
with_license: Option<String>,
#[arg(default_value = ".")]
project_dir: String,
#[arg(long)]
git: Option<Option<String>>,
}
pub fn run() -> Result<()> {
let Args {
v,
dry_run,
mut assets,
bare,
without_readme,
name,
project_dir,
mut overwrite,
mut with_ci,
ci_yml,
authors,
bin,
lib,
mut license,
with_license,
mut gitignore,
full,
description,
list,
dependencies,
mut etc,
mut git,
} = Args::parse();
let project_dir_path = std::path::Path::new(&project_dir);
if full {
with_ci = true;
license = true;
gitignore = true;
etc = true;
assets = true;
git = Some(None);
}
if list {
root::list_dependencies()?;
return Ok(());
}
telemetry::init_tracing_subscriber(v)?;
match overwrite {
true => {
tracing::warn!("Overwrite flag is set, existing files will be overwritten");
if !Confirm::new("[WARNING] Overwrite mode will overwrite any conflicting files. Are you sure you wish to proceed?").prompt()? {
println!("Phew, close call... aborting");
return Ok(());
}
}
false => {
utils::check_artifacts(project_dir_path, with_ci || ci_yml.is_some(), dry_run)?;
overwrite = true;
}
}
if !dry_run && !overwrite {
tracing::warn!("Running in non-dry run mode.");
tracing::warn!("This action may be destructive.");
if !Confirm::new("Running amble in without dry mode, are you sure you wish to proceed?")
.prompt()?
{
println!("Phew, close call... aborting");
return Ok(());
}
}
let mut builder = TreeBuilder::new(project_dir.clone());
if !dry_run {
std::fs::create_dir_all(project_dir_path)?;
}
if license || with_license.is_some() {
let license_type = with_license.as_deref().unwrap_or("mit");
license::create(project_dir_path, license_type, dry_run, Some(&mut builder))?;
}
if gitignore {
gitignore::create(project_dir_path, dry_run, Some(&mut builder))?;
}
if let Some(u) = git {
git::create(project_dir_path, dry_run, u, Some(&mut builder))?;
}
if etc {
etc::create(project_dir_path, dry_run, assets, Some(&mut builder))?;
}
if !bin && !lib {
root::create(
project_dir_path,
&name,
description.as_ref(),
dry_run,
without_readme,
authors,
dependencies,
Some(&mut builder),
)?;
bins::create(&project_dir_path.join("bin"), &name, dry_run, Some(&mut builder))?;
libs::create(&project_dir_path.join("crates"), "common", dry_run, Some(&mut builder))?;
} else if bin {
cargo::create_bin(
project_dir_path,
&name,
description.as_ref(),
dry_run,
bare,
authors,
dependencies,
Some(&mut builder),
)?;
} else if lib {
cargo::create_lib(
project_dir_path,
&name,
description.as_ref(),
dry_run,
bare,
authors,
dependencies,
Some(&mut builder),
)?;
}
if with_ci || ci_yml.is_some() {
ci::create(project_dir_path, dry_run, ci_yml, Some(&mut builder))?;
}
if dry_run {
let tree = builder.build();
ptree::print_tree(&tree).expect("Error printing tree");
}
Ok(())
}