matrixcode_core/tools/codegraph/
install.rs1use anyhow::Result;
4use std::path::PathBuf;
5use tokio::process::Command;
6
7#[cfg(windows)]
9fn create_command(program: &str) -> std::process::Command {
10 use std::os::windows::process::CommandExt;
11 const CREATE_NO_WINDOW: u32 = 0x08000000;
12 let mut cmd = std::process::Command::new(program);
13 cmd.creation_flags(CREATE_NO_WINDOW);
14 cmd
15}
16
17#[cfg(not(windows))]
18fn create_command(program: &str) -> std::process::Command {
19 std::process::Command::new(program)
20}
21
22#[cfg(windows)]
24fn create_async_command(program: &str) -> Command {
25 const CREATE_NO_WINDOW: u32 = 0x08000000;
26 let mut cmd = Command::new(program);
27 cmd.creation_flags(CREATE_NO_WINDOW);
28 cmd
29}
30
31#[cfg(not(windows))]
32fn create_async_command(program: &str) -> Command {
33 Command::new(program)
34}
35
36fn get_codegraph_install_dir() -> Option<PathBuf> {
38 dirs::data_local_dir()
39 .map(|p| p.join("codegraph").join("current").join("bin"))
40}
41
42fn get_codegraph_exe_name() -> String {
44 if cfg!(windows) {
45 "codegraph.cmd".to_string()
46 } else {
47 "codegraph".to_string()
48 }
49}
50
51pub fn is_codegraph_installed() -> bool {
53 if create_command("codegraph")
55 .arg("--version")
56 .output()
57 .is_ok()
58 {
59 return true;
60 }
61
62 if let Some(install_dir) = get_codegraph_install_dir() {
64 let exe_name = get_codegraph_exe_name();
65 let exe_path = install_dir.join(&exe_name);
66 if exe_path.exists()
67 && create_command(exe_path.to_str().unwrap_or("codegraph"))
68 .arg("--version")
69 .output()
70 .is_ok()
71 {
72 return true;
73 }
74 }
75
76 false
77}
78
79pub fn get_codegraph_path() -> Option<String> {
81 if create_command("codegraph")
83 .arg("--version")
84 .output()
85 .is_ok()
86 {
87 return Some("codegraph".to_string());
88 }
89
90 if let Some(install_dir) = get_codegraph_install_dir() {
92 let exe_name = get_codegraph_exe_name();
93 let exe_path = install_dir.join(&exe_name);
94 if exe_path.exists() {
95 return Some(exe_path.to_string_lossy().to_string());
96 }
97 }
98
99 None
100}
101
102pub async fn install_codegraph() -> Result<()> {
104 log::info!("Installing CodeGraph CLI...");
105
106 let result = create_async_command("powershell")
108 .args([
109 "-NoProfile",
110 "-Command",
111 "irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex",
112 ])
113 .output()
114 .await?;
115
116 if result.status.success() {
117 log::info!("CodeGraph CLI installed successfully");
118 Ok(())
119 } else {
120 let stderr = String::from_utf8_lossy(&result.stderr);
121 Err(anyhow::anyhow!("CodeGraph installation failed: {}", stderr))
122 }
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
127#[allow(dead_code)]
128pub enum CodeGraphInstallStatus {
129 Installed(String),
131 NotInstalled,
133}
134
135#[allow(dead_code)]
137pub fn check_codegraph_status() -> CodeGraphInstallStatus {
138 match get_codegraph_path() {
139 Some(path) => CodeGraphInstallStatus::Installed(path),
140 None => CodeGraphInstallStatus::NotInstalled,
141 }
142}
143
144pub async fn ensure_codegraph() -> Result<String> {
146 if let Some(path) = get_codegraph_path() {
147 return Ok(path);
148 }
149
150 install_codegraph().await?;
151 get_codegraph_path().ok_or_else(|| anyhow::anyhow!("CodeGraph not found after installation"))
152}