v0.2.2 : suggestions d'installation selon l'OS (scoop/winget/apt/dnf/pacman/apk/brew) + README remanie
This commit is contained in:
+52
-18
@@ -111,34 +111,60 @@ pub fn check_agent(agent: &AgentDef, runner: &dyn Runner) -> Vec<DepCheck> {
|
||||
}
|
||||
|
||||
/// Fail with an actionable message when dependencies are missing.
|
||||
/// With auto_install_deps enabled, dependencies that define an install_cmd
|
||||
/// are offered for automatic installation first.
|
||||
///
|
||||
/// With auto_install_deps enabled (the default), missing tools are offered
|
||||
/// for installation right away: an explicit install_cmd from the config
|
||||
/// first, otherwise the command detected for the current OS
|
||||
/// (scoop/winget on Windows, apt/dnf/pacman/apk on Linux, brew on macOS).
|
||||
pub fn ensure_deps(app: &App, agent: &AgentDef, runner: &dyn Runner) -> Result<()> {
|
||||
let mut checks = check_agent(agent, runner);
|
||||
if checks.iter().all(|c| c.ok) {
|
||||
return Ok(());
|
||||
}
|
||||
let os = crate::toolchain::OsInfo::detect();
|
||||
if app.config.settings.auto_install_deps() && !app.dry_run() {
|
||||
for dep in &agent.dependencies {
|
||||
if dep.install_cmd.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if check_dep(runner, dep).ok {
|
||||
continue;
|
||||
}
|
||||
let cmd_line = dep.install_cmd.join(" ");
|
||||
app.log.warn(&format!("dependency '{}' is missing", dep.name));
|
||||
let proceed = app
|
||||
.confirm(&format!("Run '{cmd_line}' to install it?"))
|
||||
.unwrap_or(false);
|
||||
if proceed {
|
||||
let prog = dep.install_cmd[0].clone();
|
||||
let args: Vec<String> = dep.install_cmd[1..].to_vec();
|
||||
let empty = BTreeMap::new();
|
||||
let out = runner.run(&prog, &args, &empty, None, false)?;
|
||||
if out.code != 0 {
|
||||
app.log
|
||||
.warn(&format!("automatic installation of '{}' failed", dep.name));
|
||||
// 1) Explicit install command from the configuration.
|
||||
if !dep.install_cmd.is_empty() {
|
||||
let cmd_line = dep.install_cmd.join(" ");
|
||||
if app.confirm(&format!("Run '{cmd_line}' to install it?"))? {
|
||||
let prog = dep.install_cmd[0].clone();
|
||||
let args: Vec<String> = dep.install_cmd[1..].to_vec();
|
||||
let empty = BTreeMap::new();
|
||||
let out = runner.run(&prog, &args, &empty, None, false)?;
|
||||
if out.code != 0 {
|
||||
app.log.warn(&format!(
|
||||
"automatic installation of '{}' failed (exit code {})",
|
||||
dep.name, out.code
|
||||
));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 2) Command detected for the current OS.
|
||||
let cmds = crate::toolchain::install_commands(&dep.name, &os);
|
||||
if let Some(cmd) = cmds.first() {
|
||||
let proceed = app
|
||||
.confirm(&format!("Run the detected installer for {}? -> {cmd}", os.name))?;
|
||||
if proceed {
|
||||
if let Ok(tokens) = shell_words::split(cmd) {
|
||||
if !tokens.is_empty() {
|
||||
let prog = tokens[0].clone();
|
||||
let args: Vec<String> = tokens[1..].to_vec();
|
||||
let empty = BTreeMap::new();
|
||||
let out = runner.run(&prog, &args, &empty, None, false)?;
|
||||
if out.code != 0 {
|
||||
app.log.warn(&format!(
|
||||
"installation of '{}' failed (exit code {})",
|
||||
dep.name, out.code
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,7 +179,15 @@ pub fn ensure_deps(app: &App, agent: &AgentDef, runner: &dyn Runner) -> Result<(
|
||||
if let Some(min) = &c.min {
|
||||
line.push_str(&format!(" (minimum: {min})"));
|
||||
}
|
||||
if let Some(dep) = agent.dependencies.iter().find(|d| d.name == c.name) {
|
||||
let cmds = crate::toolchain::install_commands(&c.name, &os);
|
||||
if !cmds.is_empty() {
|
||||
line.push_str(&format!(
|
||||
"
|
||||
on {}: {}",
|
||||
os.name,
|
||||
cmds.join(" | ")
|
||||
));
|
||||
} else if let Some(dep) = agent.dependencies.iter().find(|d| d.name == c.name) {
|
||||
if let Some(hint) = &dep.install_hint {
|
||||
line.push_str(&format!(" — install via {hint}"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user