diff --git a/crates/templates/src/manager.rs b/crates/templates/src/manager.rs index 882a4a88e4..9ffbbfb368 100644 --- a/crates/templates/src/manager.rs +++ b/crates/templates/src/manager.rs @@ -780,6 +780,7 @@ mod tests { name: "my project".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -813,6 +814,7 @@ mod tests { name: "my project".to_owned(), values, accept_defaults: true, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -878,6 +880,7 @@ mod tests { name: "my multi project".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -905,6 +908,7 @@ mod tests { name: "hello".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -929,6 +933,7 @@ mod tests { name: "hello 2".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -985,6 +990,7 @@ mod tests { name: "my various project".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -1012,6 +1018,7 @@ mod tests { name: "insertvars".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -1063,6 +1070,7 @@ mod tests { name: "my various project".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -1090,6 +1098,7 @@ mod tests { name: "insertvars".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -1114,6 +1123,7 @@ mod tests { name: "insertvarsagain".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -1124,6 +1134,120 @@ mod tests { assert!(!spin_toml.contains("service.example.com")); } + #[tokio::test] + async fn component_new_no_vcs() { + let temp_dir = tempdir().unwrap(); + let store = TemplateStore::new(temp_dir.path()); + let manager = TemplateManager { store }; + let source = TemplateSource::File(project_root()); + + manager + .install(&source, &InstallOptions::default(), &DiscardingReporter) + .await + .unwrap(); + + let dest_temp_dir = tempdir().unwrap(); + let application_dir = dest_temp_dir.path().join("no-vcs-new"); + + let template = manager.get("http-rust").unwrap().unwrap(); + + let values = [ + ("project-description".to_owned(), "my desc".to_owned()), + ("http-path".to_owned(), "/path/...".to_owned()), + ] + .into_iter() + .collect(); + + let options = RunOptions { + variant: crate::template::TemplateVariantInfo::NewApplication, + output_path: application_dir.clone(), + name: "no vcs new".to_owned(), + values, + accept_defaults: false, + no_vcs: true, + }; + + template.run(options).silent().await.unwrap(); + let gitignore = application_dir.join(".gitignore"); + assert!( + !gitignore.exists(), + "expected .gitignore to not have been created" + ); + } + + #[tokio::test] + async fn component_add_no_vcs() { + let temp_dir = tempdir().unwrap(); + let store = TemplateStore::new(temp_dir.path()); + let manager = TemplateManager { store }; + let source = TemplateSource::File(project_root()); + + manager + .install(&source, &InstallOptions::default(), &DiscardingReporter) + .await + .unwrap(); + + let dest_temp_dir = tempdir().unwrap(); + let application_dir = dest_temp_dir.path().join("no-vcs-add"); + + // Set up the containing app + { + let template = manager.get("http-empty").unwrap().unwrap(); + + let values = [("project-description".to_owned(), "my desc".to_owned())] + .into_iter() + .collect(); + let options = RunOptions { + variant: crate::template::TemplateVariantInfo::NewApplication, + output_path: application_dir.clone(), + name: "my multi project".to_owned(), + values, + accept_defaults: false, + no_vcs: true, + }; + + template.run(options).silent().await.unwrap(); + } + + let gitignore = application_dir.join(".gitignore"); + let spin_toml_path = application_dir.join("spin.toml"); + assert!( + !gitignore.exists(), + "expected .gitignore to not have been created" + ); + + { + let template = manager.get("http-rust").unwrap().unwrap(); + + let values = [ + ("project-description".to_owned(), "my desc".to_owned()), + ("http-path".to_owned(), "/path/...".to_owned()), + ] + .into_iter() + .collect(); + + let output_dir = "hello"; + + let options = RunOptions { + variant: crate::template::TemplateVariantInfo::AddComponent { + manifest_path: spin_toml_path.clone(), + }, + output_path: PathBuf::from(output_dir), + name: "added_component".to_owned(), + values, + accept_defaults: false, + no_vcs: true, + }; + template.run(options).silent().await.unwrap(); + } + + let gitignore_add = application_dir.join("hello").join(".gitignore"); + assert!( + !gitignore_add.exists(), + "expected .gitignore to not have been created" + ); + } + #[tokio::test] async fn can_add_component_with_different_trigger() { let temp_dir = tempdir().unwrap(); @@ -1162,6 +1286,7 @@ mod tests { name: "my multi project".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -1189,6 +1314,7 @@ mod tests { name: "hello".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template.run(options).silent().await.unwrap(); @@ -1249,6 +1375,7 @@ mod tests { name: "hello".to_owned(), values, accept_defaults: false, + no_vcs: false, }; template @@ -1318,6 +1445,7 @@ mod tests { name: "bad-filter-should-fail ".to_owned(), values, accept_defaults: false, + no_vcs: false, }; let err = template diff --git a/crates/templates/src/run.rs b/crates/templates/src/run.rs index d5b67f7eb9..928de175c2 100644 --- a/crates/templates/src/run.rs +++ b/crates/templates/src/run.rs @@ -38,6 +38,8 @@ pub struct RunOptions { pub values: HashMap, /// If true accept default values where available pub accept_defaults: bool, + /// If true, do not create a .gitignore file + pub no_vcs: bool, } impl Run { @@ -138,7 +140,15 @@ impl Run { } fn included_files(&self, from: &Path, to: &Path) -> anyhow::Result> { - let all_content_files = Self::list_content_files(from)?; + let gitignore = ".gitignore"; + let mut all_content_files = Self::list_content_files(from)?; + // If user asked for no_vcs + if self.options.no_vcs { + all_content_files.retain(|file| match file.file_name() { + None => true, + Some(file_name) => file_name.to_os_string() != gitignore, + }); + } let included_files = self.template .included_files(from, all_content_files, &self.options.variant); diff --git a/crates/templates/src/test_built_ins/mod.rs b/crates/templates/src/test_built_ins/mod.rs index 9ffc262316..ef32188fdb 100644 --- a/crates/templates/src/test_built_ins/mod.rs +++ b/crates/templates/src/test_built_ins/mod.rs @@ -40,6 +40,7 @@ async fn add_fileserver_does_not_create_dir() -> anyhow::Result<()> { output_path: app_dir.path().to_owned(), values: HashMap::new(), accept_defaults: true, + no_vcs: false, }; manager .get("http-empty")? @@ -56,6 +57,7 @@ async fn add_fileserver_does_not_create_dir() -> anyhow::Result<()> { output_path: app_dir.path().join("fs"), values: HashMap::new(), accept_defaults: true, + no_vcs: false, }; manager .get("static-fileserver")? diff --git a/src/commands/new.rs b/src/commands/new.rs index d87b1acda6..728ae396d9 100644 --- a/src/commands/new.rs +++ b/src/commands/new.rs @@ -62,6 +62,10 @@ pub struct TemplateNewCommandCore { /// by accepting the defaults if available on the template #[clap(short = 'a', long = "accept-defaults", takes_value = false)] pub accept_defaults: bool, + + /// An optional argument that allows to skip creating .gitignore + #[clap(long = "no-vcs", takes_value = false)] + pub no_vcs: bool, } /// Scaffold a new application based on a template. @@ -179,6 +183,7 @@ impl TemplateNewCommandCore { output_path, values, accept_defaults: self.accept_defaults, + no_vcs: self.no_vcs, }; template.run(options).interactive().await