Skip to content

Commit 09c7caa

Browse files
committed
Add TemplateManifestConfig
1 parent 8a79278 commit 09c7caa

File tree

3 files changed

+72
-39
lines changed

3 files changed

+72
-39
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
#### Added
1313

1414
- `snforge completion` command - used to generate autocompletion script
15+
- `--template` flag to `snforge new` command that allows selecting a template for the new project. Possible values are `balance-contract` (default) and `cairo-program`
1516

1617
### Cast
1718

@@ -50,7 +51,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5051
- `snforge new` now adds the `snfoundry_trace`, `coverage`, and `profile` directories to `.gitignore`.
5152
- Custom types can be used in fuzz testing by implementing the `Fuzzable` trait
5253
- Support for Cairo 2.10.0
53-
- `--template` flag to `snforge new` command that allows selecting a template for the new project. Possible values are `balance-contract` (default) and `cairo-program`
5454

5555
#### Changed
5656

crates/forge/src/new.rs

+70-37
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,39 @@ static TEMPLATES_DIR: Dir = include_dir!("snforge_templates");
1818
const DEFAULT_ASSERT_MACROS: Version = Version::new(0, 1, 0);
1919
const MINIMAL_SCARB_FOR_CORRESPONDING_ASSERT_MACROS: Version = Version::new(2, 8, 0);
2020

