1use anyhow::{Context, Result};
14use colored::*;
15use robonix_cli::{Config, SourcePathKey};
16use std::path::{Path, PathBuf};
17use std::process::Command;
18
19use super::codegen::{build_codegen_cmd, locate_codegen_bin, run_cmd};
20
21pub async fn execute(config: Config, out_dir: Option<PathBuf>) -> Result<()> {
22 let root = config.resolve_source_path(SourcePathKey::Root)?;
23 let rust_root = config.resolve_source_path(SourcePathKey::RustRoot)?;
24 let capabilities_dir = config.resolve_source_path(SourcePathKey::Capabilities)?;
25 let interfaces_lib = config.resolve_source_path(SourcePathKey::InterfacesLib)?;
26
27 let out = match out_dir {
30 Some(d) if d.is_absolute() => d,
31 Some(d) => root.join(d),
32 None => root.join("docs").join("src").join("reference"),
33 };
34 std::fs::create_dir_all(&out)
35 .with_context(|| format!("create reference dir {}", out.display()))?;
36
37 let stamp = version_stamp(&root);
38
39 let direct = locate_codegen_bin(&rust_root);
40 let cargo = if direct.is_none() {
41 Some(std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()))
42 } else {
43 None
44 };
45
46 println!(
47 "{} robonix-codegen --lang docs → {}",
48 "[docs]".bold(),
49 out.display()
50 );
51 println!("{} version stamp: {}", "[docs]".bold(), stamp);
52 let log_dir = out.parent().unwrap_or(&out).join("rbnx-build").join("logs");
55 let mut cmd = build_codegen_cmd(direct.as_ref(), cargo.as_deref(), &rust_root, &log_dir);
56 cmd.args(["--lang", "docs", "-I"])
57 .arg(&interfaces_lib)
58 .arg("--contracts")
59 .arg(&capabilities_dir)
60 .arg("-o")
61 .arg(&out)
62 .arg("--doc-stamp")
63 .arg(&stamp);
64 run_cmd("robonix-codegen docs", &mut cmd)?;
65
66 println!(
67 "{} wrote contracts.md + idl.md. Commit them into the docs repo — \
68 the mdBook / Pages build needs no robonix environment.",
69 "[docs]".green().bold()
70 );
71 Ok(())
72}
73
74fn version_stamp(root: &Path) -> String {
79 let git = |args: &[&str]| -> Option<String> {
80 let out = Command::new("git")
81 .arg("-C")
82 .arg(root)
83 .args(args)
84 .output()
85 .ok()?;
86 if !out.status.success() {
87 return None;
88 }
89 let s = String::from_utf8(out.stdout).ok()?.trim().to_string();
90 (!s.is_empty()).then_some(s)
91 };
92 let sha = git(&["rev-parse", "--short", "HEAD"]).unwrap_or_else(|| "unknown".to_string());
93 let dirty = git(&["status", "--porcelain"]).is_some_and(|s| !s.is_empty());
94 let date = git(&["log", "-1", "--format=%cd", "--date=short"]).unwrap_or_default();
95 let ver = env!("CARGO_PKG_VERSION");
96 let dirty_tag = if dirty { "-dirty" } else { "" };
97 let date_part = if date.is_empty() {
98 String::new()
99 } else {
100 format!(" · {date}")
101 };
102 format!("v{ver} · commit {sha}{dirty_tag}{date_part}")
103}