fp-dotfiles-manager 0.2.5

Minimal, zero-dependency Chezmoi-based dotfiles manager
use crate::logger::*;
use std::io;

pub fn run_bootstrap(bootstrap_dir: &str, check_env: bool) -> io::Result<()> {
    if check_env {
        let skip = std::env::var("SKIP_BOOTSTRAP").unwrap_or_default();
        if skip == "1" || skip.to_lowercase() == "true" {
            log_warn("Skipping bootstrap due to SKIP_BOOTSTRAP.");
            return Ok(());
        }
    }

    log_section("Running bootstrap scripts...");
    let dir_path = std::path::Path::new(bootstrap_dir);
    if dir_path.is_dir() {
        log_step(&("Scanning ".to_owned() + bootstrap_dir));
        let mut scripts = Vec::new();
        for entry in std::fs::read_dir(dir_path)? {
            if let Ok(entry) = entry {
                let path = entry.path();
                if path.is_file() && path.extension().map_or(false, |ext| ext == "sh") {
                    scripts.push(path);
                }
            }
        }

        scripts.sort();

        for script in scripts {
            let filename = script
                .file_name()
                .unwrap_or_default()
                .to_string_lossy()
                .into_owned();

            let is_executable = {
                #[cfg(unix)]
                {
                    use std::os::unix::fs::MetadataExt;
                    if let Ok(meta) = std::fs::metadata(&script) {
                        (meta.mode() & 0o111) != 0
                    } else {
                        false
                    }
                }
                #[cfg(not(unix))]
                true
            };

            if is_executable {
                log_step(&("Executing ".to_owned() + &filename));
                let status = std::process::Command::new(&script).status()?;
                if status.success() {
                    log_success(&("Finished ".to_owned() + &filename));
                } else {
                    log_error(&("Script failed: ".to_owned() + &filename));
                }
            } else {
                log_warn(&("Skipping non-executable script: ".to_owned() + &filename));
            }
        }
        log_done("Bootstrap phase complete.");
    } else {
        log_warn(&("No bootstrap directory found at ".to_owned() + bootstrap_dir));
    }

    Ok(())
}