use std::fs::{OpenOptions, TryLockError};
use anyhow::{Context, Result, bail};
use ryra_core::config::ConfigPaths;
#[must_use = "binding the lock to `_` drops it immediately and locks nothing"]
pub struct MutationLock(#[allow(dead_code)] std::fs::File);
impl MutationLock {
pub fn acquire(dry_run: bool) -> Result<Option<Self>> {
if dry_run {
return Ok(None);
}
let paths = ConfigPaths::resolve()?;
paths.ensure_dirs()?;
let path = paths.config_dir.join(".ryra.lock");
let file = OpenOptions::new()
.create(true)
.truncate(false)
.write(true)
.open(&path)
.with_context(|| format!("open {}", path.display()))?;
match file.try_lock() {
Ok(()) => Ok(Some(Self(file))),
Err(TryLockError::WouldBlock) => {
bail!("another ryra operation is already running — wait for it to finish and retry")
}
Err(TryLockError::Error(e)) => {
Err(e).with_context(|| format!("lock {}", path.display()))
}
}
}
}