bashrs 6.66.0

Rust-to-Shell transpiler for deterministic bootstrap scripts
fn generate_installer_toml(
    patterns: &[BashPattern],
    name: &str,
) -> Result<(String, Vec<TemplateFile>, ConversionStats)> {
    let mut toml = String::new();
    let mut templates = Vec::new();
    let mut stats = ConversionStats::default();
    let mut step_id = 0;

    // Check for root requirement
    let requires_root = patterns.iter().any(|p| matches!(p, BashPattern::RootCheck));

    // Generate installer header
    toml.push_str(&format!(
        r#"# Installer specification converted from bash script
# Generated by bashrs installer from-bash

[installer]
name = "{name}"
version = "1.0.0"
description = "Converted from legacy bash script"

[installer.requirements]
privileges = "{}"

"#,
        if requires_root { "root" } else { "user" }
    ));

    // Generate steps
    for pattern in patterns {
        match pattern {
            BashPattern::RootCheck => {
                // Already handled in requirements
                stats.conditionals_converted += 1;
            }
            BashPattern::AptUpdate => {
                step_id += 1;
                stats.steps_generated += 1;
                toml.push_str(&format!(
                    r#"[[step]]
id = "step-{step_id}-apt-update"
name = "Update Package Lists"
action = "script"

[step.script]
interpreter = "sh"
content = "apt-get update"

"#
                ));
            }
            BashPattern::AptInstall { packages } => {
                step_id += 1;
                stats.steps_generated += 1;
                stats.apt_installs += 1;
                let packages_list = packages
                    .iter()
                    .map(|p| format!("\"{}\"", p))
                    .collect::<Vec<_>>()
                    .join(", ");
                toml.push_str(&format!(
                    r#"[[step]]
id = "step-{step_id}-install"
name = "Install Packages"
action = "script"

[step.script]
interpreter = "sh"
content = "apt-get install -y {}"

# Packages: [{}]

"#,
                    packages.join(" "),
                    packages_list
                ));
            }
            BashPattern::MkdirP { path } => {
                step_id += 1;
                stats.steps_generated += 1;
                toml.push_str(&format!(
                    r#"[[step]]
id = "step-{step_id}-mkdir"
name = "Create Directory"
action = "script"

[step.script]
interpreter = "sh"
content = "mkdir -p {path}"

"#
                ));
            }
            BashPattern::Download { url, output } => {
                step_id += 1;
                stats.steps_generated += 1;
                let output_str = output.as_deref().unwrap_or("downloaded-file");
                toml.push_str(&format!(
                    r#"[[step]]
id = "step-{step_id}-download"
name = "Download File"
action = "script"

[step.script]
interpreter = "sh"
content = "curl -fsSL {url} -o {output_str}"

"#
                ));
            }
            BashPattern::Heredoc { delimiter, content } => {
                step_id += 1;
                stats.steps_generated += 1;
                stats.heredocs_converted += 1;
                let template_name = format!("template-{}.txt", step_id);
                templates.push(TemplateFile {
                    name: template_name.clone(),
                    content: content.clone(),
                });
                toml.push_str(&format!(
                    r#"[[step]]
id = "step-{step_id}-heredoc"
name = "Write Template File"
action = "script"

# Original heredoc delimiter: {delimiter}
# Template extracted to: templates/{template_name}

[step.script]
interpreter = "sh"
content = "cat templates/{template_name}"

"#
                ));
            }
            BashPattern::SudoCommand { command } => {
                step_id += 1;
                stats.steps_generated += 1;
                stats.sudo_patterns += 1;
                toml.push_str(&format!(
                    r#"[[step]]
id = "step-{step_id}-sudo"
name = "Execute Privileged Command"
action = "script"

[step.script]
interpreter = "sh"
content = "{command}"

[step.checkpoint]
enabled = true

"#
                ));
            }
            BashPattern::Script { content } => {
                step_id += 1;
                stats.steps_generated += 1;
                toml.push_str(&format!(
                    r#"[[step]]
id = "step-{step_id}-script"
name = "Execute Script"
action = "script"

[step.script]
interpreter = "sh"
content = "{content}"

"#
                ));
            }
        }
    }

    Ok((toml, templates, stats))
}


include!("from_bash_generate.rs");