use crate::crypto::CryptoKey;
use crate::error::{GitCryptError, Result};
use git2::Repository;
use std::io::{self, Read, Write};
use std::path::Path;
pub struct GitRepo {
repo: Repository,
}
impl GitRepo {
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
let repo = Repository::discover(path).map_err(|_| GitCryptError::NotInGitRepo)?;
Ok(Self { repo })
}
pub fn git_dir(&self) -> &Path {
self.repo.path()
}
pub fn configure_filters(&self) -> Result<()> {
let mut config = self.repo.config()?;
config.set_str("filter.git-crypt.clean", "git-crypt clean")?;
config.set_str("filter.git-crypt.smudge", "git-crypt smudge")?;
config.set_str("filter.git-crypt.diff", "git-crypt diff")?;
config.set_bool("filter.git-crypt.required", true)?;
Ok(())
}
pub fn remove_filters(&self) -> Result<()> {
let mut config = self.repo.config()?;
let _ = config.remove("filter.git-crypt.clean");
let _ = config.remove("filter.git-crypt.smudge");
let _ = config.remove("filter.git-crypt.diff");
let _ = config.remove("filter.git-crypt.required");
Ok(())
}
#[allow(dead_code)]
pub fn workdir(&self) -> Result<&Path> {
self.repo.workdir().ok_or(GitCryptError::Other(
"Repository has no working directory".into(),
))
}
}
pub fn clean_filter(key: &CryptoKey) -> Result<()> {
let mut input = Vec::new();
io::stdin().read_to_end(&mut input)?;
if CryptoKey::is_encrypted(&input) {
io::stdout().write_all(&input)?;
return Ok(());
}
let encrypted = key.encrypt(&input)?;
io::stdout().write_all(&encrypted)?;
Ok(())
}
pub fn smudge_filter(key: &CryptoKey) -> Result<()> {
let mut input = Vec::new();
io::stdin().read_to_end(&mut input)?;
if !CryptoKey::is_encrypted(&input) {
io::stdout().write_all(&input)?;
return Ok(());
}
let decrypted = key.decrypt(&input)?;
io::stdout().write_all(&decrypted)?;
Ok(())
}
pub fn diff_filter() -> Result<()> {
let mut input = Vec::new();
io::stdin().read_to_end(&mut input)?;
if CryptoKey::is_encrypted(&input) {
writeln!(
io::stdout(),
"*** This file is encrypted with git-crypt ***"
)?;
} else {
io::stdout().write_all(&input)?;
}
Ok(())
}