use eyre::eyre;
use std::io::Write;
use std::path::PathBuf;
use std::str::FromStr;
use crate::CommandExecute;
#[derive(clap::Args, Debug)]
#[clap(author)]
pub(crate) struct New {
name: String,
#[clap(long, short)]
bgworker: bool,
#[clap(from_global, action = ArgAction::Count)]
verbose: u8,
}
impl CommandExecute for New {
#[tracing::instrument(level = "error", skip(self))]
fn execute(self) -> eyre::Result<()> {
validate_extension_name(&self.name)?;
let path = PathBuf::from_str(&format!("{}/", self.name)).unwrap();
create_crate_template(path, &self.name, self.bgworker)
}
}
fn validate_extension_name(extname: &str) -> eyre::Result<()> {
for c in extname.chars() {
if !c.is_alphanumeric() && c != '_' && !c.is_lowercase() {
return Err(eyre!("Extension name must be in the set of [a-z0-9_]"));
}
}
Ok(())
}
#[tracing::instrument(skip_all, fields(path, name))]
pub(crate) fn create_crate_template(
path: PathBuf,
name: &str,
is_bgworker: bool,
) -> eyre::Result<()> {
create_directory_structure(&path)?;
create_control_file(&path, name)?;
create_cargo_toml(&path, name)?;
create_dotcargo_config_toml(&path, name)?;
create_lib_rs(&path, name, is_bgworker)?;
create_git_ignore(&path, name)?;
Ok(())
}
fn create_directory_structure(path: &PathBuf) -> Result<(), std::io::Error> {
let mut src_dir = path.clone();
src_dir.push("src");
std::fs::create_dir_all(&src_dir)?;
src_dir.pop();
src_dir.push(".cargo");
std::fs::create_dir_all(&src_dir)?;
src_dir.pop();
src_dir.push("sql");
std::fs::create_dir_all(&src_dir)
}
fn create_control_file(path: &PathBuf, name: &str) -> Result<(), std::io::Error> {
let mut filename = path.clone();
filename.push(format!("{}.control", name));
let mut file = std::fs::File::create(filename)?;
file.write_all(&format!(include_str!("../templates/control"), name = name).as_bytes())?;
Ok(())
}
fn create_cargo_toml(path: &PathBuf, name: &str) -> Result<(), std::io::Error> {
let mut filename = path.clone();
filename.push("Cargo.toml");
let mut file = std::fs::File::create(filename)?;
file.write_all(&format!(include_str!("../templates/cargo_toml"), name = name).as_bytes())?;
Ok(())
}
fn create_dotcargo_config_toml(path: &PathBuf, _name: &str) -> Result<(), std::io::Error> {
let mut filename = path.clone();
filename.push(".cargo");
filename.push("config.toml");
let mut file = std::fs::File::create(filename)?;
file.write_all(include_bytes!("../templates/cargo_config_toml"))?;
Ok(())
}
fn create_lib_rs(path: &PathBuf, name: &str, is_bgworker: bool) -> Result<(), std::io::Error> {
let mut filename = path.clone();
filename.push("src");
filename.push("lib.rs");
let mut file = std::fs::File::create(filename)?;
if is_bgworker {
file.write_all(
&format!(include_str!("../templates/bgworker_lib_rs"), name = name).as_bytes(),
)?;
} else {
file.write_all(&format!(include_str!("../templates/lib_rs"), name = name).as_bytes())?;
}
Ok(())
}
fn create_git_ignore(path: &PathBuf, _name: &str) -> Result<(), std::io::Error> {
let mut filename = path.clone();
filename.push(".gitignore");
let mut file = std::fs::File::create(filename)?;
file.write_all(include_bytes!("../templates/gitignore"))?;
Ok(())
}