uvm-install2 0.13.0

Install specified unity version.
Documentation
use log::{debug, error};
use std::fs;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
pub type InstallerPath = PathBuf;
pub type InstallDestination = PathBuf;
pub type Rename = Option<(PathBuf, PathBuf)>;
#[cfg(windows)]
pub type Cmd = String;
#[cfg(windows)]
pub type OptionalCmd = Option<String>;

pub type BaseInstaller = (InstallerPath, (), (), Rename);
pub type InstallerWithDestination = (InstallerPath, InstallDestination, (), Rename);

#[cfg(windows)]
pub type InstallerWithDestinationAndOptionalCommand =
    (InstallerPath, InstallDestination, OptionalCmd, Rename);
#[cfg(windows)]
pub type InstallerWithCommand = (InstallerPath, (), Cmd, Rename);
#[cfg(windows)]
pub type InstallerWithOptionalCommand = (InstallerPath, (), OptionalCmd, Rename);

mod pkg;
mod po;
mod zip;

pub use self::pkg::*;
pub use self::po::*;
pub use self::zip::*;

pub struct Installer<V, T, I> {
    _variant: PhantomData<V>,
    _installer_type: PhantomData<T>,
    inner: I,
}

impl<V, T, X, Y> Installer<V, T, (InstallerPath, X, Y, Rename)> {
    pub fn installer(&self) -> &Path {
        &self.inner.0
    }

    pub fn rename(&self) -> Option<(&Path, &Path)> {
        self.inner
            .3
            .as_ref()
            .map(|(f, t)| (f.as_path(), t.as_path()))
    }
}

impl<V, T, X, Y, Z> Installer<V, T, (X, InstallDestination, Y, Z)> {
    pub fn destination(&self) -> &Path {
        &self.inner.1
    }
}

#[cfg(windows)]
impl<V, T, X, Y, Z> Installer<V, T, (X, Y, Cmd, Z)> {
    pub fn cmd(&self) -> &String {
        &self.inner.2
    }
}

#[cfg(windows)]
impl<V, T, X, Y, Z> Installer<V, T, (X, Y, OptionalCmd, Z)> {
    pub fn cmd(&self) -> Option<&String> {
        self.inner.2.as_ref()
    }
}

impl<V, T> Installer<V, T, InstallerWithDestination> {
    pub fn new<P, D, R>(installer: P, destination: D, rename: Option<(R, R)>) -> Self
    where
        P: AsRef<Path>,
        D: AsRef<Path>,
        R: AsRef<Path>,
    {
        let installer = installer.as_ref().to_path_buf();
        let destination = destination.as_ref().to_path_buf();
        let rename = rename.map(|(f, t)| (f.as_ref().to_path_buf(), t.as_ref().to_path_buf()));

        Installer {
            _variant: PhantomData,
            _installer_type: PhantomData,
            inner: (installer, destination, (), rename),
        }
    }
}

#[cfg(windows)]
impl<V, T> Installer<V, T, InstallerWithDestinationAndOptionalCommand> {
    pub fn new<P, D, R>(
        installer: P,
        destination: D,
        cmd: Option<String>,
        rename: Option<(R, R)>,
    ) -> Self
    where
        P: AsRef<Path>,
        D: AsRef<Path>,
        R: AsRef<Path>,
    {
        let installer = installer.as_ref().to_path_buf();
        let destination = destination.as_ref().to_path_buf();
        let rename = rename.map(|(f, t)| (f.as_ref().to_path_buf(), t.as_ref().to_path_buf()));
        let cmd = cmd;

        Installer {
            _variant: PhantomData,
            _installer_type: PhantomData,
            inner: (installer, destination, cmd, rename),
        }
    }
}

#[cfg(windows)]
impl<V, T> Installer<V, T, InstallerWithCommand> {
    pub fn new<P, R>(installer: P, cmd: String, rename: Option<(R, R)>) -> Self
    where
        P: AsRef<Path>,
        R: AsRef<Path>,
    {
        let installer = installer.as_ref().to_path_buf();
        let cmd = cmd;
        let rename = rename.map(|(f, t)| (f.as_ref().to_path_buf(), t.as_ref().to_path_buf()));

        Installer {
            _variant: PhantomData,
            _installer_type: PhantomData,
            inner: (installer, (), cmd, rename),
        }
    }
}

#[cfg(windows)]
impl<V, T> Installer<V, T, InstallerWithOptionalCommand> {
    pub fn new<P, R>(installer: P, cmd: Option<String>, rename: Option<(R, R)>) -> Self
    where
        P: AsRef<Path>,
        R: AsRef<Path>,
    {
        let installer = installer.as_ref().to_path_buf();
        let cmd = cmd;
        let rename = rename.map(|(f, t)| (f.as_ref().to_path_buf(), t.as_ref().to_path_buf()));

        Installer {
            _variant: PhantomData,
            _installer_type: PhantomData,
            inner: (installer, (), cmd, rename),
        }
    }
}

impl<V, T> Installer<V, T, BaseInstaller> {
    pub fn new<P, R>(installer: P, rename: Option<(R, R)>) -> Self
    where
        P: AsRef<Path>,
        R: AsRef<Path>,
    {
        let installer = installer.as_ref().to_path_buf();
        let rename = rename.map(|(f, t)| (f.as_ref().to_path_buf(), t.as_ref().to_path_buf()));

        Installer {
            _variant: PhantomData,
            _installer_type: PhantomData,
            inner: (installer, (), (), rename),
        }
    }
}

impl<V, T, I> Installer<V, T, I> {
    pub fn cleanup_file_failable<P: AsRef<Path>>(&self, file: P) {
        let file = file.as_ref();
        if file.exists() && file.is_file() {
            debug!("cleanup file {}", &file.display());
            fs::remove_file(file).unwrap_or_else(|err| {
                error!("failed to cleanup file {}", &file.display());
                error!("{}", err);
            });
        }
    }

    pub fn cleanup_directory_failable<P: AsRef<Path>>(&self, dir: P) {
        let dir = dir.as_ref();
        if dir.exists() && dir.is_dir() {
            debug!("cleanup directory {}", dir.display());
            fs::remove_dir_all(dir).unwrap_or_else(|err| {
                error!("failed to cleanup directory {}", dir.display());
                error!("{}", err);
            })
        }
    }
}