v0.2.2 : suggestions d'installation selon l'OS (scoop/winget/apt/dnf/pacman/apk/brew) + README remanie

This commit is contained in:
2026-08-15 12:56:33 -04:00
parent bd1d566a44
commit e513dd485d
9 changed files with 638 additions and 390 deletions
+49 -6
View File
@@ -63,6 +63,7 @@ pub fn run(app: &App, runner: &dyn Runner) -> DoctorReport {
("uv", false),
("docker", false),
];
let os = crate::toolchain::OsInfo::detect();
for (tool, required) in tools {
match runner.which(tool) {
Some(path) => {
@@ -84,14 +85,20 @@ pub fn run(app: &App, runner: &dyn Runner) -> DoctorReport {
});
}
None => {
let (status, detail) = if *required {
(
Status::Error,
"required but not found on PATH".to_string(),
)
let mut detail = if *required {
"required but not found on PATH".to_string()
} else {
(Status::Ok, "not installed".to_string())
"not installed".to_string()
};
let cmds = crate::toolchain::install_commands(tool, &os);
if !cmds.is_empty() {
detail.push_str(&format!(
" — on {}: {}",
os.name,
cmds.join(" | ")
));
}
let status = if *required { Status::Error } else { Status::Ok };
checks.push(Check {
name: tool.to_string(),
status,
@@ -199,6 +206,42 @@ fn is_on_path(dir: &std::path::Path) -> bool {
})
}
/// Offer to install the missing optional tools (node, python, ...) with
/// the command detected for the current OS. Returns what was repaired.
pub fn install_missing_tools(app: &App, runner: &dyn Runner) -> Result<Vec<String>> {
let mut installed = Vec::new();
let os = crate::toolchain::OsInfo::detect();
for tool in ["node", "python", "cargo", "go", "bun", "uv", "docker"] {
if runner.which(tool).is_some() {
continue;
}
let cmds = crate::toolchain::install_commands(tool, &os);
let Some(cmd) = cmds.first() else {
continue;
};
if !app.confirm(&format!(
"'{tool}' is missing — run the detected installer for {}? -> {cmd}",
os.name
))? {
continue;
}
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)?;
installed.push(if out.code == 0 {
format!("installed '{tool}' ({cmd})")
} else {
format!("failed to install '{tool}' (exit code {})", out.code)
});
}
}
}
Ok(installed)
}
/// Repair what can be repaired: create directories, fix a corrupt state file.
pub fn fix(app: &App) -> Result<Vec<String>> {
let mut repaired = Vec::new();