use std::collections::BTreeMap;
use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::{git_util, hook};
#[derive(Serialize, Deserialize, Clone, PartialEq, Default)]
pub struct Project {
pub remote: String,
pub branch: String,
pub configuration: BTreeMap<String, String>,
pub hooks: BTreeMap<String, String>,
}
pub struct ProjectOpts {
pub branch: Option<String>,
pub configuration: BTreeMap<String, String>,
pub hook: Option<String>,
}
impl Project {
pub fn new(
remote: &str,
branch: &str,
configuration: BTreeMap<String, String>,
hooks: BTreeMap<String, String>,
) -> Self {
Project {
remote: remote.to_string(),
branch: branch.to_string(),
configuration,
hooks,
}
}
pub fn empty(remote: &str) -> Self {
Project::new(remote, "", BTreeMap::new(), BTreeMap::new())
}
pub fn configure<P: AsRef<Path>>(
&mut self,
repo: &git2::Repository,
options: &ProjectOpts,
config_dir: P,
) -> anyhow::Result<()> {
if let Some(branch) = &options.branch {
if *branch != self.branch {
repo.set_head(&format!("refs/heads/{}", branch))?;
self.branch = branch.clone();
}
}
if !options.configuration.is_empty() {
self.configuration.clear();
let mut repo_config = repo.config()?;
for (key, value) in &options.configuration {
repo_config.set_str(key.as_str(), value.as_str())?;
self.configuration.insert(key.clone(), value.clone());
}
}
if let Some(hook) = &options.hook {
hook::install(hook, repo.path(), config_dir)?;
self.hooks.insert("pre-commit".to_string(), hook.clone());
}
Ok(())
}
}
impl From<git2::Repository> for Project {
fn from(repo: git2::Repository) -> Self {
let mut project = Project::default();
if let Ok(remote) = repo.find_remote("origin") {
project.remote = remote.name().unwrap().to_string();
}
if let Some(branch) = git_util::get_active_branch(&repo).unwrap() {
project.branch = branch;
}
let config = repo.config().unwrap().snapshot().unwrap();
for entry in &config.entries(None).unwrap() {
let entry = entry.unwrap();
project.configuration.insert(
entry.name().unwrap().to_string(),
entry.value().unwrap().to_string(),
);
}
project
}
}
impl ProjectOpts {
pub fn new(
branch: Option<&str>,
configuration: BTreeMap<String, String>,
hook: Option<&str>,
) -> Self {
ProjectOpts {
branch: branch.map(String::from),
configuration,
hook: hook.map(String::from),
}
}
}
impl From<Project> for ProjectOpts {
fn from(p: Project) -> Self {
ProjectOpts {
branch: Some(p.branch),
configuration: p.configuration,
hook: p.hooks.get("pre-commit").cloned(),
}
}
}