aprender_contracts_cli/commands/
generate.rs1use std::path::Path;
2
3use provable_contracts::binding::{parse_binding, BindingRegistry};
4use provable_contracts::generate::{generate_all, GeneratedFiles};
5use provable_contracts::readme_gen::{generate_ci_workflow, generate_readme};
6use provable_contracts::schema::{parse_contract, Contract};
7
8pub fn run(
9 contract: &Path,
10 output_dir: &Path,
11 binding_path: Option<&Path>,
12 readme: bool,
13 ci: bool,
14) -> Result<(), Box<dyn std::error::Error>> {
15 let c = parse_contract(contract)?;
16 let binding = load_binding(binding_path)?;
17 let stem = contract
18 .file_stem()
19 .and_then(|s| s.to_str())
20 .unwrap_or("contract");
21
22 let result = generate_all(&c, stem, output_dir, binding.as_ref())?;
23 print_generated_files(&result, output_dir);
24
25 if readme {
26 write_readme(&c, stem, output_dir, binding.as_ref())?;
27 }
28 if ci {
29 write_ci_workflow(output_dir, binding.as_ref())?;
30 }
31 Ok(())
32}
33
34fn load_binding(
35 binding_path: Option<&Path>,
36) -> Result<Option<BindingRegistry>, Box<dyn std::error::Error>> {
37 match binding_path {
38 Some(bp) => Ok(Some(parse_binding(bp)?)),
39 None => Ok(None),
40 }
41}
42
43fn print_generated_files(result: &GeneratedFiles, output_dir: &Path) {
44 println!(
45 "Generated {} files in {}:",
46 result.files.len(),
47 output_dir.display()
48 );
49 for f in &result.files {
50 println!(
51 " {} ({}, {} bytes)",
52 f.relative_path.display(),
53 f.kind,
54 f.bytes
55 );
56 }
57}
58
59fn write_readme(
60 c: &Contract,
61 stem: &str,
62 output_dir: &Path,
63 binding: Option<&BindingRegistry>,
64) -> Result<(), Box<dyn std::error::Error>> {
65 let Some(reg) = binding else {
66 eprintln!("warning: --readme requires --binding to generate coverage report");
67 return Ok(());
68 };
69 let contracts = vec![(stem.to_string(), c)];
70 let readme_content = generate_readme(&contracts, reg);
71 let readme_path = output_dir.join("CONTRACT-README.md");
72 std::fs::write(&readme_path, &readme_content)?;
73 println!(
74 " CONTRACT-README.md (readme, {} bytes)",
75 readme_content.len()
76 );
77 Ok(())
78}
79
80fn write_ci_workflow(
81 output_dir: &Path,
82 binding: Option<&BindingRegistry>,
83) -> Result<(), Box<dyn std::error::Error>> {
84 let project_name = binding.map_or("project", |b| b.target_crate.as_str());
85 let ci_content = generate_ci_workflow(project_name);
86 let ci_dir = output_dir.join(".github").join("workflows");
87 std::fs::create_dir_all(&ci_dir)?;
88 let ci_path = ci_dir.join("contracts.yml");
89 std::fs::write(&ci_path, &ci_content)?;
90 println!(
91 " .github/workflows/contracts.yml (ci, {} bytes)",
92 ci_content.len()
93 );
94 Ok(())
95}