diff --git a/assets/ContractTemplate.sol b/assets/ContractTemplate.sol new file mode 100644 index 0000000000000..fb706945cff8b --- /dev/null +++ b/assets/ContractTemplate.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: Unlicense +pragma solidity 0.8.10; + +contract Contract {} diff --git a/assets/ContractTemplate.t.sol b/assets/ContractTemplate.t.sol new file mode 100644 index 0000000000000..409403a84941f --- /dev/null +++ b/assets/ContractTemplate.t.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Unlicense +pragma solidity 0.8.10; + +contract ContractTest { + function setUp() public {} +} diff --git a/cli/src/forge.rs b/cli/src/forge.rs index 8a3d1e8425a73..3c2d61b92b4ed 100644 --- a/cli/src/forge.rs +++ b/cli/src/forge.rs @@ -245,6 +245,55 @@ fn main() -> eyre::Result<()> { .collect(); remappings.iter().for_each(|x| println!("{}", x)); } + Subcommands::Init { root, template } => { + let root = root.unwrap_or_else(|| std::env::current_dir().unwrap()); + // create the root dir if it does not exist + if !root.exists() { + std::fs::create_dir_all(&root)?; + } + let root = std::fs::canonicalize(root)?; + + // if a template is provided, then this command is just an alias to `git clone + // ` + if let Some(ref template) = template { + println!("Initializing {} from {}...", root.display(), template); + std::process::Command::new("git") + .args(&["clone", template, &root.display().to_string()]) + .spawn()? + .wait()?; + } else { + println!("Initializing {}...", root.display()); + + // make the dirs + let src = root.join("src"); + let test = src.join("test"); + std::fs::create_dir_all(&test)?; + let lib = root.join("lib"); + std::fs::create_dir(&lib)?; + + // write the contract file + let contract_path = src.join("Contract.sol"); + std::fs::write(contract_path, include_str!("../../assets/ContractTemplate.sol"))?; + // write the tests + let contract_path = test.join("Contract.t.sol"); + std::fs::write(contract_path, include_str!("../../assets/ContractTemplate.t.sol"))?; + + // sets up git + std::process::Command::new("git").arg("init").current_dir(&root).spawn()?.wait()?; + std::process::Command::new("git") + .args(&["add", "."]) + .current_dir(&root) + .spawn()? + .wait()?; + std::process::Command::new("git") + .args(&["commit", "-m", "chore: forge init"]) + .current_dir(&root) + .spawn()? + .wait()?; + } + + println!("Done."); + } } Ok(()) diff --git a/cli/src/forge_opts.rs b/cli/src/forge_opts.rs index a14c601350c82..88df61e6d9a9a 100644 --- a/cli/src/forge_opts.rs +++ b/cli/src/forge_opts.rs @@ -122,6 +122,13 @@ pub enum Subcommands { #[structopt(long, help = "verify on Etherscan")] verify: bool, }, + #[structopt(alias = "i", about = "initializes a new forge repository")] + Init { + #[structopt(help = "the project's root path, default being the current directory")] + root: Option, + #[structopt(help = "optional solidity template to start from", long, short)] + template: Option, + }, } /// Represents the common dapp argument pattern for `:` where `:` is