use anyhow::{Context, Result};
use std::fs::{self, File};
use std::path::Path;
use vtcode_commons::VtCodePaths;
use super::time::modified_age_secs;
pub(crate) fn acquire_lock_file(lock_path: &Path, max_age_secs: u64) -> Result<Option<File>> {
if let Some(parent) = lock_path.parent() {
VtCodePaths::ensure_user_dir(parent).with_context(|| format!("Failed to create {}", parent.display()))?;
}
if let Some(file) = try_create_new_lock_file(lock_path)? {
return Ok(Some(file));
}
if !lock_is_active(lock_path, max_age_secs) {
let _ = fs::remove_file(lock_path);
return try_create_new_lock_file(lock_path);
}
Ok(None)
}
fn try_create_new_lock_file(lock_path: &Path) -> Result<Option<File>> {
match VtCodePaths::create_private_file(lock_path) {
Ok(file) => Ok(Some(file)),
Err(err)
if err
.downcast_ref::<std::io::Error>()
.is_some_and(|error| error.kind() == std::io::ErrorKind::AlreadyExists) =>
{
Ok(None)
}
Err(err) => Err(err).with_context(|| format!("Failed to create lock file {}", lock_path.display())),
}
}
pub(crate) fn lock_is_active(lock_path: &Path, max_age_secs: u64) -> bool {
modified_age_secs(lock_path).is_some_and(|age| age < max_age_secs)
}