use std::fs::{File, OpenOptions, TryLockError};
use std::path::{Path, PathBuf};
pub const ALREADY_RUNNING: &str =
"playr is already running, in a terminal, a window or a server; quit it first";
#[derive(Debug)]
pub struct Instance {
_lock: Option<File>,
}
pub fn lock_path() -> PathBuf {
playr_core::db::default_path().with_file_name("instance.lock")
}
pub fn claim() -> Result<Instance, String> {
claim_at(&lock_path())
}
pub fn claim_at(path: &Path) -> Result<Instance, String> {
if let Some(dir) = path.parent() {
let _ = std::fs::create_dir_all(dir);
}
let file = OpenOptions::new()
.create(true)
.truncate(false)
.write(true)
.open(path);
let Ok(file) = file else {
return Ok(Instance { _lock: None });
};
match file.try_lock() {
Ok(()) => Ok(Instance { _lock: Some(file) }),
Err(TryLockError::WouldBlock) => Err(ALREADY_RUNNING.into()),
Err(TryLockError::Error(_)) => Ok(Instance { _lock: None }),
}
}