use crate::discover::{self, InstallOrigin, InstalledNode};
use crate::error::Error;
use std::path::PathBuf;
pub fn mise_on_path() -> Option<PathBuf> {
static FOUND: std::sync::OnceLock<Option<PathBuf>> = std::sync::OnceLock::new();
FOUND
.get_or_init(|| discover::find_on_path(if cfg!(windows) { "mise.exe" } else { "mise" }))
.clone()
}
pub(crate) async fn install_via_mise(
mise_bin: &std::path::Path,
version: &node_semver::Version,
progress: &dyn crate::progress::DownloadProgress,
) -> Result<InstalledNode, Error> {
install_tool_via_mise(mise_bin, "node", version, progress).await?;
find_mise_install(version).ok_or_else(|| Error::MiseInstallFailed {
version: format!("node@{version}"),
reason: format!(
"mise reported success but node@{} was not found under {} — \
if mise uses a custom data dir, export MISE_DATA_DIR so aube sees the same path",
version,
discover::mise_node_installs_dir()
.unwrap_or_default()
.display()
),
})
}
pub(crate) async fn install_tool_via_mise(
mise_bin: &std::path::Path,
tool: &str,
version: &node_semver::Version,
progress: &dyn crate::progress::DownloadProgress,
) -> Result<(), Error> {
let spec = format!("{tool}@{version}");
tracing::debug!(mise = %mise_bin.display(), %spec, "delegating install to mise");
progress.on_external_tool_start();
let result = tokio::process::Command::new(mise_bin)
.args(["install", &spec])
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.output()
.await;
progress.on_external_tool_end();
let output = result.map_err(|e| Error::MiseInstallFailed {
version: spec.clone(),
reason: format!("failed to spawn mise: {e}"),
})?;
for line in String::from_utf8_lossy(&output.stdout).lines() {
tracing::debug!(target: "mise", "{line}");
}
if !output.status.success() {
return Err(Error::MiseInstallFailed {
version: spec,
reason: format!(
"exit status {} (see mise output above)",
output.status.code().unwrap_or(-1)
),
});
}
Ok(())
}
pub(crate) fn find_mise_install(version: &node_semver::Version) -> Option<InstalledNode> {
let dir = discover::mise_node_installs_dir()?.join(version.to_string());
discover::validate_install(&dir, version.clone(), InstallOrigin::Mise)
}