dotter 0.12.14

A dotfile manager and templater written in rust
use anyhow::{Context, Result};
use handlebars::Handlebars;

use std::path::Path;
use std::process::Child;
use std::process::Command;

pub(crate) fn run_hook(
    location: &Path,
    cache_dir: &Path,
    handlebars: &Handlebars,
    variables: &crate::config::Variables,
) -> Result<()> {
    if !location.exists() {
        debug!("Hook file at {:?} missing", location);
        return Ok(());
    }

    let mut script_file = cache_dir.join(location);
    let mut target = std::env::temp_dir().join("dotter_temp");
    if cfg!(windows) {
        script_file.set_extension("bat");
        target.set_extension("bat");
    }
    debug!("Rendering script {:?} -> {:?}", location, script_file);

    crate::actions::perform_template_deploy(
        location,
        &script_file,
        &target.clone().into(),
        &mut crate::filesystem::RealFilesystem::new(false),
        handlebars,
        variables,
    )
    .context("deploy script")?;

    debug!("Running script file");
    let mut child = run_script_file(&target)?;

    anyhow::ensure!(
        child.wait().context("wait for child shell")?.success(),
        "subshell returned error"
    );

    Ok(())
}

#[cfg(unix)]
fn run_script_file(script: &Path) -> Result<Child> {
    use std::os::unix::fs::PermissionsExt;

    let permissions = script.metadata()?.permissions();
    if !script.is_dir() && permissions.mode() & 0o111 != 0 {
        Command::new(script).spawn().context("spawn script file")
    } else {
        Command::new("sh")
            .arg(script)
            .spawn()
            .context("spawn shell")
    }
}

#[cfg(windows)]
fn run_script_file(script: &Path) -> Result<Child> {
    Command::new(script).spawn().context("spawn batch file")
}