args-cli 0.1.1

Command-line interface for args
Documentation
use itertools::Either;
use tombi_config::TomlVersion;
use tombi_diagnostic::printer::{Pretty, Print};
use tombi_linter::{LintOptions, Linter};
use tombi_schema_store::SchemaStore;

use args_config::ci::CiConfig;

pub async fn lint() -> anyhow::Result<()> {
    let config_path = crate::util::ci::find_config().await?;
    if !config_path.exists() {
        anyhow::bail!(
            "{} not found. Run `args ci init` to create one.",
            config_path.display()
        );
    }
    let source = tokio::fs::read_to_string(&config_path).await?;

    toml_lint(&config_path, &source).await?;
    semantic_lint(&config_path, &source)?;

    println!("{}: no issues found", config_path.display());
    Ok(())
}

async fn toml_lint(config_path: &std::path::Path, source: &str) -> anyhow::Result<()> {
    let schema_store = SchemaStore::new();
    let options = LintOptions::default();
    let linter = Linter::new(
        TomlVersion::V1_1_0,
        &options,
        Some(Either::Right(config_path)),
        &schema_store,
    );

    if let Err(diagnostics) = linter.lint(source).await {
        let mut printer = Pretty::default();
        for d in &diagnostics {
            d.clone().with_source_file(config_path).print(&mut printer);
        }
        anyhow::bail!(
            "{}: {} issue(s) found",
            config_path.display(),
            diagnostics.len()
        );
    }

    Ok(())
}

fn semantic_lint(config_path: &std::path::Path, source: &str) -> anyhow::Result<()> {
    CiConfig::new(source).map_err(|e| anyhow::anyhow!("{}: {e}", config_path.display()))?;

    Ok(())
}