//! This file is copy-pasted directly from the pijul source code
use std::path::PathBuf;
use anyhow::bail;
use libpijul::DOT_DIR;
use log::debug;
pub fn current_dir() -> Result<PathBuf, anyhow::Error> {
if let Ok(cur) = std::env::current_dir() {
Ok(cur)
} else {
bail!("Cannot access working directory")
}
}
pub struct Repository {
pub pristine: libpijul::pristine::sanakirja::Pristine,
pub changes: libpijul::changestore::filesystem::FileSystem,
pub working_copy: libpijul::working_copy::filesystem::FileSystem,
//pub config: config::Config,
pub path: PathBuf,
pub changes_dir: PathBuf,
}
pub const PRISTINE_DIR: &str = "pristine";
pub const CHANGES_DIR: &str = "changes";
//pub const CONFIG_FILE: &str = "config";
#[cfg(unix)]
pub fn max_files() -> usize {
let n = if let Ok((n, _)) = rlimit::getrlimit(rlimit::Resource::NOFILE) {
(n as usize / (2 * num_cpus::get())).max(1)
} else {
256
};
debug!("max_files = {:?}", n);
n
}
#[cfg(not(unix))]
pub fn max_files() -> usize {
1
}
impl Repository {
fn find_root_(cur: Option<PathBuf>, dot_dir: &str) -> 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 {
bail!("No Pijul repository found")
}
} else {
break;
}
}
Ok(cur)
}
pub fn find_root(cur: Option<PathBuf>) -> Result<Self, anyhow::Error> {
Self::find_root_with_dot_dir(cur, DOT_DIR)
}
pub fn find_root_with_dot_dir(
cur: Option<PathBuf>,
dot_dir: &str,
) -> Result<Self, anyhow::Error> {
let cur = Self::find_root_(cur, dot_dir)?;
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_path = cur.join(CONFIG_FILE);
// let config = if let Ok(config) = std::fs::read(&config_path) {
// if let Ok(toml) = toml::from_slice(&config) {
// toml
// } else {
// bail!("Could not read configuration file at {:?}", config_path)
// }
// } else {
// config::Config::default()
// };
Ok(Repository {
pristine: libpijul::pristine::sanakirja::Pristine::new(&pristine_dir.join("db"))?,
working_copy: libpijul::working_copy::filesystem::FileSystem::from_root(
&working_copy_dir,
),
changes: libpijul::changestore::filesystem::FileSystem::from_root(
&working_copy_dir,
crate::repository::max_files(),
),
//config,
path: working_copy_dir,
changes_dir,
})
}
// pub fn update_config(&self) -> Result<(), anyhow::Error> {
// std::fs::write(
// self.path.join(DOT_DIR).join("config"),
// toml::to_string(&self.config)?,
// )?;
// Ok(())
// }
}
fn init_default_config(path: &std::path::Path, remote: Option<&str>) -> Result<(), anyhow::Error> {
use std::io::Write;
let mut path = path.join(DOT_DIR);
path.push("config");
if std::fs::metadata(&path).is_err() {
let mut f = std::fs::File::create(&path)?;
if let Some(rem) = remote {
writeln!(f, "default_remote = {:?}", rem)?;
}
writeln!(f, "[hooks]\nrecord = []")?;
}
Ok(())
}