use std::path::{Path, PathBuf};
use std::sync::Arc;
use cageforge_policy::{PathPattern, PathResolutionContext, PathSelector};
#[derive(Debug, Clone)]
pub(crate) struct ContextIdentity(Arc<()>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EffectivePathContext {
context: PathResolutionContext,
identity: ContextIdentity,
}
impl ContextIdentity {
pub(crate) fn new() -> Self {
Self(Arc::new(()))
}
fn matches(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl PartialEq for ContextIdentity {
fn eq(&self, other: &Self) -> bool {
self.matches(other)
}
}
impl Eq for ContextIdentity {}
impl EffectivePathContext {
pub(crate) fn new(context: PathResolutionContext, identity: ContextIdentity) -> Self {
Self { context, identity }
}
pub fn workspace_roots(&self) -> &[PathBuf] {
self.context.workspace_roots()
}
pub fn root_paths(&self) -> &[PathBuf] {
self.context.root_paths()
}
pub fn minimal_paths(&self) -> &[PathBuf] {
self.context.minimal_paths()
}
pub fn executable_roots(&self) -> &[PathBuf] {
self.context.executable_roots()
}
pub fn tmpdir(&self) -> Option<&std::path::Path> {
self.context.tmpdir()
}
pub fn slash_tmp(&self) -> Option<&std::path::Path> {
self.context.slash_tmp()
}
pub fn current_directory(&self) -> Option<&Path> {
self.context.current_directory()
}
pub fn resolve(&self, selector: &PathSelector) -> Vec<PathBuf> {
selector.resolve(&self.context)
}
pub fn glob_search_roots(&self, pattern: &PathPattern) -> Vec<PathBuf> {
let prefix = pattern.literal_prefix();
if pattern.is_absolute() {
vec![prefix]
} else {
self.context
.workspace_roots()
.iter()
.map(|root| root.join(&prefix))
.collect()
}
}
pub fn pattern_matches(&self, pattern: &PathPattern, path: &Path) -> bool {
pattern.matches_path(path, &self.context)
}
pub(crate) fn belongs_to(&self, identity: &ContextIdentity) -> bool {
self.identity.matches(identity)
}
pub(crate) fn raw(&self) -> &PathResolutionContext {
&self.context
}
}