Skip to main content

rbnx/cmd/
setup.rs

1// SPDX-License-Identifier: MulanPSL-2.0
2// `rbnx setup` — register the current robonix source tree so out-of-tree packages
3// (their build.sh, codegen calls) can resolve paths via `rbnx path <key>`.
4
5use anyhow::{Context, Result};
6use colored::*;
7use robonix_cli::Config;
8use std::path::{Path, PathBuf};
9
10/// Markers that identify a directory as a valid robonix repo root.
11/// The Cargo workspace lives at the repo root; capabilities/ hosts the
12/// contract TOMLs plus the IDL tree under capabilities/lib (used to be a
13/// symlink into rust/crates/robonix-interfaces/lib; now hosted directly).
14const ROBONIX_ROOT_MARKERS: &[&str] = &["Cargo.toml", "capabilities", "capabilities/lib"];
15
16fn looks_like_robonix_root(dir: &Path) -> bool {
17    ROBONIX_ROOT_MARKERS.iter().all(|m| dir.join(m).exists())
18}
19
20/// Find a robonix root by walking up from `start`.
21fn find_root_upwards(start: &Path) -> Option<PathBuf> {
22    let mut cur = start;
23    loop {
24        if looks_like_robonix_root(cur) {
25            return Some(cur.to_path_buf());
26        }
27        cur = cur.parent()?;
28    }
29}
30
31pub async fn execute(_config: Config, path: Option<PathBuf>) -> Result<()> {
32    // Determine candidate: explicit arg, $RBNX_INVOCATION_CWD, then process cwd.
33    let candidate = if let Some(p) = path {
34        if p.is_absolute() {
35            p
36        } else {
37            std::env::current_dir()?.join(p)
38        }
39    } else {
40        let invocation_cwd = std::env::var("RBNX_INVOCATION_CWD").ok();
41        invocation_cwd
42            .map(PathBuf::from)
43            .unwrap_or(std::env::current_dir()?)
44    };
45
46    let candidate = candidate
47        .canonicalize()
48        .with_context(|| format!("Failed to canonicalize {}", candidate.display()))?;
49
50    let root = if looks_like_robonix_root(&candidate) {
51        candidate.clone()
52    } else if let Some(r) = find_root_upwards(&candidate) {
53        r
54    } else {
55        eprintln!(
56            "{}: {} does not look like a robonix source tree.",
57            "error".red().bold(),
58            candidate.display()
59        );
60        eprintln!(
61            "Expected markers (at least one level up): {}",
62            ROBONIX_ROOT_MARKERS.join(", ")
63        );
64        eprintln!("Run `rbnx setup` from inside a cloned robonix repo.");
65        std::process::exit(1);
66    };
67
68    let mut config = Config::load()?;
69    let previous = config.robonix_source_path.clone();
70    config.robonix_source_path = Some(root.clone());
71    config.save()?;
72
73    println!("{} robonix source path registered:", "✓".green().bold());
74    println!("  {}", root.display().to_string().bold().cyan());
75    if let Some(prev) = previous.filter(|p| p != &root) {
76        println!("  (previously: {})", prev.display().to_string().dimmed());
77    }
78    println!(
79        "\nOther packages can now resolve paths via `{}`.",
80        "rbnx path <key>".bold()
81    );
82    println!("Valid keys: root, rust, capabilities, interfaces-lib, runtime-proto, robonix-api");
83    Ok(())
84}