alef-e2e 0.3.5

Fixture-driven e2e test generator for alef
Documentation
//! Post-generation formatter support for e2e test projects.
//!
//! Reads formatter commands from `E2eConfig.format` and runs them for each
//! language that had files generated. The `{dir}` placeholder in the command
//! is replaced with the actual output directory.

use crate::config::E2eConfig;
use alef_core::backend::GeneratedFile;
use std::collections::HashSet;
use std::path::Path;
use tracing::warn;

/// Run per-language formatters for all languages that had files generated.
///
/// For each language present in `files`, looks up `e2e_config.format[lang]` and
/// runs the command with `{dir}` replaced by `{output}/{lang}`.
/// Failures are logged as warnings and do not abort the process.
pub fn run_formatters(files: &[GeneratedFile], e2e_config: &E2eConfig) {
    if e2e_config.format.is_empty() {
        return;
    }

    // Collect the set of languages that had files generated by inspecting
    // file paths. E2e files are written to `{output}/{lang}/...`, so the
    // first path component after the output prefix is the language name.
    let output_prefix = Path::new(e2e_config.effective_output());
    let languages: HashSet<String> = files
        .iter()
        .filter_map(|f| {
            let remainder = f.path.strip_prefix(output_prefix).ok()?;
            let first = remainder.components().next()?;
            Some(first.as_os_str().to_string_lossy().into_owned())
        })
        .collect();

    for (lang, cmd_template) in &e2e_config.format {
        if !languages.contains(lang.as_str()) {
            continue;
        }

        let dir = format!("{}/{}", e2e_config.effective_output(), lang);
        let cmd = cmd_template.replace("{dir}", &dir);

        eprintln!("  Formatting {lang}: {cmd}");
        let status = std::process::Command::new("sh").args(["-c", &cmd]).status();

        match status {
            Ok(s) if s.success() => {}
            Ok(s) => {
                warn!("Formatter for {lang} exited with {s}: {cmd}");
            }
            Err(e) => {
                warn!("Failed to run formatter for {lang}: {e}");
            }
        }
    }
}