simit 0.17.7

Semver-aware git commit helper for Rust projects
Documentation
use std::fs;
use std::path::Path;

use anyhow::{Context, Result};

use crate::cargo;
use crate::cli::{CoprAction, CoprCommand, CoprRenderArgs};
use crate::config::{CoprOverrides, ProjectConfig, ResolvedCopr};
use crate::render::{copr_makefile, rpm_spec};

pub const MAKEFILE_PATH: &str = ".copr/Makefile";

pub fn run(command: CoprCommand) -> Result<()> {
    match command.action {
        CoprAction::Render(args) => render(args),
    }
}

fn render(args: CoprRenderArgs) -> Result<()> {
    let (resolved, package_version) = resolve(args.copr.as_overrides(), args.package.as_deref())?;
    let version = args.version.as_deref().unwrap_or(&package_version);
    let rendered = render_files(&resolved, version);
    println!("==> {}", resolved.spec_path);
    print!("{}", rendered.spec);
    println!("==> {MAKEFILE_PATH}");
    print!("{}", rendered.makefile);
    Ok(())
}

pub(crate) fn resolve(
    overrides: CoprOverrides<'_>,
    package: Option<&str>,
) -> Result<(ResolvedCopr, String)> {
    let metadata = cargo::metadata_for_current_dir()?;
    let workspace_root = metadata.workspace_root.as_std_path();
    let pkg = cargo::representative_package(&metadata, package)?;
    let cfg = ProjectConfig::load(workspace_root)?;
    let resolved = cfg.resolve_copr(overrides, &pkg)?;
    Ok((resolved, pkg.version))
}

pub(crate) struct RenderedCopr {
    pub spec: String,
    pub makefile: String,
}

pub(crate) fn render_files(resolved: &ResolvedCopr, version: &str) -> RenderedCopr {
    RenderedCopr {
        spec: rpm_spec::render_spec(resolved, version),
        makefile: copr_makefile::render_makefile(resolved),
    }
}

pub(crate) fn write_files(
    workspace_root: &Path,
    resolved: &ResolvedCopr,
    rendered: &RenderedCopr,
) -> Result<()> {
    let spec_path = workspace_root.join(&resolved.spec_path);
    if let Some(parent) = spec_path.parent() {
        fs::create_dir_all(parent).with_context(|| format!("creating {}", parent.display()))?;
    }
    fs::write(&spec_path, &rendered.spec)
        .with_context(|| format!("writing {}", spec_path.display()))?;

    let makefile_path = workspace_root.join(MAKEFILE_PATH);
    if let Some(parent) = makefile_path.parent() {
        fs::create_dir_all(parent).with_context(|| format!("creating {}", parent.display()))?;
    }
    fs::write(&makefile_path, &rendered.makefile)
        .with_context(|| format!("writing {}", makefile_path.display()))?;
    Ok(())
}