use crate::{config, current_dir, Error};
use libanu::DOT_DIR;
use std::io::Write;
use std::path::PathBuf;
pub struct Repository {
pub pristine: libanu::pristine::sanakirja::Pristine,
pub changes: libanu::changestore::filesystem::FileSystem,
pub working_copy: libanu::working_copy::filesystem::FileSystem,
pub config: config::Config,
pub path: PathBuf,
pub changes_dir: PathBuf,
}
pub const PRISTINE_DIR: &'static str = "pristine";
pub const CHANGES_DIR: &'static str = "changes";
pub const CONFIG_FILE: &'static str = "config";
impl Repository {
pub fn save_config(&self) -> Result<(), anyhow::Error> {
let config = toml::to_string(&self.config)?;
let mut file = std::fs::File::create(&self.path.join(DOT_DIR).join(CONFIG_FILE))?;
file.write_all(config.as_bytes())?;
Ok(())
}
fn find_root_(cur: Option<PathBuf>) -> Result<PathBuf, anyhow::Error> {
let mut cur = if let Some(cur) = cur {
cur
} else {
current_dir()?
};
cur.push(DOT_DIR);
loop {
debug!("{:?}", cur);
if std::fs::metadata(&cur).is_err() {
cur.pop();
if cur.pop() {
cur.push(DOT_DIR);
} else {
return Err(Error::NoRepoRoot.into());
}
} else {
break;
}
}
Ok(cur)
}
pub fn find_root(cur: Option<PathBuf>) -> Result<Self, anyhow::Error> {
let cur = Self::find_root_(cur)?;
let mut pristine_dir = cur.clone();
pristine_dir.push(PRISTINE_DIR);
let mut changes_dir = cur.clone();
changes_dir.push(CHANGES_DIR);
let mut working_copy_dir = cur.clone();
working_copy_dir.pop();
let config = if let Ok(config) = std::fs::read(&cur.join(CONFIG_FILE)) {
toml::from_slice(&config)?
} else {
config::Config::default()
};
Ok(Repository {
pristine: libanu::pristine::sanakirja::Pristine::new(&pristine_dir)?,
working_copy: libanu::working_copy::filesystem::FileSystem::from_root(
&working_copy_dir,
),
changes: libanu::changestore::filesystem::FileSystem::from_root(&working_copy_dir),
config,
path: working_copy_dir,
changes_dir,
})
}
pub fn init(path: Option<std::path::PathBuf>) -> Result<Self, anyhow::Error> {
let cur = if let Some(path) = path {
path
} else {
current_dir()?
};
let mut pristine_dir = cur.clone();
pristine_dir.push(DOT_DIR);
pristine_dir.push(PRISTINE_DIR);
if std::fs::metadata(&pristine_dir).is_err() {
std::fs::create_dir_all(&pristine_dir)?;
let mut changes_dir = cur.clone();
changes_dir.push(DOT_DIR);
changes_dir.push(CHANGES_DIR);
Ok(Repository {
pristine: libanu::pristine::sanakirja::Pristine::new(&pristine_dir)?,
working_copy: libanu::working_copy::filesystem::FileSystem::from_root(&cur),
changes: libanu::changestore::filesystem::FileSystem::from_root(&cur),
config: config::Config::default(),
path: cur,
changes_dir,
})
} else {
Err(Error::AlreadyInARepo.into())
}
}
}