veryl-metadata 0.2.2

A modern hardware description language
Documentation
use crate::metadata_error::MetadataError;
use log::info;
use std::path::{Path, PathBuf};
use std::process::Command;
use url::Url;

pub struct Git {
    rev: Option<String>,
    tag: Option<String>,
    branch: Option<String>,
    path: PathBuf,
}

impl Git {
    pub fn clone(
        url: &Url,
        path: &Path,
        rev: Option<&str>,
        tag: Option<&str>,
        branch: Option<&str>,
    ) -> Result<Self, MetadataError> {
        let current_dir = path.parent().unwrap();
        let target = path.file_name().unwrap();
        if !path.exists() {
            let output = Command::new("git")
                .arg("clone")
                .arg(url.as_str())
                .arg(target)
                .current_dir(current_dir)
                .output()?;
            if !output.status.success() {
                let context = String::from_utf8_lossy(&output.stderr).to_string();
                let msg = format!("failed to clone repository: {}", url.as_str());
                return Err(MetadataError::Git { msg, context });
            }
            info!("Cloned repository ({})", url);
        }

        Ok(Git {
            path: path.to_path_buf(),
            rev: rev.map(|x| x.to_owned()),
            tag: tag.map(|x| x.to_owned()),
            branch: branch.map(|x| x.to_owned()),
        })
    }

    pub fn fetch(&self) -> Result<(), MetadataError> {
        let output = Command::new("git")
            .arg("fetch")
            .current_dir(&self.path)
            .output()?;
        if !output.status.success() {
            let context = String::from_utf8_lossy(&output.stderr).to_string();
            let msg = format!(
                "failed to fetch repository: {}",
                self.path.to_string_lossy()
            );
            return Err(MetadataError::Git { msg, context });
        }

        info!("Fetched repository ({})", self.path.to_string_lossy());

        Ok(())
    }

    pub fn checkout(&self) -> Result<(), MetadataError> {
        let dst = if let Some(ref rev) = self.rev {
            rev.to_string()
        } else if let Some(ref tag) = self.tag {
            tag.to_string()
        } else if let Some(ref branch) = self.branch {
            format!("origin/{}", branch)
        } else {
            "origin/HEAD".to_string()
        };

        let output = Command::new("git")
            .arg("checkout")
            .arg(&dst)
            .current_dir(&self.path)
            .output()?;
        if !output.status.success() {
            let context = String::from_utf8_lossy(&output.stderr).to_string();
            let msg = format!(
                "failed to checkout repository: {}",
                self.path.to_string_lossy()
            );
            return Err(MetadataError::Git { msg, context });
        }

        info!(
            "Checkouted repository ({} @ {})",
            self.path.to_string_lossy(),
            dst
        );

        Ok(())
    }
}