use anyhow::Result;
use clap::{Args, Parser};
use std::{
fs,
path::Path,
process::{Command, Stdio},
};
use yansi::Paint;
#[derive(Args)]
#[group(required = true, multiple = false)]
struct TemplateType {
#[arg(long)]
bare: bool,
#[arg(long)]
evm: bool,
}
#[derive(Parser)]
#[command(name = "new", about = "Setup a new project that runs inside the SP1.")]
pub struct NewCmd {
name: String,
#[command(flatten)]
template: TemplateType,
#[arg(long, default_value = "main")]
version: String,
}
const TEMPLATE_REPOSITORY_URL: &str = "https://github.com/succinctlabs/sp1-project-template";
impl NewCmd {
pub fn run(&self) -> Result<()> {
let root = Path::new(&self.name);
if !root.exists() {
fs::create_dir(&self.name)?;
}
println!(" \x1b[1m{}\x1b[0m {}", Paint::green("Cloning"), TEMPLATE_REPOSITORY_URL);
let mut command = Command::new("git");
command
.arg("clone")
.arg("--branch")
.arg(&self.version)
.arg(TEMPLATE_REPOSITORY_URL)
.arg(root.as_os_str())
.arg("--depth=1");
if self.template.evm {
command.arg("--recurse-submodules").arg("--shallow-submodules");
}
command.stdout(Stdio::inherit()).stderr(Stdio::inherit());
let output = command.output().expect("failed to execute command");
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow::anyhow!("failed to clone repository: {}", stderr));
}
fs::remove_dir_all(root.join(".git"))?;
if self.template.evm {
if Command::new("foundry").arg("--version").output().is_err() {
println!(
" \x1b[1m{}\x1b[0m Make sure to install Foundry to use contracts: https://book.getfoundry.sh/getting-started/installation",
Paint::yellow("Warning:"),
);
}
} else {
fs::remove_dir_all(root.join("contracts"))?;
fs::remove_file(root.join(".gitmodules"))?;
}
println!(
" \x1b[1m{}\x1b[0m {} ({})",
Paint::green("Initialized"),
self.name,
std::fs::canonicalize(root).expect("failed to canonicalize").to_str().unwrap()
);
Ok(())
}
}