cargo_tangle/command/create/
mod.rs1pub use crate::command::create::error::Error;
2pub use crate::command::create::source::Source;
3pub use crate::command::create::types::BlueprintType;
4use crate::foundry::FoundryToolchain;
5use types::{BlueprintVariant, EigenlayerVariant};
6
7pub mod error;
8pub mod source;
9pub mod types;
10
11pub fn new_blueprint(
26 name: &str,
27 source: Option<Source>,
28 blueprint_type: Option<BlueprintType>,
29 mut define: Vec<String>,
30 template_values_file: &Option<String>,
31 skip_prompts: bool,
32) -> Result<(), Error> {
33 println!("Generating blueprint with name: {}", name);
34
35 let source = source.unwrap_or_default();
36 let blueprint_variant = blueprint_type.map(|t| t.get_type()).unwrap_or_default();
37 let template_path_opt: Option<cargo_generate::TemplatePath> = source.into();
38
39 let template_path = template_path_opt.unwrap_or_else(|| {
40 let template_repo: String = match blueprint_variant {
42 Some(BlueprintVariant::Tangle) | None => {
43 "https://github.com/tangle-network/blueprint-template".into()
44 }
45 Some(BlueprintVariant::Eigenlayer(EigenlayerVariant::BLS)) => {
46 "https://github.com/tangle-network/eigenlayer-bls-template".into()
47 }
48 Some(BlueprintVariant::Eigenlayer(EigenlayerVariant::ECDSA)) => {
49 "https://github.com/tangle-network/eigenlayer-ecdsa-template".into()
50 }
51 };
52
53 cargo_generate::TemplatePath {
54 git: Some(template_repo),
55 branch: Some(String::from("main")),
56 ..Default::default()
57 }
58 });
59
60 if skip_prompts {
61 println!("Skipping prompts and using default values for unspecified template variables");
62
63 let mut defined_vars = std::collections::HashMap::new();
65 for def in &define {
66 if let Some((key, value)) = def.split_once('=') {
67 defined_vars.insert(key.to_string(), value.to_string());
68 }
69 }
70
71 let defaults = [
73 ("gh-username", ""),
74 ("gh-repo", ""),
75 ("gh-organization", ""),
76 ("project-description", ""),
77 ("project-homepage", ""),
78 ("flakes", "false"),
79 ("container", "true"),
80 ("base-image", "rustlang/rust:nightly"),
81 ("container-registry", "docker.io"),
82 ("ci", "true"),
83 ("rust-ci", "true"),
84 ("release-ci", "true"),
85 ];
86
87 for (key, value) in defaults {
89 if !defined_vars.contains_key(key) {
90 define.push(format!("{key}={value}"));
91 println!(" Using default value for {key}: {value}");
92 }
93 }
94 } else {
95 println!("Running in interactive mode - will prompt for template variables as needed");
96 }
97
98 if !define.is_empty() {
99 println!("Using template variables: {:?}", define);
100 }
101 let (silent, template_values_file) = if let Some(file) = &template_values_file {
102 println!("Using template values file: {}", file);
103 (true, Some(file.clone()))
104 } else {
105 (false, None)
106 };
107
108 let path = cargo_generate::generate(cargo_generate::GenerateArgs {
109 template_path,
110 list_favorites: false,
111 name: Some(name.to_string()),
112 force: false,
113 verbose: false,
114 template_values_file,
115 silent,
116 config: None,
117 vcs: Some(cargo_generate::Vcs::Git),
118 lib: false,
119 bin: true,
120 ssh_identity: None,
121 gitconfig: None,
122 define,
123 init: false,
124 destination: None,
125 force_git_init: false,
126 allow_commands: false,
127 overwrite: false,
128 skip_submodules: false,
129 other_args: Option::default(),
130 continue_on_error: false,
131 quiet: false,
132 })
133 .map_err(Error::GenerationFailed)?;
134
135 println!("Blueprint generated at: {}", path.display());
136
137 let foundry = FoundryToolchain::new();
138 if !foundry.forge.is_installed() {
139 blueprint_core::warn!("Forge not installed, skipping dependencies");
140 blueprint_core::warn!("NOTE: See <https://getfoundry.sh>");
141 blueprint_core::warn!(
142 "NOTE: After installing Forge, you can run `forge soldeer update -d` to install dependencies"
143 );
144 return Ok(());
145 }
146
147 std::env::set_current_dir(path)?;
148 if let Err(e) = foundry.forge.install_dependencies() {
149 blueprint_core::error!("{e}");
150 }
151
152 Ok(())
153}