21+
struct Dependency {
22+
name: String,
23+
version: String,
24+
dev: bool,
25+
}
26+
27+
struct TemplateManifestConfig {
28+
dependencies: Vec<Dependency>,
29+
contract_target: bool,
30+
}
31+
32+
impl TryFrom<&Template> for TemplateManifestConfig {
33+
type Error = anyhow::Error;
34+
35+
fn try_from(template: &Template) -> Result<Self> {
36+
let cairo_version = ScarbCommand::version().run()?.cairo;
37+
match template {
38+
Template::CairoProgram => Ok(TemplateManifestConfig {
39+
dependencies: vec![],
40+
contract_target: false,
41+
}),
42+
Template::BalanceContract => Ok(TemplateManifestConfig {
43+
dependencies: vec![Dependency {
44+
name: "starknet".to_string(),
45+
version: cairo_version.to_string(),
46+
dev: false,
47+
}],
48+
contract_target: true,
49+
}),
50+
}
51+
}
52+
}
53+
2154
fn create_snfoundry_manifest(path: &PathBuf) -> Result<()> {
2255
fs::write(
2356
path,
@@ -56,7 +89,7 @@ fn add_template_to_scarb_manifest(path: &PathBuf) -> Result<()> {
5689
Ok(())
5790
}
5891

59-
fn overwrite_or_copy_files(
92+
fn overwrite_or_copy_template_files(
6093
dir: &Dir,
6194
template_path: &Path,
6295
project_path: &Path,
@@ -68,7 +101,7 @@ fn overwrite_or_copy_files(
68101
match entry {
69102
DirEntry::Dir(dir) => {
70103
fs::create_dir_all(&destination)?;
71-
overwrite_or_copy_files(dir, template_path, project_path, project_name)?;
104+
overwrite_or_copy_template_files(dir, template_path, project_path, project_name)?;
72105
}
73106
DirEntry::File(file) => {
74107
let contents = file.contents();
@@ -87,13 +120,16 @@ fn replace_project_name(contents: &[u8], project_name: &str) -> Result<Vec<u8>>
87120
Ok(contents.into_bytes())
88121
}
89122

90-
fn update_config(config_path: &Path, template: &Template) -> Result<()> {
91-
let config_file = fs::read_to_string(config_path)?;
92-
let mut document = config_file
123+
fn update_config(
124+
scarb_manifest_path: &Path,
125+
template_config: &TemplateManifestConfig,
126+
) -> Result<()> {
127+
let scarb_toml_content = fs::read_to_string(scarb_manifest_path)?;
128+
let mut document = scarb_toml_content
93129
.parse::<DocumentMut>()
94130
.context("invalid document")?;
95131

96-
if !matches!(template, Template::CairoProgram) {
132+
if template_config.contract_target {
97133
add_target_to_toml(&mut document);
98134
}
99135

@@ -102,7 +138,7 @@ fn update_config(config_path: &Path, template: &Template) -> Result<()> {
102138
add_assert_macros(&mut document)?;
103139
add_allow_prebuilt_macros(&mut document)?;
104140

105-
fs::write(config_path, document.to_string())?;
141+
fs::write(scarb_manifest_path, document.to_string())?;
106142

107143
Ok(())
108144
}
@@ -192,6 +228,7 @@ pub fn new(
192228
template,
193229
}: NewArgs,
194230
) -> Result<()> {
231+
ScarbCommand::new().ensure_available()?;
195232
if !overwrite {
196233
ensure!(
197234
!path.exists() || path.read_dir().is_ok_and(|mut i| i.next().is_none()),
@@ -238,12 +275,14 @@ pub fn new(
238275
create_snfoundry_manifest(&snfoundry_manifest_path)?;
239276
}
240277

241-
add_dependencies_to_scarb_toml(&project_path, &template)?;
242-
update_config(&scarb_manifest_path, &template)?;
243-
extend_gitignore(&project_path)?;
278+
let template_config = TemplateManifestConfig::try_from(&template)?;
279+
add_dependencies(&scarb_manifest_path, &template_config)?;
280+
update_config(&scarb_manifest_path, &template_config)?;
244281

245282
let template_dir = get_template_dir(&template)?;
246-
overwrite_or_copy_files(&template_dir, template_dir.path(), &project_path, &name)?;
283+
overwrite_or_copy_template_files(&template_dir, template_dir.path(), &project_path, &name)?;
284+
285+
extend_gitignore(&project_path)?;
247286

248287
// Fetch to create lock file.
249288
ScarbCommand::new_with_stdio()
@@ -255,46 +294,40 @@ pub fn new(
255294
Ok(())
256295
}
257296

258-
fn add_dependencies_to_scarb_toml(project_path: &PathBuf, template: &Template) -> Result<()> {
259-
let snforge_version = env!("CARGO_PKG_VERSION");
260-
let cairo_version = ScarbCommand::version().run()?.cairo;
261-
297+
fn add_dependencies(
298+
scarb_manifest_path: &PathBuf,
299+
template_config: &TemplateManifestConfig,
300+
) -> Result<()> {
262301
if env::var("DEV_DISABLE_SNFORGE_STD_DEPENDENCY").is_err() {
263-
add_dependency(project_path, "snforge_std", snforge_version, true)?;
302+
let snforge_version = env!("CARGO_PKG_VERSION");
303+
add_dependency(
304+
scarb_manifest_path,
305+
&Dependency {
306+
name: "snforge_std".to_string(),
307+
version: snforge_version.to_string(),
308+
dev: true,
309+
},
310+
)?;
264311
}
265312

266-
match template {
267-
Template::BalanceContract => {
268-
add_dependency(project_path, "starknet", &cairo_version.to_string(), false)?;
269-
}
270-
Template::CairoProgram => {}
313+
for dep in &template_config.dependencies {
314+
add_dependency(scarb_manifest_path, dep)?;
271315
}
272316

273317
Ok(())
274318
}
275319

276-
fn add_dependency(
277-
project_path: &PathBuf,
278-
dep_name: &str,
279-
version: &str,
280-
is_dev: bool,
281-
) -> Result<()> {
282-
let scarb_manifest_path = project_path.join("Scarb.toml");
283-
320+
fn add_dependency(scarb_manifest_path: &PathBuf, dependency: &Dependency) -> Result<()> {
284321
let mut cmd = ScarbCommand::new_with_stdio();
322+
cmd.manifest_path(scarb_manifest_path).offline().arg("add");
285323

286-
cmd.current_dir(project_path)
287-
.manifest_path(scarb_manifest_path.clone())
288-
.offline()
289-
.arg("add");
290-
291-
if is_dev {
324+
if dependency.dev {
292325
cmd.arg("--dev");
293326
}
294327

295-
cmd.arg(format!("{dep_name}@{version}"))
328+
cmd.arg(format!("{}@{}", dependency.name, dependency.version))
296329
.run()
297-
.context(format!("Failed to add {dep_name} dependency"))?;
330+
.context(format!("Failed to add {} dependency", dependency.name))?;
298331

299332
Ok(())
300333
}

docs/src/appendix/snforge/new.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Name of a package to create, defaults to the directory name.
1212

1313
## `-t`, `--template`
1414

15-
Name of a template to use in creating the new project. Possible values:
15+
Name of a template to use when creating a new project. Possible values:
1616
- `balance-contract` (default): Basic contract with example tests.
1717
- `cairo-program`: Simple Cairo program with unit tests.
1818

0 commit comments

Comments
 (0)