use std::fs;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use libpijul::MutTxnT;
use pijul_repository::Repository;
use tempfile::TempDir;
const IDENTITY_TOML: &str = include_str!("fixtures/identity.toml");
const SECRET_KEY_JSON: &str = include_str!("fixtures/secret_key.json");
pub struct RepoFixture {
temp_dir: TempDir,
identity_name: String,
}
impl RepoFixture {
pub fn new() -> Result<Self> {
let temp_dir = TempDir::new().context("failed to create temp dir")?;
let fixture = Self {
temp_dir,
identity_name: "test".to_string(),
};
fixture.prepare_dirs()?;
fixture.write_identity_files()?;
fixture.init_repo()?;
Ok(fixture)
}
pub fn repo_root(&self) -> &Path {
self.temp_dir.path()
}
pub fn home_dir(&self) -> &Path {
self.temp_dir.path()
}
pub fn xdg_config_home(&self) -> PathBuf {
self.temp_dir.path().join(".config")
}
pub fn xdg_data_home(&self) -> PathBuf {
self.temp_dir.path().join(".local").join("share")
}
pub fn identity_dir(&self) -> PathBuf {
self.xdg_config_home()
.join("pijul")
.join("identities")
.join(&self.identity_name)
}
pub fn pristine_db_path(&self) -> PathBuf {
self.repo_root().join(".pijul").join("pristine").join("db")
}
pub fn apply_env(&self, cmd: &mut std::process::Command) {
cmd.env("HOME", self.home_dir())
.env("XDG_CONFIG_HOME", self.xdg_config_home())
.env("XDG_DATA_HOME", self.xdg_data_home());
}
pub fn write_file(&self, rel: &str, contents: &str) -> Result<()> {
let path = self.repo_root().join(rel);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)
.with_context(|| format!("failed to create parent dirs for {}", path.display()))?;
}
fs::write(&path, contents)
.with_context(|| format!("failed to write {}", path.display()))?;
Ok(())
}
fn prepare_dirs(&self) -> Result<()> {
fs::create_dir_all(self.identity_dir())
.with_context(|| format!("failed to create {}", self.identity_dir().display()))?;
fs::create_dir_all(self.xdg_data_home().join("pijul")).with_context(|| {
format!(
"failed to create {}",
self.xdg_data_home().join("pijul").display()
)
})?;
Ok(())
}
fn write_identity_files(&self) -> Result<()> {
let identity_toml_path = self.identity_dir().join("identity.toml");
let secret_key_json_path = self.identity_dir().join("secret_key.json");
fs::write(&identity_toml_path, IDENTITY_TOML)
.with_context(|| format!("failed to write {}", identity_toml_path.display()))?;
fs::write(&secret_key_json_path, SECRET_KEY_JSON)
.with_context(|| format!("failed to write {}", secret_key_json_path.display()))?;
Ok(())
}
fn init_repo(&self) -> Result<()> {
let repo = Repository::init(Some(self.repo_root().to_path_buf()), None, None)
.context("failed to initialize repository")?;
let mut txn = repo
.pristine
.mut_txn_begin()
.context("failed to open pristine mut txn")?;
txn.open_or_create_channel("main")
.context("failed to create main channel")?;
txn.commit().context("failed to commit pristine txn")?;
anyhow::ensure!(
self.pristine_db_path().exists(),
"expected pristine db at {}",
self.pristine_db_path().display()
);
Ok(())
}
}