use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Mutex, MutexGuard};
static WORKTREE_METADATA_PROBE: AtomicUsize = AtomicUsize::new(0); static WORKTREE_READ_DIR_PROBE: AtomicUsize = AtomicUsize::new(0); static WORKTREE_PATH_RESOLVE_PROBE: AtomicUsize = AtomicUsize::new(0); static WORKTREE_PROBE_ACTIVE: AtomicUsize = AtomicUsize::new(0); static WORKTREE_PROBE_ROOT: Mutex<Option<PathBuf>> = Mutex::new(None); static WORKTREE_PROBE_SERIAL: Mutex<()> = Mutex::new(());
pub struct WorktreeProbeScope {
_serial: MutexGuard<'static, ()>,
}
impl Drop for WorktreeProbeScope {
fn drop(&mut self) {
*WORKTREE_PROBE_ROOT
.lock()
.unwrap_or_else(|e| e.into_inner()) = None;
WORKTREE_PROBE_ACTIVE.store(0, Ordering::Release);
}
}
fn probe_counts(path: &Path) -> bool {
if WORKTREE_PROBE_ACTIVE.load(Ordering::Acquire) == 0 {
return false;
}
WORKTREE_PROBE_ROOT
.lock()
.unwrap_or_else(|e| e.into_inner())
.as_deref()
.is_some_and(|root| path.starts_with(root))
}
pub fn reset_worktree_metadata_probe(root: &Path) -> WorktreeProbeScope {
let serial = WORKTREE_PROBE_SERIAL
.lock()
.unwrap_or_else(|e| e.into_inner());
*WORKTREE_PROBE_ROOT
.lock()
.unwrap_or_else(|e| e.into_inner()) = Some(root.to_path_buf());
WORKTREE_METADATA_PROBE.store(0, Ordering::Relaxed);
WORKTREE_READ_DIR_PROBE.store(0, Ordering::Relaxed);
WORKTREE_PATH_RESOLVE_PROBE.store(0, Ordering::Relaxed);
WORKTREE_PROBE_ACTIVE.store(1, Ordering::Release);
WorktreeProbeScope { _serial: serial }
}
pub fn worktree_metadata_probe_count() -> usize {
WORKTREE_METADATA_PROBE.load(Ordering::Relaxed)
}
pub fn worktree_read_dir_probe_count() -> usize {
WORKTREE_READ_DIR_PROBE.load(Ordering::Relaxed)
}
pub fn worktree_path_resolve_probe_count() -> usize {
WORKTREE_PATH_RESOLVE_PROBE.load(Ordering::Relaxed)
}
pub(crate) fn record_metadata(path: &Path) {
if probe_counts(path) {
WORKTREE_METADATA_PROBE.fetch_add(1, Ordering::Relaxed);
}
}
pub(crate) fn record_read_dir(path: &Path) {
if probe_counts(path) {
WORKTREE_READ_DIR_PROBE.fetch_add(1, Ordering::Relaxed);
}
}
pub(crate) fn record_path_resolve(path: &Path) {
if probe_counts(path) {
WORKTREE_PATH_RESOLVE_PROBE.fetch_add(1, Ordering::Relaxed);
}
}